From fcc4c9b34a6ab771c9cef6673e817866773e12d0 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 18 Jan 2023 16:20:52 +0100 Subject: Change domain block CSV parsing to be more robust and handle more lists (#21470) * Change domain block CSV parsing to be more robust and handle more lists * Add some tests * Improve domain block import validation and reporting --- app/models/admin/import.rb | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) (limited to 'app/models') diff --git a/app/models/admin/import.rb b/app/models/admin/import.rb index 79c0722d5..fecde4878 100644 --- a/app/models/admin/import.rb +++ b/app/models/admin/import.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require 'csv' + # A non-activerecord helper class for csv upload class Admin::Import include ActiveModel::Model @@ -15,17 +17,46 @@ class Admin::Import data.original_filename end + def csv_rows + csv_data.rewind + + csv_data.take(ROWS_PROCESSING_LIMIT + 1) + end + private - def validate_data - return if data.blank? + def csv_data + return @csv_data if defined?(@csv_data) + + csv_converter = lambda do |field, field_info| + case field_info.header + when '#domain', '#public_comment' + field&.strip + when '#severity' + field&.strip&.to_sym + when '#reject_media', '#reject_reports', '#obfuscate' + ActiveModel::Type::Boolean.new.cast(field) + else + field + end + end + + @csv_data = CSV.open(data.path, encoding: 'UTF-8', skip_blanks: true, headers: true, converters: csv_converter) + @csv_data.take(1) # Ensure the headers are read + @csv_data = CSV.open(data.path, encoding: 'UTF-8', skip_blanks: true, headers: ['#domain'], converters: csv_converter) unless @csv_data.headers&.first == '#domain' + @csv_data + end - csv_data = CSV.read(data.path, encoding: 'UTF-8') + def csv_row_count + return @csv_row_count if defined?(@csv_row_count) - row_count = csv_data.size - row_count -= 1 if csv_data.first&.first == '#domain' + csv_data.rewind + @csv_row_count = csv_data.take(ROWS_PROCESSING_LIMIT + 2).count + end - errors.add(:data, I18n.t('imports.errors.over_rows_processing_limit', count: ROWS_PROCESSING_LIMIT)) if row_count > ROWS_PROCESSING_LIMIT + def validate_data + return if data.nil? + errors.add(:data, I18n.t('imports.errors.over_rows_processing_limit', count: ROWS_PROCESSING_LIMIT)) if csv_row_count > ROWS_PROCESSING_LIMIT rescue CSV::MalformedCSVError => e errors.add(:data, I18n.t('imports.errors.invalid_csv_file', error: e.message)) end -- cgit From d1387579b904542245646fc12eca99c97feccc63 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 18 Jan 2023 16:33:03 +0100 Subject: Fix situations in which instance actor can be set to a Mastodon-incompatible name (#22307) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Validate internal actor * Use “internal.actor” by default for the server actor username * Fix instance actor username on the fly if it includes ':' * Change actor name from internal.actor to mastodon.internal --- app/models/account.rb | 4 ++-- app/models/concerns/account_finder_concern.rb | 6 ++++-- db/seeds/02_instance_actor.rb | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'app/models') diff --git a/app/models/account.rb b/app/models/account.rb index b27fc748f..262285a09 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -84,8 +84,8 @@ class Account < ApplicationRecord validates :username, presence: true validates_with UniqueUsernameValidator, if: -> { will_save_change_to_username? } - # Remote user validations - validates :username, format: { with: USERNAME_ONLY_RE }, if: -> { !local? && will_save_change_to_username? } + # Remote user validations, also applies to internal actors + validates :username, format: { with: USERNAME_ONLY_RE }, if: -> { (!local? || actor_type == 'Application') && will_save_change_to_username? } # Local user validations validates :username, format: { with: /\A[a-z0-9_]+\z/i }, length: { maximum: 30 }, if: -> { local? && will_save_change_to_username? && actor_type != 'Application' } diff --git a/app/models/concerns/account_finder_concern.rb b/app/models/concerns/account_finder_concern.rb index e8b804934..37c3b8895 100644 --- a/app/models/concerns/account_finder_concern.rb +++ b/app/models/concerns/account_finder_concern.rb @@ -13,9 +13,11 @@ module AccountFinderConcern end def representative - Account.find(-99).tap(&:ensure_keys!) + actor = Account.find(-99).tap(&:ensure_keys!) + actor.update!(username: 'mastodon.internal') if actor.username.include?(':') + actor rescue ActiveRecord::RecordNotFound - Account.create!(id: -99, actor_type: 'Application', locked: true, username: Rails.configuration.x.local_domain) + Account.create!(id: -99, actor_type: 'Application', locked: true, username: 'mastodon.internal') end def find_local(username) diff --git a/db/seeds/02_instance_actor.rb b/db/seeds/02_instance_actor.rb index 39186b273..f9aa372f1 100644 --- a/db/seeds/02_instance_actor.rb +++ b/db/seeds/02_instance_actor.rb @@ -1 +1 @@ -Account.create_with(actor_type: 'Application', locked: true, username: ENV['LOCAL_DOMAIN'] || Rails.configuration.x.local_domain).find_or_create_by(id: -99) +Account.create_with(actor_type: 'Application', locked: true, username: 'mastodon.internal').find_or_create_by(id: -99) -- cgit From 343e1fe8e9ce94ea4f86d3a3df71f22f5fb2319d Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 18 Jan 2023 16:40:09 +0100 Subject: Add confirmation screen when handling reports (#22375) * Add confirmation screen on moderation actions * Add flash notice when a report has been processed * Refactor tests * Add tests --- .../admin/account_actions_controller.rb | 2 +- .../admin/reports/actions_controller.rb | 17 ++- app/models/admin/status_batch_action.rb | 9 +- app/views/admin/reports/_actions.html.haml | 2 +- app/views/admin/reports/actions/preview.html.haml | 78 +++++++++++++ config/i18n-tasks.yml | 2 + config/locales/en.yml | 21 ++++ config/routes.rb | 6 +- .../admin/reports/actions_controller_spec.rb | 128 ++++++++++++++++++--- 9 files changed, 238 insertions(+), 27 deletions(-) create mode 100644 app/views/admin/reports/actions/preview.html.haml (limited to 'app/models') 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/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/models/admin/status_batch_action.rb b/app/models/admin/status_batch_action.rb index 39cd7d0eb..b8bdec722 100644 --- a/app/models/admin/status_batch_action.rb +++ b/app/models/admin/status_batch_action.rb @@ -6,7 +6,8 @@ class Admin::StatusBatchAction include Authorization attr_accessor :current_account, :type, - :status_ids, :report_id + :status_ids, :report_id, + :text attr_reader :send_email_notification @@ -57,7 +58,8 @@ class Admin::StatusBatchAction action: :delete_statuses, account: current_account, report: report, - status_ids: status_ids + status_ids: status_ids, + text: text ) statuses.each { |status| Tombstone.find_or_create_by(uri: status.uri, account: status.account, by_moderator: true) } unless target_account.local? @@ -95,7 +97,8 @@ class Admin::StatusBatchAction action: :mark_statuses_as_sensitive, account: current_account, report: report, - status_ids: status_ids + status_ids: status_ids, + text: text ) UserMailer.warning(target_account.user, @warning).deliver_later! if warnable? diff --git a/app/views/admin/reports/_actions.html.haml b/app/views/admin/reports/_actions.html.haml index 486eb486c..aad441625 100644 --- a/app/views/admin/reports/_actions.html.haml +++ b/app/views/admin/reports/_actions.html.haml @@ -1,4 +1,4 @@ -= form_tag admin_report_actions_path(@report), method: :post do += form_tag preview_admin_report_actions_path(@report), method: :post do .report-actions .report-actions__item .report-actions__item__button diff --git a/app/views/admin/reports/actions/preview.html.haml b/app/views/admin/reports/actions/preview.html.haml new file mode 100644 index 000000000..58745319c --- /dev/null +++ b/app/views/admin/reports/actions/preview.html.haml @@ -0,0 +1,78 @@ +- target_acct = @report.target_account.acct +- warning_action = { 'delete' => 'delete_statuses', 'mark_as_sensitive' => 'mark_statuses_as_sensitive' }.fetch(@moderation_action, @moderation_action) + +- content_for :page_title do + = t('admin.reports.confirm_action', acct: target_acct) + += form_tag admin_report_actions_path(@report), class: 'simple_form', method: :post do + = hidden_field_tag :moderation_action, @moderation_action + + %p.hint= t("admin.reports.summary.action_preambles.#{@moderation_action}_html", acct: target_acct) + %ul.hint + %li.warning-hint= t("admin.reports.summary.actions.#{@moderation_action}_html", acct: target_acct) + - if @moderation_action == 'suspend' + %li.warning-hint= t('admin.reports.summary.delete_data_html', acct: target_acct) + - if %w(silence suspend).include?(@moderation_action) + %li.warning-hint= t('admin.reports.summary.close_reports_html', acct: target_acct) + - else + %li= t('admin.reports.summary.close_report', id: @report.id) + %li= t('admin.reports.summary.record_strike_html', acct: target_acct) + - if @report.target_account.local? && !@report.spam? + %li= t('admin.reports.summary.send_email_html', acct: target_acct) + + %hr.spacer/ + + - if @report.target_account.local? + %p.hint= t('admin.reports.summary.preview_preamble_html', acct: target_acct) + + .strike-card + - unless warning_action == 'none' + %p= t "user_mailer.warning.explanation.#{warning_action}", instance: Rails.configuration.x.local_domain + + .fields-group + = text_area_tag :text, nil, placeholder: t('admin.reports.summary.warning_placeholder') + + - if !@report.other? + %p + %strong= t('user_mailer.warning.reason') + = t("user_mailer.warning.categories.#{@report.category}") + + - if @report.violation? && @report.rule_ids.present? + %ul.strike-card__rules + - @report.rules.each do |rule| + %li + %span.strike-card__rules__text= rule.text + + - if @report.status_ids.present? && !@report.status_ids.empty? + %p + %strong= t('user_mailer.warning.statuses') + + .strike-card__statuses-list + - status_map = @report.statuses.includes(:application, :media_attachments).index_by(&:id) + + - @report.status_ids.each do |status_id| + .strike-card__statuses-list__item + - if (status = status_map[status_id.to_i]) + .one-liner + = link_to short_account_status_url(@report.target_account, status_id), class: 'emojify' do + = one_line_preview(status) + + - status.ordered_media_attachments.each do |media_attachment| + %abbr{ title: media_attachment.description } + = fa_icon 'link' + = media_attachment.file_file_name + .strike-card__statuses-list__item__meta + %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) + - unless status.application.nil? + · + = status.application.name + - else + .one-liner= t('disputes.strikes.status', id: status_id) + .strike-card__statuses-list__item__meta + = t('disputes.strikes.status_removed') + + %hr.spacer/ + + .actions + = link_to t('admin.reports.cancel'), admin_report_path(@report), class: 'button button-tertiary' + = button_tag t('admin.reports.confirm'), name: :confirm, class: 'button', type: :submit diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index c1da42bd8..46dd3124b 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -58,6 +58,8 @@ ignore_unused: - 'errors.429' - 'admin.accounts.roles.*' - 'admin.action_logs.actions.*' + - 'admin.reports.summary.action_preambles.*' + - 'admin.reports.summary.actions.*' - 'admin_mailer.new_appeal.actions.*' - 'statuses.attached.*' - 'move_handler.carry_{mutes,blocks}_over_text' diff --git a/config/locales/en.yml b/config/locales/en.yml index 4143aab04..3de2f2772 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -590,6 +590,7 @@ en: comment: none: None comment_description_html: 'To provide more information, %{name} wrote:' + confirm_action: Confirm moderation action against @%{acct} created_at: Reported delete_and_resolve: Delete posts forwarded: Forwarded @@ -606,6 +607,7 @@ en: placeholder: Describe what actions have been taken, or any other related updates... title: Notes notes_description_html: View and leave notes to other moderators and your future self + processed_msg: 'Report #%{id} successfully processed' quick_actions_description_html: 'Take a quick action or scroll down to see reported content:' remote_user_placeholder: the remote user from %{instance} reopen: Reopen report @@ -618,9 +620,28 @@ en: status: Status statuses: Reported content statuses_description_html: Offending content will be cited in communication with the reported account + summary: + action_preambles: + delete_html: 'You are about to remove some of @%{acct}''s posts. This will:' + mark_as_sensitive_html: 'You are about to mark some of @%{acct}''s posts as sensitive. This will:' + silence_html: 'You are about to limit @%{acct}''s account. This will:' + suspend_html: 'You are about to suspend @%{acct}''s account. This will:' + actions: + delete_html: Remove the offending posts + mark_as_sensitive_html: Mark the offending posts' media as sensitive + silence_html: Severely limit @%{acct}'s reach by making their profile and contents only visible to people already following them or manually looking it profile up + suspend_html: Suspend @%{acct}, making their profile and contents inaccessible and impossible to interact with + close_report: 'Mark report #%{id} as resolved' + close_reports_html: Mark all reports against @%{acct} as resolved + delete_data_html: Delete @%{acct}'s profile and contents 30 days from now unless they get unsuspended in the meantime + preview_preamble_html: "@%{acct} will receive a warning with the following contents:" + record_strike_html: Record a strike against @%{acct} to help you escalate on future violations from this account + send_email_html: Send @%{acct} a warning e-mail + warning_placeholder: Optional additional reasoning for the moderation action. target_origin: Origin of reported account title: Reports unassign: Unassign + unknown_action_msg: 'Unknown action: %{action}' unresolved: Unresolved updated_at: Updated view_profile: View profile diff --git a/config/routes.rb b/config/routes.rb index 98e19667c..0bee2f639 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -310,7 +310,11 @@ Rails.application.routes.draw do end resources :reports, only: [:index, :show] do - resources :actions, only: [:create], controller: 'reports/actions' + resources :actions, only: [:create], controller: 'reports/actions' do + collection do + post :preview + end + end member do post :assign_to_self diff --git a/spec/controllers/admin/reports/actions_controller_spec.rb b/spec/controllers/admin/reports/actions_controller_spec.rb index 6609798dc..9890ac9ce 100644 --- a/spec/controllers/admin/reports/actions_controller_spec.rb +++ b/spec/controllers/admin/reports/actions_controller_spec.rb @@ -4,39 +4,131 @@ describe Admin::Reports::ActionsController do render_views let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } - let(:account) { Fabricate(:account) } - let!(:status) { Fabricate(:status, account: account) } - let(:media_attached_status) { Fabricate(:status, account: account) } - let!(:media_attachment) { Fabricate(:media_attachment, account: account, status: media_attached_status) } - let(:media_attached_deleted_status) { Fabricate(:status, account: account, deleted_at: 1.day.ago) } - let!(:media_attachment2) { Fabricate(:media_attachment, account: account, status: media_attached_deleted_status) } - let(:last_media_attached_status) { Fabricate(:status, account: account) } - let!(:last_media_attachment) { Fabricate(:media_attachment, account: account, status: last_media_attached_status) } - let!(:last_status) { Fabricate(:status, account: account) } before do sign_in user, scope: :user end - describe 'POST #create' do - let(:report) { Fabricate(:report, status_ids: status_ids, account: user.account, target_account: account) } - let(:status_ids) { [media_attached_status.id, media_attached_deleted_status.id] } + describe 'POST #preview' do + let(:report) { Fabricate(:report) } before do - post :create, params: { report_id: report.id, action => '' } + post :preview, params: { report_id: report.id, action => '' } + end + + context 'when the action is "suspend"' do + let(:action) { 'suspend' } + + it 'returns http success' do + expect(response).to have_http_status(200) + end end - context 'when action is mark_as_sensitive' do + context 'when the action is "silence"' do + let(:action) { 'silence' } + it 'returns http success' do + expect(response).to have_http_status(200) + end + end + + context 'when the action is "delete"' do + let(:action) { 'delete' } + + it 'returns http success' do + expect(response).to have_http_status(200) + end + end + + context 'when the action is "mark_as_sensitive"' do let(:action) { 'mark_as_sensitive' } - it 'resolves the report' do - expect(report.reload.action_taken_at).to_not be_nil + it 'returns http success' do + expect(response).to have_http_status(200) + end + end + end + + describe 'POST #create' do + let(:target_account) { Fabricate(:account) } + let(:statuses) { [Fabricate(:status, account: target_account), Fabricate(:status, account: target_account)] } + let!(:media) { Fabricate(:media_attachment, account: target_account, status: statuses[0]) } + let(:report) { Fabricate(:report, target_account: target_account, status_ids: statuses.map(&:id)) } + let(:text) { 'hello' } + + shared_examples 'common behavior' do + it 'closes the report' do + expect { subject }.to change { report.reload.action_taken? }.from(false).to(true) end - it 'marks the non-deleted as sensitive' do - expect(media_attached_status.reload.sensitive).to eq true + it 'creates a strike with the expected text' do + expect { subject }.to change { report.target_account.strikes.count }.by(1) + expect(report.target_account.strikes.last.text).to eq text end + + it 'redirects' do + subject + expect(response).to redirect_to(admin_reports_path) + end + end + + shared_examples 'all action types' do + context 'when the action is "suspend"' do + let(:action) { 'suspend' } + + it_behaves_like 'common behavior' + + it 'suspends the target account' do + expect { subject }.to change { report.target_account.reload.suspended? }.from(false).to(true) + end + end + + context 'when the action is "silence"' do + let(:action) { 'silence' } + + it_behaves_like 'common behavior' + + it 'suspends the target account' do + expect { subject }.to change { report.target_account.reload.silenced? }.from(false).to(true) + end + end + + context 'when the action is "delete"' do + let(:action) { 'delete' } + + it_behaves_like 'common behavior' + end + + context 'when the action is "mark_as_sensitive"' do + let(:action) { 'mark_as_sensitive' } + let(:statuses) { [media_attached_status, media_attached_deleted_status] } + + let!(:status) { Fabricate(:status, account: target_account) } + let(:media_attached_status) { Fabricate(:status, account: target_account) } + let!(:media_attachment) { Fabricate(:media_attachment, account: target_account, status: media_attached_status) } + let(:media_attached_deleted_status) { Fabricate(:status, account: target_account, deleted_at: 1.day.ago) } + let!(:media_attachment2) { Fabricate(:media_attachment, account: target_account, status: media_attached_deleted_status) } + let(:last_media_attached_status) { Fabricate(:status, account: target_account) } + let!(:last_media_attachment) { Fabricate(:media_attachment, account: target_account, status: last_media_attached_status) } + let!(:last_status) { Fabricate(:status, account: target_account) } + + it_behaves_like 'common behavior' + + it 'marks the non-deleted as sensitive' do + subject + expect(media_attached_status.reload.sensitive).to eq true + end + end + end + + context 'action as submit button' do + subject { post :create, params: { report_id: report.id, text: text, action => '' } } + it_behaves_like 'all action types' + end + + context 'action as submit button' do + subject { post :create, params: { report_id: report.id, text: text, moderation_action: action } } + it_behaves_like 'all action types' end end end -- cgit From 3970a6f433ad3cf79ef41d84baf6d788d25bd246 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 18 Jan 2023 16:43:58 +0100 Subject: Add option to make the landing page be /about even when trends are enabled (#20808) * Add option to make the landing page be /about even when trends are enabled * Restablish /explore as landing page by default --- app/javascript/mastodon/features/ui/index.js | 4 ++-- app/javascript/mastodon/initial_state.js | 2 ++ app/models/form/admin_settings.rb | 2 ++ app/serializers/initial_state_serializer.rb | 1 + app/views/admin/settings/discovery/show.html.haml | 3 +++ config/locales/simple_form.en.yml | 2 ++ config/settings.yml | 1 + 7 files changed, 13 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js index b05956606..3fbe03fdf 100644 --- a/app/javascript/mastodon/features/ui/index.js +++ b/app/javascript/mastodon/features/ui/index.js @@ -54,7 +54,7 @@ import { About, PrivacyPolicy, } from './util/async-components'; -import initialState, { me, owner, singleUserMode, showTrends } from '../../initial_state'; +import initialState, { me, owner, singleUserMode, showTrends, trendsAsLanding } from '../../initial_state'; import { closeOnboarding, INTRODUCTION_VERSION } from 'mastodon/actions/onboarding'; import Header from './components/header'; @@ -163,7 +163,7 @@ class SwitchingColumnsArea extends React.PureComponent { } } else if (singleUserMode && owner && initialState?.accounts[owner]) { redirect = ; - } else if (showTrends) { + } else if (showTrends && trendsAsLanding) { redirect = ; } else { redirect = ; diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js index 62fd4ac72..5bb8546eb 100644 --- a/app/javascript/mastodon/initial_state.js +++ b/app/javascript/mastodon/initial_state.js @@ -75,6 +75,7 @@ * @property {boolean} timeline_preview * @property {string} title * @property {boolean} trends + * @property {boolean} trends_as_landing_page * @property {boolean} unfollow_modal * @property {boolean} use_blurhash * @property {boolean=} use_pending_items @@ -126,6 +127,7 @@ export const singleUserMode = getMeta('single_user_mode'); export const source_url = getMeta('source_url'); export const timelinePreview = getMeta('timeline_preview'); export const title = getMeta('title'); +export const trendsAsLanding = getMeta('trends_as_landing_page'); export const unfollowModal = getMeta('unfollow_modal'); export const useBlurhash = getMeta('use_blurhash'); export const usePendingItems = getMeta('use_pending_items'); diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index dc6cc5ed3..132b57b04 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -23,6 +23,7 @@ class Form::AdminSettings thumbnail mascot trends + trends_as_landing_page trendable_by_default show_domain_blocks show_domain_blocks_rationale @@ -46,6 +47,7 @@ class Form::AdminSettings preview_sensitive_media profile_directory trends + trends_as_landing_page trendable_by_default noindex require_invite_text diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 70f40088d..1bd62c26f 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -32,6 +32,7 @@ class InitialStateSerializer < ActiveModel::Serializer activity_api_enabled: Setting.activity_api_enabled, single_user_mode: Rails.configuration.x.single_user_mode, translation_enabled: TranslationService.configured?, + trends_as_landing_page: Setting.trends_as_landing_page, } if object.current_account diff --git a/app/views/admin/settings/discovery/show.html.haml b/app/views/admin/settings/discovery/show.html.haml index 59188833b..759bbdceb 100644 --- a/app/views/admin/settings/discovery/show.html.haml +++ b/app/views/admin/settings/discovery/show.html.haml @@ -18,6 +18,9 @@ .fields-group = f.input :trends, as: :boolean, wrapper: :with_label + .fields-group + = f.input :trends_as_landing_page, as: :boolean, wrapper: :with_label + .fields-group = f.input :trendable_by_default, as: :boolean, wrapper: :with_label, recommended: :not_recommended diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index f66e12c4c..d01f0ae75 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -96,6 +96,7 @@ en: timeline_preview: Logged out visitors will be able to browse the most recent public posts available on the server. trendable_by_default: Skip manual review of trending content. Individual items can still be removed from trends after the fact. trends: Trends show which posts, hashtags and news stories are gaining traction on your server. + trends_as_landing_page: Show trending content to logged-out users and visitors instead of a description of this server. Requires trends to be enabled. form_challenge: current_password: You are entering a secure area imports: @@ -256,6 +257,7 @@ en: timeline_preview: Allow unauthenticated access to public timelines trendable_by_default: Allow trends without prior review trends: Enable trends + trends_as_landing_page: Use trends as the landing page interactions: must_be_follower: Block notifications from non-followers must_be_following: Block notifications from people you don't follow diff --git a/config/settings.yml b/config/settings.yml index ec8fead0f..f0b09dd5c 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -35,6 +35,7 @@ defaults: &defaults use_blurhash: true use_pending_items: false trends: true + trends_as_landing_page: true trendable_by_default: false crop_images: true notification_emails: -- cgit From a1abda39dd96c9415b46b799ce969cf7a5a1492a Mon Sep 17 00:00:00 2001 From: Jeong Arm Date: Sat, 21 Jan 2023 18:22:22 +0900 Subject: Fix Account Strike causing PG not null validation error (#23178) --- app/models/account_warning.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'app/models') diff --git a/app/models/account_warning.rb b/app/models/account_warning.rb index 961a078b9..a181cd18d 100644 --- a/app/models/account_warning.rb +++ b/app/models/account_warning.rb @@ -26,6 +26,8 @@ class AccountWarning < ApplicationRecord suspend: 4_000, }, _suffix: :action + before_validation :before_validate + belongs_to :account, inverse_of: :account_warnings belongs_to :target_account, class_name: 'Account', inverse_of: :strikes belongs_to :report, optional: true @@ -47,4 +49,10 @@ class AccountWarning < ApplicationRecord def to_log_human_identifier target_account.acct end + + private + + def before_validate + self.text = '' if text.blank? + end end -- cgit From 6883fddb19b1319a378aa5dc2034670c3b27ce39 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 24 Jan 2023 19:40:21 +0100 Subject: Fix account activation being triggered before email confirmation (#23245) * Add tests * Fix account activation being triggered before email confirmation Fixes #23098 --- app/models/user.rb | 28 +++++++--- spec/models/user_spec.rb | 134 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 152 insertions(+), 10 deletions(-) (limited to 'app/models') diff --git a/app/models/user.rb b/app/models/user.rb index 2a42ffaa1..d40044da3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -195,10 +195,16 @@ class User < ApplicationRecord super - if new_user && approved? - prepare_new_user! - elsif new_user - notify_staff_about_pending_account! + if new_user + # Avoid extremely unlikely race condition when approving and confirming + # the user at the same time + reload unless approved? + + if approved? + prepare_new_user! + else + notify_staff_about_pending_account! + end end end @@ -209,7 +215,13 @@ class User < ApplicationRecord skip_confirmation! save! - prepare_new_user! if new_user && approved? + if new_user + # Avoid extremely unlikely race condition when approving and confirming + # the user at the same time + reload unless approved? + + prepare_new_user! if approved? + end end def update_sign_in!(new_sign_in: false) @@ -260,7 +272,11 @@ class User < ApplicationRecord return if approved? update!(approved: true) - prepare_new_user! + + # Avoid extremely unlikely race condition when approving and confirming + # the user at the same time + reload unless confirmed? + prepare_new_user! if confirmed? end def otp_enabled? diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index a7da31e60..4b3d6101f 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -142,10 +142,136 @@ RSpec.describe User, type: :model do end describe '#confirm' do - it 'sets email to unconfirmed_email' do - user = Fabricate.build(:user, confirmed_at: Time.now.utc, unconfirmed_email: 'new-email@example.com') - user.confirm - expect(user.email).to eq 'new-email@example.com' + let(:new_email) { 'new-email@example.com' } + + subject { user.confirm } + + before do + allow(TriggerWebhookWorker).to receive(:perform_async) + end + + context 'when the user is already confirmed' do + let!(:user) { Fabricate(:user, confirmed_at: Time.now.utc, approved: true, unconfirmed_email: new_email) } + + it 'sets email to unconfirmed_email' do + expect { subject }.to change { user.reload.email }.to(new_email) + end + + it 'does not trigger the account.approved Web Hook' do + subject + expect(TriggerWebhookWorker).not_to have_received(:perform_async).with('account.approved', 'Account', user.account_id) + end + end + + context 'when the user is a new user' do + let(:user) { Fabricate(:user, confirmed_at: nil, unconfirmed_email: new_email) } + + context 'when the user is already approved' do + around(:example) do |example| + registrations_mode = Setting.registrations_mode + Setting.registrations_mode = 'approved' + + example.run + + Setting.registrations_mode = registrations_mode + end + + before do + user.approve! + end + + it 'sets email to unconfirmed_email' do + expect { subject }.to change { user.reload.email }.to(new_email) + end + + it 'triggers the account.approved Web Hook' do + user.confirm + expect(TriggerWebhookWorker).to have_received(:perform_async).with('account.approved', 'Account', user.account_id).once + end + end + + context 'when the user does not require explicit approval' do + around(:example) do |example| + registrations_mode = Setting.registrations_mode + Setting.registrations_mode = 'open' + + example.run + + Setting.registrations_mode = registrations_mode + end + + it 'sets email to unconfirmed_email' do + expect { subject }.to change { user.reload.email }.to(new_email) + end + + it 'triggers the account.approved Web Hook' do + user.confirm + expect(TriggerWebhookWorker).to have_received(:perform_async).with('account.approved', 'Account', user.account_id).once + end + end + + context 'when the user requires explicit approval but is not approved' do + around(:example) do |example| + registrations_mode = Setting.registrations_mode + Setting.registrations_mode = 'approved' + + example.run + + Setting.registrations_mode = registrations_mode + end + + it 'sets email to unconfirmed_email' do + expect { subject }.to change { user.reload.email }.to(new_email) + end + + it 'does not trigger the account.approved Web Hook' do + subject + expect(TriggerWebhookWorker).to_not have_received(:perform_async).with('account.approved', 'Account', user.account_id) + end + end + end + end + + describe '#approve!' do + subject { user.approve! } + + around(:example) do |example| + registrations_mode = Setting.registrations_mode + Setting.registrations_mode = 'approved' + + example.run + + Setting.registrations_mode = registrations_mode + end + + before do + allow(TriggerWebhookWorker).to receive(:perform_async) + end + + context 'when the user is already confirmed' do + let(:user) { Fabricate(:user, confirmed_at: Time.now.utc, approved: false) } + + it 'sets the approved flag' do + expect { subject }.to change { user.reload.approved? }.to(true) + end + + it 'triggers the account.approved Web Hook' do + subject + expect(TriggerWebhookWorker).to have_received(:perform_async).with('account.approved', 'Account', user.account_id).once + end + end + + context 'when the user is not confirmed' do + let(:user) { Fabricate(:user, confirmed_at: nil, approved: false) } + + it 'sets the approved flag' do + expect { subject }.to change { user.reload.approved? }.to(true) + end + + it 'does not trigger the account.approved Web Hook' do + subject + expect(TriggerWebhookWorker).not_to have_received(:perform_async).with('account.approved', 'Account', user.account_id) + end end end -- cgit From 13a2abacc8f943e2b1d2da63551443887e1065b0 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 25 Jan 2023 19:55:40 +0100 Subject: Add `roles` attribute to Account entities in REST API (#23255) --- app/models/status.rb | 4 ++-- app/serializers/rest/account_serializer.rb | 18 ++++++++++++++++++ spec/fabricators/user_role_fabricator.rb | 6 +++--- 3 files changed, 23 insertions(+), 5 deletions(-) (limited to 'app/models') diff --git a/app/models/status.rb b/app/models/status.rb index fa9fb9fad..b1c49e99a 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -117,7 +117,7 @@ class Status < ApplicationRecord :tags, :preview_cards, :preloadable_poll, - account: [:account_stat, :user], + account: [:account_stat, user: :role], active_mentions: { account: :account_stat }, reblog: [ :application, @@ -127,7 +127,7 @@ class Status < ApplicationRecord :conversation, :status_stat, :preloadable_poll, - account: [:account_stat, :user], + account: [:account_stat, user: :role], active_mentions: { account: :account_stat }, ], thread: { account: :account_stat } diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb index 6582b5bcf..62eac1fbd 100644 --- a/app/serializers/rest/account_serializer.rb +++ b/app/serializers/rest/account_serializer.rb @@ -26,6 +26,16 @@ class REST::AccountSerializer < ActiveModel::Serializer end end + class RoleSerializer < ActiveModel::Serializer + attributes :id, :name, :color + + def id + object.id.to_s + end + end + + has_many :roles, serializer: RoleSerializer, if: :local? + class FieldSerializer < ActiveModel::Serializer include FormattingHelper @@ -114,6 +124,14 @@ class REST::AccountSerializer < ActiveModel::Serializer object.silenced? end + def roles + if object.suspended? + [] + else + [object.user.role].compact.filter { |role| role.highlighted? } + end + end + def noindex object.user_prefers_noindex? end diff --git a/spec/fabricators/user_role_fabricator.rb b/spec/fabricators/user_role_fabricator.rb index 28f76c8c4..ed0a7dc1f 100644 --- a/spec/fabricators/user_role_fabricator.rb +++ b/spec/fabricators/user_role_fabricator.rb @@ -1,5 +1,5 @@ Fabricator(:user_role) do name "MyString" - color "MyString" - permissions "" -end \ No newline at end of file + color "" + permissions 0 +end -- cgit From 8f590b0a211716bcbfc0f2278a452469f3346f55 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 4 Feb 2023 04:56:06 +0100 Subject: Add setting for status page URL (#23390) --- .../mastodon/features/ui/components/link_footer.js | 16 +++++++++++----- app/javascript/mastodon/initial_state.js | 1 + app/models/form/admin_settings.rb | 2 ++ app/presenters/instance_presenter.rb | 4 ++++ app/serializers/initial_state_serializer.rb | 1 + app/serializers/rest/instance_serializer.rb | 1 + app/views/admin/settings/about/show.html.haml | 3 +++ config/locales/simple_form.en.yml | 2 ++ 8 files changed, 25 insertions(+), 5 deletions(-) (limited to 'app/models') diff --git a/app/javascript/mastodon/features/ui/components/link_footer.js b/app/javascript/mastodon/features/ui/components/link_footer.js index db5945d6a..be2111207 100644 --- a/app/javascript/mastodon/features/ui/components/link_footer.js +++ b/app/javascript/mastodon/features/ui/components/link_footer.js @@ -3,7 +3,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; import { Link } from 'react-router-dom'; -import { domain, version, source_url, profile_directory as profileDirectory } from 'mastodon/initial_state'; +import { domain, version, source_url, statusPageUrl, profile_directory as profileDirectory } from 'mastodon/initial_state'; import { logOut } from 'mastodon/utils/log_out'; import { openModal } from 'mastodon/actions/modal'; import { PERMISSION_INVITE_USERS } from 'mastodon/permissions'; @@ -59,21 +59,27 @@ class LinkFooter extends React.PureComponent {

{domain}: {' '} - + + {statusPageUrl && ( + <> + {DividingCircle} + + + )} {canInvite && ( <> {DividingCircle} - + )} {canProfileDirectory && ( <> {DividingCircle} - + )} {DividingCircle} - +

diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js index 5bb8546eb..d04c4a42d 100644 --- a/app/javascript/mastodon/initial_state.js +++ b/app/javascript/mastodon/initial_state.js @@ -134,5 +134,6 @@ export const usePendingItems = getMeta('use_pending_items'); export const version = getMeta('version'); export const translationEnabled = getMeta('translation_enabled'); export const languages = initialState?.languages; +export const statusPageUrl = getMeta('status_page_url'); export default initialState; diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index 132b57b04..001caa376 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -32,6 +32,7 @@ class Form::AdminSettings media_cache_retention_period content_cache_retention_period backups_retention_period + status_page_url ).freeze INTEGER_KEYS = %i( @@ -68,6 +69,7 @@ class Form::AdminSettings validates :show_domain_blocks_rationale, inclusion: { in: %w(disabled users all) }, if: -> { defined?(@show_domain_blocks_rationale) } validates :media_cache_retention_period, :content_cache_retention_period, :backups_retention_period, numericality: { only_integer: true }, allow_blank: true, if: -> { defined?(@media_cache_retention_period) || defined?(@content_cache_retention_period) || defined?(@backups_retention_period) } validates :site_short_description, length: { maximum: 200 }, if: -> { defined?(@site_short_description) } + validates :status_page_url, url: true validate :validate_site_uploads KEYS.each do |key| diff --git a/app/presenters/instance_presenter.rb b/app/presenters/instance_presenter.rb index fba3cc734..e3ba984f7 100644 --- a/app/presenters/instance_presenter.rb +++ b/app/presenters/instance_presenter.rb @@ -38,6 +38,10 @@ class InstancePresenter < ActiveModelSerializers::Model Setting.site_terms end + def status_page_url + Setting.status_page_url + end + def domain Rails.configuration.x.local_domain end diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 1bd62c26f..24417bca7 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -33,6 +33,7 @@ class InitialStateSerializer < ActiveModel::Serializer single_user_mode: Rails.configuration.x.single_user_mode, translation_enabled: TranslationService.configured?, trends_as_landing_page: Setting.trends_as_landing_page, + status_page_url: Setting.status_page_url, } if object.current_account diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb index 5ae1099d0..fbb2fea0d 100644 --- a/app/serializers/rest/instance_serializer.rb +++ b/app/serializers/rest/instance_serializer.rb @@ -45,6 +45,7 @@ class REST::InstanceSerializer < ActiveModel::Serializer { urls: { streaming: Rails.configuration.x.streaming_api_base_url, + status: object.status_page_url, }, accounts: { diff --git a/app/views/admin/settings/about/show.html.haml b/app/views/admin/settings/about/show.html.haml index 366d213f6..2aaa64abe 100644 --- a/app/views/admin/settings/about/show.html.haml +++ b/app/views/admin/settings/about/show.html.haml @@ -26,6 +26,9 @@ .fields-row__column.fields-row__column-6.fields-group = f.input :show_domain_blocks_rationale, wrapper: :with_label, collection: %i(disabled users all), label_method: lambda { |value| t("admin.settings.domain_blocks.#{value}") }, include_blank: false, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li' + .fields-group + = f.input :status_page_url, wrapper: :with_block_label, input_html: { placeholder: "https://status.#{Rails.configuration.x.local_domain}" } + .fields-group = f.input :site_terms, wrapper: :with_block_label, as: :text, input_html: { rows: 8 } diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index d01f0ae75..96b0131ef 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -91,6 +91,7 @@ en: site_short_description: A short description to help uniquely identify your server. Who is running it, who is it for? site_terms: Use your own privacy policy or leave blank to use the default. Can be structured with Markdown syntax. site_title: How people may refer to your server besides its domain name. + status_page_url: URL of a page where people can see the status of this server during an outage theme: Theme that logged out visitors and new users see. thumbnail: A roughly 2:1 image displayed alongside your server information. timeline_preview: Logged out visitors will be able to browse the most recent public posts available on the server. @@ -252,6 +253,7 @@ en: site_short_description: Server description site_terms: Privacy Policy site_title: Server name + status_page_url: Status page URL theme: Default theme thumbnail: Server thumbnail timeline_preview: Allow unauthenticated access to public timelines -- cgit From ed570050c62115cfbcca8cfcd0de891b729f3e5c Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Mon, 6 Feb 2023 21:44:36 -0500 Subject: Autofix Rails/EagerEvaluationLogMessage (#23429) * Autofix Rails/EagerEvaluationLogMessage * Update spec for debug block syntax --- app/lib/activitypub/activity/create.rb | 2 +- app/lib/link_details_extractor.rb | 2 +- app/models/concerns/remotable.rb | 4 ++-- app/services/activitypub/fetch_featured_collection_service.rb | 2 +- app/services/activitypub/fetch_remote_account_service.rb | 2 +- app/services/activitypub/fetch_remote_actor_service.rb | 2 +- app/services/activitypub/fetch_remote_key_service.rb | 2 +- app/services/activitypub/process_collection_service.rb | 4 ++-- app/services/activitypub/process_status_update_service.rb | 2 +- app/services/fetch_link_card_service.rb | 2 +- app/services/fetch_resource_service.rb | 2 +- app/services/keys/claim_service.rb | 2 +- app/services/keys/query_service.rb | 2 +- app/services/resolve_account_service.rb | 2 +- app/services/verify_link_service.rb | 2 +- app/workers/activitypub/processing_worker.rb | 2 +- spec/models/concerns/remotable_spec.rb | 4 +++- 17 files changed, 21 insertions(+), 19 deletions(-) (limited to 'app/models') diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index b15e66ca2..cfad62a6b 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -285,7 +285,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity media_attachments rescue Addressable::URI::InvalidURIError => e - Rails.logger.debug "Invalid URL in attachment: #{e}" + Rails.logger.debug { "Invalid URL in attachment: #{e}" } media_attachments end diff --git a/app/lib/link_details_extractor.rb b/app/lib/link_details_extractor.rb index b0c4e4f42..2e0672abe 100644 --- a/app/lib/link_details_extractor.rb +++ b/app/lib/link_details_extractor.rb @@ -248,7 +248,7 @@ class LinkDetailsExtractor structured_data rescue Oj::ParseError, EncodingError - Rails.logger.debug("Invalid JSON-LD in #{@original_url}") + Rails.logger.debug { "Invalid JSON-LD in #{@original_url}" } next end.first end diff --git a/app/models/concerns/remotable.rb b/app/models/concerns/remotable.rb index ffe8a7565..cb8f46e68 100644 --- a/app/models/concerns/remotable.rb +++ b/app/models/concerns/remotable.rb @@ -27,11 +27,11 @@ module Remotable public_send("#{attachment_name}=", ResponseWithLimit.new(response, limit)) end rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError => e - Rails.logger.debug "Error fetching remote #{attachment_name}: #{e}" + Rails.logger.debug { "Error fetching remote #{attachment_name}: #{e}" } public_send("#{attachment_name}=", nil) if public_send("#{attachment_name}_file_name").present? raise e unless suppress_errors rescue Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Paperclip::Error, Mastodon::DimensionsValidationError, Mastodon::StreamValidationError => e - Rails.logger.debug "Error fetching remote #{attachment_name}: #{e}" + Rails.logger.debug { "Error fetching remote #{attachment_name}: #{e}" } public_send("#{attachment_name}=", nil) if public_send("#{attachment_name}_file_name").present? end diff --git a/app/services/activitypub/fetch_featured_collection_service.rb b/app/services/activitypub/fetch_featured_collection_service.rb index a746ef4d6..1208820df 100644 --- a/app/services/activitypub/fetch_featured_collection_service.rb +++ b/app/services/activitypub/fetch_featured_collection_service.rb @@ -53,7 +53,7 @@ class ActivityPub::FetchFeaturedCollectionService < BaseService status.id rescue ActiveRecord::RecordInvalid => e - Rails.logger.debug "Invalid pinned status #{uri}: #{e.message}" + Rails.logger.debug { "Invalid pinned status #{uri}: #{e.message}" } nil end diff --git a/app/services/activitypub/fetch_remote_account_service.rb b/app/services/activitypub/fetch_remote_account_service.rb index 7aba8269e..567dd8a14 100644 --- a/app/services/activitypub/fetch_remote_account_service.rb +++ b/app/services/activitypub/fetch_remote_account_service.rb @@ -6,7 +6,7 @@ class ActivityPub::FetchRemoteAccountService < ActivityPub::FetchRemoteActorServ actor = super return actor if actor.nil? || actor.is_a?(Account) - Rails.logger.debug "Fetching account #{uri} failed: Expected Account, got #{actor.class.name}" + Rails.logger.debug { "Fetching account #{uri} failed: Expected Account, got #{actor.class.name}" } raise Error, "Expected Account, got #{actor.class.name}" unless suppress_errors end end diff --git a/app/services/activitypub/fetch_remote_actor_service.rb b/app/services/activitypub/fetch_remote_actor_service.rb index 4f60ea5e8..8908d21e2 100644 --- a/app/services/activitypub/fetch_remote_actor_service.rb +++ b/app/services/activitypub/fetch_remote_actor_service.rb @@ -38,7 +38,7 @@ class ActivityPub::FetchRemoteActorService < BaseService ActivityPub::ProcessAccountService.new.call(@username, @domain, @json, only_key: only_key, verified_webfinger: !only_key, request_id: request_id) rescue Error => e - Rails.logger.debug "Fetching actor #{uri} failed: #{e.message}" + Rails.logger.debug { "Fetching actor #{uri} failed: #{e.message}" } raise unless suppress_errors end diff --git a/app/services/activitypub/fetch_remote_key_service.rb b/app/services/activitypub/fetch_remote_key_service.rb index 32e82b47a..8eb97c1e6 100644 --- a/app/services/activitypub/fetch_remote_key_service.rb +++ b/app/services/activitypub/fetch_remote_key_service.rb @@ -38,7 +38,7 @@ class ActivityPub::FetchRemoteKeyService < BaseService find_actor(owner_uri, @owner, suppress_errors) rescue Error => e - Rails.logger.debug "Fetching key #{uri} failed: #{e.message}" + Rails.logger.debug { "Fetching key #{uri} failed: #{e.message}" } raise unless suppress_errors end diff --git a/app/services/activitypub/process_collection_service.rb b/app/services/activitypub/process_collection_service.rb index 8218b8a12..52f48bd49 100644 --- a/app/services/activitypub/process_collection_service.rb +++ b/app/services/activitypub/process_collection_service.rb @@ -11,7 +11,7 @@ class ActivityPub::ProcessCollectionService < BaseService begin @json = compact(@json) if @json['signature'].is_a?(Hash) rescue JSON::LD::JsonLdError => e - Rails.logger.debug "Error when compacting JSON-LD document for #{value_or_id(@json['actor'])}: #{e.message}" + Rails.logger.debug { "Error when compacting JSON-LD document for #{value_or_id(@json['actor'])}: #{e.message}" } @json = original_json.without('signature') end @@ -72,7 +72,7 @@ class ActivityPub::ProcessCollectionService < BaseService @account = nil unless @account.is_a?(Account) @account rescue JSON::LD::JsonLdError, RDF::WriterError => e - Rails.logger.debug "Could not verify LD-Signature for #{value_or_id(@json['actor'])}: #{e.message}" + Rails.logger.debug { "Could not verify LD-Signature for #{value_or_id(@json['actor'])}: #{e.message}" } nil end end diff --git a/app/services/activitypub/process_status_update_service.rb b/app/services/activitypub/process_status_update_service.rb index 11b38ab92..1dc393e28 100644 --- a/app/services/activitypub/process_status_update_service.rb +++ b/app/services/activitypub/process_status_update_service.rb @@ -94,7 +94,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService @next_media_attachments << media_attachment rescue Addressable::URI::InvalidURIError => e - Rails.logger.debug "Invalid URL in attachment: #{e}" + Rails.logger.debug { "Invalid URL in attachment: #{e}" } end end diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb index e5b5b730e..4d55aa5e2 100644 --- a/app/services/fetch_link_card_service.rb +++ b/app/services/fetch_link_card_service.rb @@ -30,7 +30,7 @@ class FetchLinkCardService < BaseService attach_card if @card&.persisted? rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e - Rails.logger.debug "Error fetching link #{@original_url}: #{e}" + Rails.logger.debug { "Error fetching link #{@original_url}: #{e}" } nil end diff --git a/app/services/fetch_resource_service.rb b/app/services/fetch_resource_service.rb index 73204e55d..4470fca01 100644 --- a/app/services/fetch_resource_service.rb +++ b/app/services/fetch_resource_service.rb @@ -12,7 +12,7 @@ class FetchResourceService < BaseService process(url) rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e - Rails.logger.debug "Error fetching resource #{@url}: #{e}" + Rails.logger.debug { "Error fetching resource #{@url}: #{e}" } nil end diff --git a/app/services/keys/claim_service.rb b/app/services/keys/claim_service.rb index ae9e24a24..0451c3cb1 100644 --- a/app/services/keys/claim_service.rb +++ b/app/services/keys/claim_service.rb @@ -58,7 +58,7 @@ class Keys::ClaimService < BaseService @result = Result.new(@target_account, @device_id, key_id: json['id'], key: json['publicKeyBase64'], signature: json.dig('signature', 'signatureValue')) rescue HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error => e - Rails.logger.debug "Claiming one-time key for #{@target_account.acct}:#{@device_id} failed: #{e}" + Rails.logger.debug { "Claiming one-time key for #{@target_account.acct}:#{@device_id} failed: #{e}" } nil end diff --git a/app/services/keys/query_service.rb b/app/services/keys/query_service.rb index ac3388bdc..404854c9f 100644 --- a/app/services/keys/query_service.rb +++ b/app/services/keys/query_service.rb @@ -73,7 +73,7 @@ class Keys::QueryService < BaseService Device.new(device_id: device['id'], name: device['name'], identity_key: device.dig('identityKey', 'publicKeyBase64'), fingerprint_key: device.dig('fingerprintKey', 'publicKeyBase64'), claim_url: device['claim']) end rescue HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error => e - Rails.logger.debug "Querying devices for #{@account.acct} failed: #{e}" + Rails.logger.debug { "Querying devices for #{@account.acct} failed: #{e}" } nil end end diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb index d8b81a7b9..1ba372cd6 100644 --- a/app/services/resolve_account_service.rb +++ b/app/services/resolve_account_service.rb @@ -54,7 +54,7 @@ class ResolveAccountService < BaseService fetch_account! rescue Webfinger::Error => e - Rails.logger.debug "Webfinger query for #{@uri} failed: #{e}" + Rails.logger.debug { "Webfinger query for #{@uri} failed: #{e}" } raise unless @options[:suppress_errors] end diff --git a/app/services/verify_link_service.rb b/app/services/verify_link_service.rb index 9708cdd73..f83a664d4 100644 --- a/app/services/verify_link_service.rb +++ b/app/services/verify_link_service.rb @@ -11,7 +11,7 @@ class VerifyLinkService < BaseService field.mark_verified! rescue OpenSSL::SSL::SSLError, HTTP::Error, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, IPAddr::AddressFamilyError => e - Rails.logger.debug "Error fetching link #{@url}: #{e}" + Rails.logger.debug { "Error fetching link #{@url}: #{e}" } nil end diff --git a/app/workers/activitypub/processing_worker.rb b/app/workers/activitypub/processing_worker.rb index 5e36fab51..1bb94b7f2 100644 --- a/app/workers/activitypub/processing_worker.rb +++ b/app/workers/activitypub/processing_worker.rb @@ -15,6 +15,6 @@ class ActivityPub::ProcessingWorker ActivityPub::ProcessCollectionService.new.call(body, actor, override_timestamps: true, delivered_to_account_id: delivered_to_account_id, delivery: true) rescue ActiveRecord::RecordInvalid => e - Rails.logger.debug "Error processing incoming ActivityPub object: #{e}" + Rails.logger.debug { "Error processing incoming ActivityPub object: #{e}" } end end diff --git a/spec/models/concerns/remotable_spec.rb b/spec/models/concerns/remotable_spec.rb index 9cc849ded..ca2d65d2d 100644 --- a/spec/models/concerns/remotable_spec.rb +++ b/spec/models/concerns/remotable_spec.rb @@ -194,7 +194,9 @@ RSpec.describe Remotable do let(:error_class) { error_class } it 'calls Rails.logger.debug' do - expect(Rails.logger).to receive(:debug).with(/^Error fetching remote #{hoge}: /) + expect(Rails.logger).to receive(:debug) do |&block| + expect(block.call).to match(/^Error fetching remote #{hoge}: /) + end foo.hoge_remote_url = url end end -- cgit From cec005068f25c6487331a8437e69f29d5bef3d60 Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Tue, 7 Feb 2023 18:58:18 -0500 Subject: Apply Rubocop Performance/RedundantBlockCall (#23440) --- app/models/trends/history.rb | 2 +- app/workers/import/relationship_worker.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/trends/history.rb b/app/models/trends/history.rb index 74723e35c..03d62103f 100644 --- a/app/models/trends/history.rb +++ b/app/models/trends/history.rb @@ -88,7 +88,7 @@ class Trends::History def each(&block) if block_given? - (0...7).map { |i| block.call(get(i.days.ago)) } + (0...7).map { |i| yield(get(i.days.ago)) } else to_enum(:each) end diff --git a/app/workers/import/relationship_worker.rb b/app/workers/import/relationship_worker.rb index 6791b15c3..c2728c196 100644 --- a/app/workers/import/relationship_worker.rb +++ b/app/workers/import/relationship_worker.rb @@ -49,7 +49,7 @@ class Import::RelationshipWorker .with_error_handler { |error, handle| error.is_a?(HTTP::Error) || error.is_a?(OpenSSL::SSL::SSLError) ? handle.call(error) : raise(error) } .run else - block.call + yield end end end -- cgit From 8c1b65c7ddb9d49cb33c15c9a92dbfefebe868c6 Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Wed, 8 Feb 2023 01:06:50 -0500 Subject: Apply Rubocop Style/RedundantAssignment (#23452) --- app/models/concerns/omniauthable.rb | 3 +-- app/models/setting.rb | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'app/models') diff --git a/app/models/concerns/omniauthable.rb b/app/models/concerns/omniauthable.rb index feac0a1f5..7d54e9d6d 100644 --- a/app/models/concerns/omniauthable.rb +++ b/app/models/concerns/omniauthable.rb @@ -97,8 +97,7 @@ module Omniauthable def ensure_valid_username(starting_username) starting_username = starting_username.split('@')[0] temp_username = starting_username.gsub(/[^a-z0-9_]+/i, '') - validated_username = temp_username.truncate(30, omission: '') - validated_username + temp_username.truncate(30, omission: '') end end end diff --git a/app/models/setting.rb b/app/models/setting.rb index 4bcaa060f..c6558d692 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -23,7 +23,7 @@ class Setting < RailsSettings::Base def [](key) return super(key) unless rails_initialized? - val = Rails.cache.fetch(cache_key(key, nil)) do + Rails.cache.fetch(cache_key(key, nil)) do db_val = object(key) if db_val @@ -35,7 +35,6 @@ class Setting < RailsSettings::Base default_settings[key] end end - val end def all_as_records -- cgit From f68bb52556fe90d7adad8db9ba8b801a22281f30 Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Wed, 8 Feb 2023 01:07:36 -0500 Subject: Apply Rubocop Style/NegatedIfElseCondition (#23451) --- app/controllers/api/v1/streaming_controller.rb | 6 +++--- app/models/user.rb | 2 +- app/services/fetch_oembed_service.rb | 2 +- app/services/verify_link_service.rb | 2 +- lib/tasks/mastodon.rake | 12 ++++++------ 5 files changed, 12 insertions(+), 12 deletions(-) (limited to 'app/models') diff --git a/app/controllers/api/v1/streaming_controller.rb b/app/controllers/api/v1/streaming_controller.rb index 7cd60615a..b23a60170 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 end end diff --git a/app/models/user.rb b/app/models/user.rb index d40044da3..c767f8984 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -265,7 +265,7 @@ class User < ApplicationRecord end def inactive_message - !approved? ? :pending : super + approved? ? super : :pending end def approve! diff --git a/app/services/fetch_oembed_service.rb b/app/services/fetch_oembed_service.rb index 7d0879c79..9851ac098 100644 --- a/app/services/fetch_oembed_service.rb +++ b/app/services/fetch_oembed_service.rb @@ -82,7 +82,7 @@ class FetchOEmbedService return if @endpoint_url.blank? body = Request.new(:get, @endpoint_url).perform do |res| - res.code != 200 ? nil : res.body_with_limit + res.code == 200 ? res.body_with_limit : nil end validate(parse_for_format(body)) if body.present? diff --git a/app/services/verify_link_service.rb b/app/services/verify_link_service.rb index f83a664d4..707aeb4e0 100644 --- a/app/services/verify_link_service.rb +++ b/app/services/verify_link_service.rb @@ -19,7 +19,7 @@ class VerifyLinkService < BaseService def perform_request! @body = Request.new(:get, @url).add_headers('Accept' => 'text/html').perform do |res| - res.code != 200 ? nil : res.body_with_limit + res.code == 200 ? res.body_with_limit : nil end end diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake index 876383d7f..1184e5273 100644 --- a/lib/tasks/mastodon.rake +++ b/lib/tasks/mastodon.rake @@ -463,10 +463,10 @@ namespace :mastodon do prompt.say 'Running `RAILS_ENV=production rails db:setup` ...' prompt.say "\n\n" - if !system(env.transform_values(&:to_s).merge({ 'RAILS_ENV' => 'production', 'SAFETY_ASSURED' => '1' }), 'rails db:setup') - prompt.error 'That failed! Perhaps your configuration is not right' - else + if system(env.transform_values(&:to_s).merge({ 'RAILS_ENV' => 'production', 'SAFETY_ASSURED' => '1' }), 'rails db:setup') prompt.ok 'Done!' + else + prompt.error 'That failed! Perhaps your configuration is not right' end end @@ -479,10 +479,10 @@ namespace :mastodon do prompt.say 'Running `RAILS_ENV=production rails assets:precompile` ...' prompt.say "\n\n" - if !system(env.transform_values(&:to_s).merge({ 'RAILS_ENV' => 'production' }), 'rails assets:precompile') - prompt.error 'That failed! Maybe you need swap space?' - else + if system(env.transform_values(&:to_s).merge({ 'RAILS_ENV' => 'production' }), 'rails assets:precompile') prompt.say 'Done!' + else + prompt.error 'That failed! Maybe you need swap space?' end end end -- cgit From 0d1f192c54ab65a4a1c938553e5d87be65a966e8 Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Wed, 8 Feb 2023 04:36:23 -0500 Subject: Apply Rubocop Performance/BlockGivenWithExplicitBlock (#23441) * Apply Rubocop Performance/BlockGivenWithExplicitBlock * Unprefix used block parameter --- app/helpers/application_helper.rb | 4 ++-- app/helpers/jsonld_helper.rb | 4 ++-- app/lib/extractor.rb | 2 +- app/models/trends/history.rb | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'app/models') diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 4c20f1e14..b2687eddd 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -67,7 +67,7 @@ module ApplicationHelper def link_to_login(name = nil, html_options = nil, &block) target = new_user_session_path - html_options = name if block_given? + html_options = name if block if omniauth_only? && Devise.mappings[:user].omniauthable? && User.omniauth_providers.size == 1 target = omniauth_authorize_path(:user, User.omniauth_providers[0]) @@ -75,7 +75,7 @@ module ApplicationHelper html_options[:method] = :post end - if block_given? + if block link_to(target, html_options, &block) else link_to(name, target, html_options) diff --git a/app/helpers/jsonld_helper.rb b/app/helpers/jsonld_helper.rb index 102e4b132..e5787fd47 100644 --- a/app/helpers/jsonld_helper.rb +++ b/app/helpers/jsonld_helper.rb @@ -213,7 +213,7 @@ module JsonLdHelper end end - def load_jsonld_context(url, _options = {}, &_block) + def load_jsonld_context(url, _options = {}, &block) json = Rails.cache.fetch("jsonld:context:#{url}", expires_in: 30.days, raw: true) do request = Request.new(:get, url) request.add_headers('Accept' => 'application/ld+json') @@ -226,6 +226,6 @@ module JsonLdHelper doc = JSON::LD::API::RemoteDocument.new(json, documentUrl: url) - block_given? ? yield(doc) : doc + block ? yield(doc) : doc end end diff --git a/app/lib/extractor.rb b/app/lib/extractor.rb index aea60dae5..ead4cdddd 100644 --- a/app/lib/extractor.rb +++ b/app/lib/extractor.rb @@ -18,7 +18,7 @@ module Extractor return [] if entities.empty? entities = remove_overlapping_entities(entities) - entities.each(&block) if block_given? + entities.each(&block) if block entities end diff --git a/app/models/trends/history.rb b/app/models/trends/history.rb index 03d62103f..83532e7bc 100644 --- a/app/models/trends/history.rb +++ b/app/models/trends/history.rb @@ -87,7 +87,7 @@ class Trends::History end def each(&block) - if block_given? + if block (0...7).map { |i| yield(get(i.days.ago)) } else to_enum(:each) -- cgit From 0592937264d7a8cb4f1ea56be403f48e0801b2b7 Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Wed, 8 Feb 2023 04:39:57 -0500 Subject: Apply Rubocop Rails/WhereNot (#23448) * Apply Rubocop Rails/WhereNot * Update spec for where.not --- app/lib/vacuum/access_tokens_vacuum.rb | 4 ++-- app/models/session_activation.rb | 2 +- spec/models/session_activation_spec.rb | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'app/models') diff --git a/app/lib/vacuum/access_tokens_vacuum.rb b/app/lib/vacuum/access_tokens_vacuum.rb index 4f3878027..7b91f74a5 100644 --- a/app/lib/vacuum/access_tokens_vacuum.rb +++ b/app/lib/vacuum/access_tokens_vacuum.rb @@ -9,10 +9,10 @@ class Vacuum::AccessTokensVacuum private def vacuum_revoked_access_tokens! - Doorkeeper::AccessToken.where('revoked_at IS NOT NULL').where('revoked_at < NOW()').delete_all + Doorkeeper::AccessToken.where.not(revoked_at: nil).where('revoked_at < NOW()').delete_all end def vacuum_revoked_access_grants! - Doorkeeper::AccessGrant.where('revoked_at IS NOT NULL').where('revoked_at < NOW()').delete_all + Doorkeeper::AccessGrant.where.not(revoked_at: nil).where('revoked_at < NOW()').delete_all end end diff --git a/app/models/session_activation.rb b/app/models/session_activation.rb index 3a59bad93..0b7fa6fe4 100644 --- a/app/models/session_activation.rb +++ b/app/models/session_activation.rb @@ -59,7 +59,7 @@ class SessionActivation < ApplicationRecord end def exclusive(id) - where('session_id != ?', id).destroy_all + where.not(session_id: id).destroy_all end end diff --git a/spec/models/session_activation_spec.rb b/spec/models/session_activation_spec.rb index 450dc1399..8db06c622 100644 --- a/spec/models/session_activation_spec.rb +++ b/spec/models/session_activation_spec.rb @@ -118,8 +118,8 @@ RSpec.describe SessionActivation, type: :model do let(:id) { '1' } it 'calls where.destroy_all' do - expect(described_class).to receive_message_chain(:where, :destroy_all) - .with('session_id != ?', id).with(no_args) + expect(described_class).to receive_message_chain(:where, :not, :destroy_all) + .with(session_id: id).with(no_args) described_class.exclusive(id) end -- cgit From 67de888bad9b045787dd8fe6db77658b84137426 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 10 Feb 2023 10:20:43 +0100 Subject: Fix server status URL being a required server setting (#23499) --- app/models/form/admin_settings.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index 001caa376..070478e8e 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -69,7 +69,7 @@ class Form::AdminSettings validates :show_domain_blocks_rationale, inclusion: { in: %w(disabled users all) }, if: -> { defined?(@show_domain_blocks_rationale) } validates :media_cache_retention_period, :content_cache_retention_period, :backups_retention_period, numericality: { only_integer: true }, allow_blank: true, if: -> { defined?(@media_cache_retention_period) || defined?(@content_cache_retention_period) || defined?(@backups_retention_period) } validates :site_short_description, length: { maximum: 200 }, if: -> { defined?(@site_short_description) } - validates :status_page_url, url: true + validates :status_page_url, url: true, allow_blank: true validate :validate_site_uploads KEYS.each do |key| -- cgit From a9c220242bcc5f3d5e4c8ea92483f6b626a30ffa Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 10 Feb 2023 11:14:58 +0100 Subject: Fix admin-set follow recommandations being case-sensitive (#23500) Fixes #23472 --- app/models/account_suggestions/setting_source.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/account_suggestions/setting_source.rb b/app/models/account_suggestions/setting_source.rb index be9eff233..7b8873e0c 100644 --- a/app/models/account_suggestions/setting_source.rb +++ b/app/models/account_suggestions/setting_source.rb @@ -54,7 +54,7 @@ class AccountSuggestions::SettingSource < AccountSuggestions::Source next if username.blank? - [username, domain] + [username.downcase, domain&.downcase] end.compact end @@ -63,6 +63,6 @@ class AccountSuggestions::SettingSource < AccountSuggestions::Source end def to_ordered_list_key(account) - [account.username, account.domain] + [account.username.downcase, account.domain&.downcase] end end -- cgit From fb8503e861b630728ead4be847309f1fd7c03dd4 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Feb 2023 23:30:27 -0800 Subject: Upgrade to Ruby 3.2 (#22928) Co-authored-by: Matthew Ford --- .circleci/config.yml | 18 ++++++++++-------- .github/workflows/check-i18n.yml | 2 +- .ruby-version | 2 +- Dockerfile | 2 +- Gemfile | 6 +++--- Gemfile.lock | 32 ++++++++++++++++++++++---------- app/models/backup.rb | 2 +- 7 files changed, 39 insertions(+), 25 deletions(-) (limited to 'app/models') diff --git a/.circleci/config.yml b/.circleci/config.yml index fabb6967e..0b3123893 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -46,7 +46,7 @@ commands: name: Set bundler settings - ruby/install-deps: bundler-version: '2.3.26' - key: ruby<< parameters.ruby-version >>-gems-v1 + key: ruby<< parameters.ruby-version >>-gems-v2 wait-db: steps: - run: @@ -56,14 +56,14 @@ commands: jobs: build: docker: - - image: cimg/ruby:3.0-node + - image: cimg/ruby:3.2-node environment: RAILS_ENV: test steps: - checkout - install-system-dependencies - install-ruby-dependencies: - ruby-version: '3.0' + ruby-version: '3.2' - node/install-packages: cache-version: v1 pkg-manager: yarn @@ -95,7 +95,7 @@ jobs: - checkout - install-system-dependencies - run: - command: sudo apt-get install -y ffmpeg imagemagick libpam-dev + command: sudo apt-get install -y ffmpeg imagemagick libmagickcore-dev libmagickwand-dev libjpeg-dev libpng-dev libtiff-dev libwebp-dev libpam-dev name: Install additional system dependencies - run: command: bundle config with 'pam_authentication' @@ -113,12 +113,12 @@ jobs: test-migrations: executor: name: default - ruby-version: '3.0' + ruby-version: '3.2' steps: - checkout - install-system-dependencies - install-ruby-dependencies: - ruby-version: '3.0' + ruby-version: '3.2' - wait-db - run: command: ./bin/rails db:create @@ -151,12 +151,12 @@ jobs: test-two-step-migrations: executor: name: default - ruby-version: '3.0' + ruby-version: '3.2' steps: - checkout - install-system-dependencies - install-ruby-dependencies: - ruby-version: '3.0' + ruby-version: '3.2' - wait-db - run: command: ./bin/rails db:create @@ -206,6 +206,8 @@ workflows: ruby-version: - '2.7' - '3.0' + - '3.1' + - '3.2' name: test-ruby<< matrix.ruby-version >> requires: - build diff --git a/.github/workflows/check-i18n.yml b/.github/workflows/check-i18n.yml index b2e619786..aa2ec0394 100644 --- a/.github/workflows/check-i18n.yml +++ b/.github/workflows/check-i18n.yml @@ -14,7 +14,7 @@ permissions: jobs: check-i18n: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 diff --git a/.ruby-version b/.ruby-version index eca690e73..e4604e3af 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.0.5 +3.2.1 diff --git a/Dockerfile b/Dockerfile index 04e3b58b1..c2b18ce88 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # This needs to be bullseye-slim because the Ruby image is built on bullseye-slim ARG NODE_VERSION="16.19-bullseye-slim" -FROM ghcr.io/moritzheiber/ruby-jemalloc:3.0.5-slim as ruby +FROM ghcr.io/moritzheiber/ruby-jemalloc:3.2.1-slim as ruby FROM node:${NODE_VERSION} as build COPY --link --from=ruby /opt/ruby /opt/ruby diff --git a/Gemfile b/Gemfile index 961926c53..3a1f3a8c4 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ # frozen_string_literal: true source 'https://rubygems.org' -ruby '>= 2.7.0', '< 3.1.0' +ruby '>= 2.7.0', '< 3.3.0' gem 'pkg-config', '~> 1.5' gem 'rexml', '~> 3.2' @@ -21,7 +21,7 @@ gem 'dotenv-rails', '~> 2.8' gem 'aws-sdk-s3', '~> 1.119', require: false gem 'fog-core', '<= 2.4.0' gem 'fog-openstack', '~> 0.3', require: false -gem 'kt-paperclip', '~> 7.1' +gem 'kt-paperclip', '~> 7.1', github: 'kreeti/kt-paperclip', ref: '11abf222dc31bff71160a1d138b445214f434b2b' gem 'blurhash', '~> 0.1' gem 'active_model_serializers', '~> 0.10' @@ -72,7 +72,7 @@ gem 'premailer-rails' gem 'rack-attack', '~> 6.6' gem 'rack-cors', '~> 1.1', require: 'rack/cors' gem 'rails-i18n', '~> 6.0' -gem 'rails-settings-cached', '~> 0.6' +gem 'rails-settings-cached', '~> 0.6', git: 'https://github.com/mastodon/rails-settings-cached.git', branch: 'v0.6.6-aliases-true' gem 'redcarpet', '~> 3.6' gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis'] gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock' diff --git a/Gemfile.lock b/Gemfile.lock index 26800af2c..fbe09b290 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,6 +7,26 @@ GIT hkdf (~> 0.2) jwt (~> 2.0) +GIT + remote: https://github.com/kreeti/kt-paperclip.git + revision: 11abf222dc31bff71160a1d138b445214f434b2b + ref: 11abf222dc31bff71160a1d138b445214f434b2b + specs: + kt-paperclip (7.1.1) + activemodel (>= 4.2.0) + activesupport (>= 4.2.0) + marcel (~> 1.0.1) + mime-types + terrapin (~> 0.6.0) + +GIT + remote: https://github.com/mastodon/rails-settings-cached.git + revision: 86328ef0bd04ce21cc0504ff5e334591e8c2ccab + branch: v0.6.6-aliases-true + specs: + rails-settings-cached (0.6.6) + rails (>= 4.2.0) + GEM remote: https://rubygems.org/ specs: @@ -357,12 +377,6 @@ GEM activerecord kaminari-core (= 1.2.2) kaminari-core (1.2.2) - kt-paperclip (7.1.1) - activemodel (>= 4.2.0) - activesupport (>= 4.2.0) - marcel (~> 1.0.1) - mime-types - terrapin (~> 0.6.0) launchy (2.5.0) addressable (~> 2.7) letter_opener (1.8.1) @@ -540,8 +554,6 @@ GEM rails-i18n (6.0.0) i18n (>= 0.7, < 2) railties (>= 6.0.0, < 7) - rails-settings-cached (0.6.6) - rails (>= 4.2.0) railties (6.1.7.2) actionpack (= 6.1.7.2) activesupport (= 6.1.7.2) @@ -811,7 +823,7 @@ DEPENDENCIES json-ld-preloaded (~> 3.2) json-schema (~> 3.0) kaminari (~> 1.2) - kt-paperclip (~> 7.1) + kt-paperclip (~> 7.1)! letter_opener (~> 1.8) letter_opener_web (~> 2.0) link_header (~> 0.0) @@ -850,7 +862,7 @@ DEPENDENCIES rails (~> 6.1.7) rails-controller-testing (~> 1.0) rails-i18n (~> 6.0) - rails-settings-cached (~> 0.6) + rails-settings-cached (~> 0.6)! rdf-normalize (~> 0.5) redcarpet (~> 3.6) redis (~> 4.5) diff --git a/app/models/backup.rb b/app/models/backup.rb index d242fd62c..277b9395b 100644 --- a/app/models/backup.rb +++ b/app/models/backup.rb @@ -18,5 +18,5 @@ class Backup < ApplicationRecord belongs_to :user, inverse_of: :backups has_attached_file :dump - do_not_validate_attachment_file_type :dump + validates_attachment_content_type :dump, content_type: /\Aapplication/ end -- cgit From 669f6d2c0af969268c76e389ed626bce0cc9f998 Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Fri, 17 Feb 2023 16:56:20 -0500 Subject: Run rubocop formatting except line length (#23632) --- .rubocop_todo.yml | 277 +-------------------- app/lib/activitypub/activity/create.rb | 4 +- app/models/concerns/expireable.rb | 2 +- app/services/activitypub/fetch_replies_service.rb | 2 +- .../20161006213403_rails_settings_migration.rb | 10 +- ...uses_for_api_v1_accounts_account_id_statuses.rb | 8 +- .../20190306145741_add_lock_version_to_polls.rb | 1 - ...20190807135426_add_comments_to_domain_blocks.rb | 1 - ...200312162302_add_status_ids_to_announcements.rb | 1 - ...00510181721_remove_duplicated_indexes_pghero.rb | 1 - db/migrate/20200628133322_create_account_notes.rb | 1 - ...340_create_account_statuses_cleanup_policies.rb | 1 - ...0729171123_fix_custom_filter_keywords_id_seq.rb | 2 +- lib/paperclip/attachment_extensions.rb | 10 +- lib/tasks/mastodon.rake | 4 +- spec/config/initializers/rack_attack_spec.rb | 10 +- .../controllers/admin/dashboard_controller_spec.rb | 8 +- .../api/v1/accounts/credentials_controller_spec.rb | 2 +- spec/controllers/api/v1/reports_controller_spec.rb | 2 +- .../favourited_by_accounts_controller_spec.rb | 2 +- .../reblogged_by_accounts_controller_spec.rb | 2 +- .../api/v2/filters/statuses_controller_spec.rb | 4 +- spec/controllers/auth/sessions_controller_spec.rb | 6 +- .../authorize_interactions_controller_spec.rb | 1 - .../settings/applications_controller_spec.rb | 2 +- .../confirmations_controller_spec.rb | 1 - .../webauthn_credentials_controller_spec.rb | 2 +- .../well_known/host_meta_controller_spec.rb | 12 +- .../custom_filter_keyword_fabricator.rb | 2 +- spec/fabricators/ip_block_fabricator.rb | 2 +- spec/fabricators/poll_vote_fabricator.rb | 2 +- spec/fabricators/status_edit_fabricator.rb | 2 +- spec/fabricators/system_key_fabricator.rb | 1 - spec/lib/activitypub/activity/create_spec.rb | 1 - spec/lib/extractor_spec.rb | 8 +- spec/lib/fast_ip_map_spec.rb | 2 +- spec/lib/link_details_extractor_spec.rb | 124 ++++----- spec/models/account/field_spec.rb | 4 +- spec/models/account_alias_spec.rb | 1 - .../models/account_statuses_cleanup_policy_spec.rb | 40 ++- spec/models/concerns/account_interactions_spec.rb | 2 +- spec/models/device_spec.rb | 1 - spec/models/encrypted_message_spec.rb | 1 - spec/models/export_spec.rb | 2 +- spec/models/login_activity_spec.rb | 1 - spec/models/one_time_key_spec.rb | 1 - spec/models/system_key_spec.rb | 1 - spec/models/trends/statuses_spec.rb | 2 +- spec/models/user_role_spec.rb | 2 +- spec/routing/api_routing_spec.rb | 72 +++--- spec/routing/well_known_routes_spec.rb | 8 +- spec/serializers/rest/account_serializer_spec.rb | 2 +- .../account_statuses_cleanup_service_spec.rb | 4 +- .../fetch_remote_status_service_spec.rb | 2 +- .../activitypub/process_account_service_spec.rb | 4 +- .../activitypub/process_collection_service_spec.rb | 12 +- .../process_status_update_service_spec.rb | 42 ++-- spec/services/bootstrap_timeline_service_spec.rb | 1 - spec/services/fetch_oembed_service_spec.rb | 1 - spec/services/import_service_spec.rb | 4 +- spec/services/remove_from_follwers_service_spec.rb | 2 +- spec/services/remove_status_service_spec.rb | 68 ++--- spec/services/resolve_account_service_spec.rb | 2 +- spec/services/resolve_url_service_spec.rb | 2 +- spec/services/update_status_service_spec.rb | 2 +- spec/support/stories/profile_stories.rb | 4 +- spec/validators/note_length_validator_spec.rb | 4 +- .../unreserved_username_validator_spec.rb | 6 +- .../activitypub/distribution_worker_spec.rb | 2 +- .../activitypub/move_distribution_worker_spec.rb | 8 +- .../accounts_statuses_cleanup_scheduler_spec.rb | 2 +- 71 files changed, 269 insertions(+), 566 deletions(-) (limited to 'app/models') diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index e3a42da5b..e24ce7e32 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit` -# on 2023-02-16 04:55:24 UTC using RuboCop version 1.45.1. +# on 2023-02-16 05:53:07 UTC using RuboCop version 1.45.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -14,53 +14,6 @@ Bundler/OrderedGems: Exclude: - 'Gemfile' -# Offense count: 5 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: with_first_argument, with_fixed_indentation -Layout/ArgumentAlignment: - Exclude: - - 'spec/models/account_statuses_cleanup_policy_spec.rb' - - 'spec/services/activitypub/process_collection_service_spec.rb' - - 'spec/services/activitypub/process_status_update_service_spec.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyleAlignWith. -# SupportedStylesAlignWith: either, start_of_block, start_of_line -Layout/BlockAlignment: - Exclude: - - 'spec/controllers/api/v1/accounts/credentials_controller_spec.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Layout/ClosingParenthesisIndentation: - Exclude: - - 'spec/controllers/auth/sessions_controller_spec.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowForAlignment. -Layout/CommentIndentation: - Exclude: - - 'db/migrate/20180514130000_improve_index_on_statuses_for_api_v1_accounts_account_id_statuses.rb' - -# Offense count: 22 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: leading, trailing -Layout/DotPosition: - Exclude: - - 'lib/paperclip/attachment_extensions.rb' - - 'spec/routing/api_routing_spec.rb' - - 'spec/routing/well_known_routes_spec.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Layout/ElseAlignment: - Exclude: - - 'db/migrate/20161006213403_rails_settings_migration.rb' - # Offense count: 81 # This cop supports safe autocorrection (--autocorrect). Layout/EmptyLineAfterGuardClause: @@ -183,73 +136,6 @@ Layout/EmptyLineAfterMagicComment: - 'spec/controllers/api/v1/accounts/statuses_controller_spec.rb' - 'spec/models/tag_spec.rb' -# Offense count: 3 -# This cop supports safe autocorrection (--autocorrect). -Layout/EmptyLines: - Exclude: - - 'spec/controllers/authorize_interactions_controller_spec.rb' - - 'spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb' - - 'spec/lib/activitypub/activity/create_spec.rb' - -# Offense count: 9 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: empty_lines, no_empty_lines -Layout/EmptyLinesAroundBlockBody: - Exclude: - - 'spec/fabricators/system_key_fabricator.rb' - - 'spec/models/account_alias_spec.rb' - - 'spec/models/device_spec.rb' - - 'spec/models/encrypted_message_spec.rb' - - 'spec/models/login_activity_spec.rb' - - 'spec/models/one_time_key_spec.rb' - - 'spec/models/system_key_spec.rb' - - 'spec/services/bootstrap_timeline_service_spec.rb' - - 'spec/services/fetch_oembed_service_spec.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyleAlignWith, Severity. -# SupportedStylesAlignWith: keyword, variable, start_of_line -Layout/EndAlignment: - Exclude: - - 'db/migrate/20161006213403_rails_settings_migration.rb' - -# Offense count: 19 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment. -Layout/ExtraSpacing: - Exclude: - - 'spec/config/initializers/rack_attack_spec.rb' - - 'spec/controllers/api/v2/filters/statuses_controller_spec.rb' - - 'spec/fabricators/custom_filter_keyword_fabricator.rb' - - 'spec/fabricators/poll_vote_fabricator.rb' - - 'spec/models/account_statuses_cleanup_policy_spec.rb' - - 'spec/services/activitypub/process_status_update_service_spec.rb' - - 'spec/services/import_service_spec.rb' - - 'spec/services/resolve_account_service_spec.rb' - - 'spec/services/resolve_url_service_spec.rb' - - 'spec/validators/note_length_validator_spec.rb' - - 'spec/validators/unreserved_username_validator_spec.rb' - - 'spec/workers/activitypub/move_distribution_worker_spec.rb' - -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: consistent, consistent_relative_to_receiver, special_for_inner_method_call, special_for_inner_method_call_in_parentheses -Layout/FirstArgumentIndentation: - Exclude: - - 'spec/services/remove_status_service_spec.rb' - -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: special_inside_parentheses, consistent, align_brackets -Layout/FirstArrayElementIndentation: - Exclude: - - 'spec/controllers/admin/dashboard_controller_spec.rb' - - 'spec/workers/activitypub/move_distribution_worker_spec.rb' - # Offense count: 113 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. @@ -276,49 +162,6 @@ Layout/HashAlignment: - 'spec/models/admin/account_action_spec.rb' - 'spec/models/concerns/account_interactions_spec.rb' -# Offense count: 3 -# This cop supports safe autocorrection (--autocorrect). -Layout/HeredocIndentation: - Exclude: - - 'spec/controllers/well_known/host_meta_controller_spec.rb' - - 'spec/lib/link_details_extractor_spec.rb' - -# Offense count: 5 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: normal, indented_internal_methods -Layout/IndentationConsistency: - Exclude: - - 'spec/controllers/api/v1/statuses/favourited_by_accounts_controller_spec.rb' - - 'spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb' - - 'spec/models/trends/statuses_spec.rb' - - 'spec/services/import_service_spec.rb' - -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: Width, AllowedPatterns. -Layout/IndentationWidth: - Exclude: - - 'db/migrate/20161006213403_rails_settings_migration.rb' - - 'spec/controllers/api/v1/accounts/credentials_controller_spec.rb' - - 'spec/services/account_statuses_cleanup_service_spec.rb' - - 'spec/services/import_service_spec.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowDoxygenCommentStyle, AllowGemfileRubyComment. -Layout/LeadingCommentSpace: - Exclude: - - 'lib/paperclip/attachment_extensions.rb' - -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AutoCorrect, EnforcedStyle. -# SupportedStyles: space, no_space -Layout/LineContinuationSpacing: - Exclude: - - 'spec/support/stories/profile_stories.rb' - # Offense count: 577 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns. @@ -326,124 +169,6 @@ Layout/LineContinuationSpacing: Layout/LineLength: Enabled: false -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: symmetrical, new_line, same_line -Layout/MultilineMethodCallBraceLayout: - Exclude: - - 'spec/models/account_statuses_cleanup_policy_spec.rb' - - 'spec/services/activitypub/process_status_update_service_spec.rb' - -# Offense count: 3 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator. -# SupportedStylesForExponentOperator: space, no_space -Layout/SpaceAroundOperators: - Exclude: - - 'spec/services/activitypub/fetch_remote_status_service_spec.rb' - - 'spec/validators/note_length_validator_spec.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. -# SupportedStyles: space, no_space -# SupportedStylesForEmptyBraces: space, no_space -Layout/SpaceBeforeBlockBraces: - Exclude: - - 'spec/controllers/api/v1/reports_controller_spec.rb' - -# Offense count: 3 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowForAlignment. -Layout/SpaceBeforeFirstArg: - Exclude: - - 'spec/fabricators/custom_filter_keyword_fabricator.rb' - - 'spec/fabricators/poll_vote_fabricator.rb' - - 'spec/models/concerns/account_interactions_spec.rb' - -# Offense count: 24 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets. -# SupportedStyles: space, no_space, compact -# SupportedStylesForEmptyBrackets: space, no_space -Layout/SpaceInsideArrayLiteralBrackets: - Exclude: - - 'db/migrate/20161006213403_rails_settings_migration.rb' - - 'spec/controllers/settings/applications_controller_spec.rb' - - 'spec/lib/extractor_spec.rb' - - 'spec/models/export_spec.rb' - - 'spec/services/activitypub/process_account_service_spec.rb' - - 'spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb' - -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters. -# SupportedStyles: space, no_space -# SupportedStylesForEmptyBraces: space, no_space -Layout/SpaceInsideBlockBraces: - Exclude: - - 'spec/lib/fast_ip_map_spec.rb' - - 'spec/models/user_role_spec.rb' - - 'spec/serializers/rest/account_serializer_spec.rb' - - 'spec/workers/activitypub/distribution_worker_spec.rb' - -# Offense count: 6 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. -# SupportedStyles: space, no_space, compact -# SupportedStylesForEmptyBraces: space, no_space -Layout/SpaceInsideHashLiteralBraces: - Exclude: - - 'app/lib/activitypub/activity/create.rb' - - 'app/services/activitypub/fetch_replies_service.rb' - - 'spec/services/activitypub/process_collection_service_spec.rb' - - 'spec/services/update_status_service_spec.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: space, compact, no_space -Layout/SpaceInsideParens: - Exclude: - - 'spec/validators/unreserved_username_validator_spec.rb' - -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: space, no_space -Layout/SpaceInsideStringInterpolation: - Exclude: - - 'spec/controllers/auth/sessions_controller_spec.rb' - - 'spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb' - - 'spec/services/activitypub/process_account_service_spec.rb' - -# Offense count: 8 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: final_newline, final_blank_line -Layout/TrailingEmptyLines: - Exclude: - - 'db/migrate/20190306145741_add_lock_version_to_polls.rb' - - 'db/migrate/20190807135426_add_comments_to_domain_blocks.rb' - - 'db/migrate/20200312162302_add_status_ids_to_announcements.rb' - - 'db/migrate/20200510181721_remove_duplicated_indexes_pghero.rb' - - 'db/migrate/20200628133322_create_account_notes.rb' - - 'db/migrate/20210722120340_create_account_statuses_cleanup_policies.rb' - - 'spec/fabricators/ip_block_fabricator.rb' - - 'spec/fabricators/status_edit_fabricator.rb' - -# Offense count: 7 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowInHeredoc. -Layout/TrailingWhitespace: - Exclude: - - 'app/models/concerns/expireable.rb' - - 'db/post_migrate/20220729171123_fix_custom_filter_keywords_id_seq.rb' - - 'lib/tasks/mastodon.rake' - - 'spec/models/account/field_spec.rb' - - 'spec/services/remove_from_follwers_service_spec.rb' - # Offense count: 14 # Configuration parameters: AllowedMethods, AllowedPatterns. Lint/AmbiguousBlockAssociation: diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 487b65223..f82112c02 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -327,7 +327,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def resolve_thread(status) return unless status.reply? && status.thread.nil? && Request.valid_url?(in_reply_to_uri) - ThreadResolveWorker.perform_async(status.id, in_reply_to_uri, { 'request_id' => @options[:request_id]}) + ThreadResolveWorker.perform_async(status.id, in_reply_to_uri, { 'request_id' => @options[:request_id] }) end def fetch_replies(status) @@ -338,7 +338,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity return unless replies.nil? uri = value_or_id(collection) - ActivityPub::FetchRepliesWorker.perform_async(status.id, uri, { 'request_id' => @options[:request_id]}) unless uri.nil? + ActivityPub::FetchRepliesWorker.perform_async(status.id, uri, { 'request_id' => @options[:request_id] }) unless uri.nil? end def conversation_from_uri(uri) diff --git a/app/models/concerns/expireable.rb b/app/models/concerns/expireable.rb index 4d902abcb..c64fc7d80 100644 --- a/app/models/concerns/expireable.rb +++ b/app/models/concerns/expireable.rb @@ -17,7 +17,7 @@ module Expireable end def expires_in=(interval) - self.expires_at = interval.present? ? interval.to_i.seconds.from_now : nil + self.expires_at = interval.present? ? interval.to_i.seconds.from_now : nil @expires_in = interval end diff --git a/app/services/activitypub/fetch_replies_service.rb b/app/services/activitypub/fetch_replies_service.rb index 18a27e851..4128df9ca 100644 --- a/app/services/activitypub/fetch_replies_service.rb +++ b/app/services/activitypub/fetch_replies_service.rb @@ -10,7 +10,7 @@ class ActivityPub::FetchRepliesService < BaseService @items = collection_items(collection_or_uri) return if @items.nil? - FetchReplyWorker.push_bulk(filtered_replies) { |reply_uri| [reply_uri, { 'request_id' => request_id}] } + FetchReplyWorker.push_bulk(filtered_replies) { |reply_uri| [reply_uri, { 'request_id' => request_id }] } @items end diff --git a/db/migrate/20161006213403_rails_settings_migration.rb b/db/migrate/20161006213403_rails_settings_migration.rb index 9d565cb5c..02932610c 100644 --- a/db/migrate/20161006213403_rails_settings_migration.rb +++ b/db/migrate/20161006213403_rails_settings_migration.rb @@ -1,8 +1,8 @@ MIGRATION_BASE_CLASS = if ActiveRecord::VERSION::MAJOR >= 5 - ActiveRecord::Migration[5.0] -else - ActiveRecord::Migration[4.2] -end + ActiveRecord::Migration[5.0] + else + ActiveRecord::Migration[4.2] + end class RailsSettingsMigration < MIGRATION_BASE_CLASS def self.up @@ -12,7 +12,7 @@ class RailsSettingsMigration < MIGRATION_BASE_CLASS t.references :target, null: false, polymorphic: true, index: { name: 'index_settings_on_target_type_and_target_id' } t.timestamps null: true end - add_index :settings, [ :target_type, :target_id, :var ], unique: true + add_index :settings, [:target_type, :target_id, :var], unique: true end def self.down diff --git a/db/migrate/20180514130000_improve_index_on_statuses_for_api_v1_accounts_account_id_statuses.rb b/db/migrate/20180514130000_improve_index_on_statuses_for_api_v1_accounts_account_id_statuses.rb index b29e62803..a3f883fcb 100644 --- a/db/migrate/20180514130000_improve_index_on_statuses_for_api_v1_accounts_account_id_statuses.rb +++ b/db/migrate/20180514130000_improve_index_on_statuses_for_api_v1_accounts_account_id_statuses.rb @@ -4,9 +4,9 @@ class ImproveIndexOnStatusesForApiV1AccountsAccountIdStatuses < ActiveRecord::Mi disable_ddl_transaction! def change - # These changes ware reverted by migration 20180514140000. - # add_index :statuses, [:account_id, :id, :visibility], where: 'visibility IN (0, 1, 2)', algorithm: :concurrently - # add_index :statuses, [:account_id, :id], where: 'visibility = 3', algorithm: :concurrently - # remove_index :statuses, column: [:account_id, :id, :visibility, :updated_at], order: { id: :desc }, algorithm: :concurrently, name: :index_statuses_20180106 + # These changes ware reverted by migration 20180514140000. + # add_index :statuses, [:account_id, :id, :visibility], where: 'visibility IN (0, 1, 2)', algorithm: :concurrently + # add_index :statuses, [:account_id, :id], where: 'visibility = 3', algorithm: :concurrently + # remove_index :statuses, column: [:account_id, :id, :visibility, :updated_at], order: { id: :desc }, algorithm: :concurrently, name: :index_statuses_20180106 end end diff --git a/db/migrate/20190306145741_add_lock_version_to_polls.rb b/db/migrate/20190306145741_add_lock_version_to_polls.rb index 5bb8cd3b4..c9fa471ad 100644 --- a/db/migrate/20190306145741_add_lock_version_to_polls.rb +++ b/db/migrate/20190306145741_add_lock_version_to_polls.rb @@ -21,4 +21,3 @@ class AddLockVersionToPolls < ActiveRecord::Migration[5.2] remove_column :polls, :lock_version end end - diff --git a/db/migrate/20190807135426_add_comments_to_domain_blocks.rb b/db/migrate/20190807135426_add_comments_to_domain_blocks.rb index b660a71ad..79b9f0212 100644 --- a/db/migrate/20190807135426_add_comments_to_domain_blocks.rb +++ b/db/migrate/20190807135426_add_comments_to_domain_blocks.rb @@ -4,4 +4,3 @@ class AddCommentsToDomainBlocks < ActiveRecord::Migration[5.2] add_column :domain_blocks, :public_comment, :text end end - diff --git a/db/migrate/20200312162302_add_status_ids_to_announcements.rb b/db/migrate/20200312162302_add_status_ids_to_announcements.rb index 42aa6513d..704d3773e 100644 --- a/db/migrate/20200312162302_add_status_ids_to_announcements.rb +++ b/db/migrate/20200312162302_add_status_ids_to_announcements.rb @@ -3,4 +3,3 @@ class AddStatusIdsToAnnouncements < ActiveRecord::Migration[5.2] add_column :announcements, :status_ids, :bigint, array: true end end - diff --git a/db/migrate/20200510181721_remove_duplicated_indexes_pghero.rb b/db/migrate/20200510181721_remove_duplicated_indexes_pghero.rb index 1d6ba1fe9..59bb1b9e2 100644 --- a/db/migrate/20200510181721_remove_duplicated_indexes_pghero.rb +++ b/db/migrate/20200510181721_remove_duplicated_indexes_pghero.rb @@ -19,4 +19,3 @@ class RemoveDuplicatedIndexesPghero < ActiveRecord::Migration[5.2] add_index :markers, :user_id, name: :index_markers_on_user_id unless index_exists?(:markers, :user_id, name: :index_markers_on_user_id) end end - diff --git a/db/migrate/20200628133322_create_account_notes.rb b/db/migrate/20200628133322_create_account_notes.rb index 664727e60..022e0ff3a 100644 --- a/db/migrate/20200628133322_create_account_notes.rb +++ b/db/migrate/20200628133322_create_account_notes.rb @@ -10,4 +10,3 @@ class CreateAccountNotes < ActiveRecord::Migration[5.2] end end end - diff --git a/db/migrate/20210722120340_create_account_statuses_cleanup_policies.rb b/db/migrate/20210722120340_create_account_statuses_cleanup_policies.rb index 28cfb6ef5..db168676a 100644 --- a/db/migrate/20210722120340_create_account_statuses_cleanup_policies.rb +++ b/db/migrate/20210722120340_create_account_statuses_cleanup_policies.rb @@ -17,4 +17,3 @@ class CreateAccountStatusesCleanupPolicies < ActiveRecord::Migration[6.1] end end end - diff --git a/db/post_migrate/20220729171123_fix_custom_filter_keywords_id_seq.rb b/db/post_migrate/20220729171123_fix_custom_filter_keywords_id_seq.rb index 7ed34a3ef..eb437c86c 100644 --- a/db/post_migrate/20220729171123_fix_custom_filter_keywords_id_seq.rb +++ b/db/post_migrate/20220729171123_fix_custom_filter_keywords_id_seq.rb @@ -5,7 +5,7 @@ class FixCustomFilterKeywordsIdSeq < ActiveRecord::Migration[6.1] def up # 20220613110711 manually inserts items with set `id` in the database, but - # we also need to bump the sequence number, otherwise + # we also need to bump the sequence number, otherwise safety_assured do execute <<-SQL.squish BEGIN; diff --git a/lib/paperclip/attachment_extensions.rb b/lib/paperclip/attachment_extensions.rb index d66a17623..7f82138aa 100644 --- a/lib/paperclip/attachment_extensions.rb +++ b/lib/paperclip/attachment_extensions.rb @@ -8,7 +8,7 @@ module Paperclip # monkey-patch to avoid unlinking too avoid unlinking source file too early # see https://github.com/kreeti/kt-paperclip/issues/64 - def post_process_style(name, style) #:nodoc: + def post_process_style(name, style) # :nodoc: raise "Style #{name} has no processors defined." if style.processors.blank? intermediate_files = [] @@ -16,16 +16,16 @@ module Paperclip # if we're processing the original, close + unlink the source tempfile intermediate_files << original if name == :original - @queued_for_write[name] = style.processors. - inject(original) do |file, processor| + @queued_for_write[name] = style.processors + .inject(original) do |file, processor| file = Paperclip.processor(processor).make(file, style.processor_options, self) intermediate_files << file unless file == original file end unadapted_file = @queued_for_write[name] - @queued_for_write[name] = Paperclip.io_adapters. - for(@queued_for_write[name], @options[:adapter_options]) + @queued_for_write[name] = Paperclip.io_adapters + .for(@queued_for_write[name], @options[:adapter_options]) unadapted_file.close if unadapted_file.respond_to?(:close) @queued_for_write[name] rescue Paperclip::Errors::NotIdentifiedByImageMagickError => e diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake index 1184e5273..477daa01b 100644 --- a/lib/tasks/mastodon.rake +++ b/lib/tasks/mastodon.rake @@ -286,13 +286,13 @@ namespace :mastodon do q.required true q.modify :strip end - + linksharing_access_key = prompt.ask('Storj Linksharing access key (uplink share --register --public --readonly=true --disallow-lists --not-after=none sj://bucket):') do |q| q.required true q.modify :strip end env['S3_ALIAS_HOST'] = "link.storjshare.io/raw/#{linksharing_access_key}/#{env['S3_BUCKET']}" - + when 'Google Cloud Storage' env['S3_ENABLED'] = 'true' env['S3_PROTOCOL'] = 'https' diff --git a/spec/config/initializers/rack_attack_spec.rb b/spec/config/initializers/rack_attack_spec.rb index 581021cb9..03695f5fd 100644 --- a/spec/config/initializers/rack_attack_spec.rb +++ b/spec/config/initializers/rack_attack_spec.rb @@ -35,12 +35,12 @@ describe Rack::Attack do let(:request) { ->() { post path, {}, 'REMOTE_ADDR' => remote_ip } } context 'for exact path' do - let(:path) { '/auth' } + let(:path) { '/auth' } it_behaves_like 'throttled endpoint' end context 'for path with format' do - let(:path) { '/auth.html' } + let(:path) { '/auth.html' } it_behaves_like 'throttled endpoint' end end @@ -50,7 +50,7 @@ describe Rack::Attack do let(:request) { ->() { post path, {}, 'REMOTE_ADDR' => remote_ip } } context 'for exact path' do - let(:path) { '/api/v1/accounts' } + let(:path) { '/api/v1/accounts' } it_behaves_like 'throttled endpoint' end @@ -70,12 +70,12 @@ describe Rack::Attack do let(:request) { ->() { post path, {}, 'REMOTE_ADDR' => remote_ip } } context 'for exact path' do - let(:path) { '/auth/sign_in' } + let(:path) { '/auth/sign_in' } it_behaves_like 'throttled endpoint' end context 'for path with format' do - let(:path) { '/auth/sign_in.html' } + let(:path) { '/auth/sign_in.html' } it_behaves_like 'throttled endpoint' end end diff --git a/spec/controllers/admin/dashboard_controller_spec.rb b/spec/controllers/admin/dashboard_controller_spec.rb index 6231a09a2..ab3738fcd 100644 --- a/spec/controllers/admin/dashboard_controller_spec.rb +++ b/spec/controllers/admin/dashboard_controller_spec.rb @@ -8,10 +8,10 @@ describe Admin::DashboardController, type: :controller do describe 'GET #index' do before do allow(Admin::SystemCheck).to receive(:perform).and_return([ - Admin::SystemCheck::Message.new(:database_schema_check), - Admin::SystemCheck::Message.new(:rules_check, nil, admin_rules_path), - Admin::SystemCheck::Message.new(:sidekiq_process_check, 'foo, bar'), - ]) + Admin::SystemCheck::Message.new(:database_schema_check), + Admin::SystemCheck::Message.new(:rules_check, nil, admin_rules_path), + Admin::SystemCheck::Message.new(:sidekiq_process_check, 'foo, bar'), + ]) sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')) end diff --git a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb index b2557d957..89cc8acad 100644 --- a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb @@ -70,7 +70,7 @@ describe Api::V1::Accounts::CredentialsController do it 'returns http success' do expect(response).to have_http_status(200) end - end + end describe 'with invalid data' do before do diff --git a/spec/controllers/api/v1/reports_controller_spec.rb b/spec/controllers/api/v1/reports_controller_spec.rb index dbc64e704..78a72b95b 100644 --- a/spec/controllers/api/v1/reports_controller_spec.rb +++ b/spec/controllers/api/v1/reports_controller_spec.rb @@ -20,7 +20,7 @@ RSpec.describe Api::V1::ReportsController, type: :controller do let(:target_account) { status.account } let(:category) { nil } let(:forward) { nil } - let(:rule_ids){ nil } + let(:rule_ids) { nil } before do allow(AdminMailer).to receive(:new_report).and_return(double('email', deliver_later: nil)) diff --git a/spec/controllers/api/v1/statuses/favourited_by_accounts_controller_spec.rb b/spec/controllers/api/v1/statuses/favourited_by_accounts_controller_spec.rb index 7cc77f430..4dcaba6bd 100644 --- a/spec/controllers/api/v1/statuses/favourited_by_accounts_controller_spec.rb +++ b/spec/controllers/api/v1/statuses/favourited_by_accounts_controller_spec.rb @@ -31,7 +31,7 @@ RSpec.describe Api::V1::Statuses::FavouritedByAccountsController, type: :control it 'returns accounts who favorited the status' do get :index, params: { status_id: status.id, limit: 2 } expect(body_as_json.size).to eq 2 - expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s]) + expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s]) end it 'does not return blocked users' do diff --git a/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb b/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb index 8d4a6f91c..dc36d4ca0 100644 --- a/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb +++ b/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb @@ -31,7 +31,7 @@ RSpec.describe Api::V1::Statuses::RebloggedByAccountsController, type: :controll it 'returns accounts who reblogged the status' do get :index, params: { status_id: status.id, limit: 2 } expect(body_as_json.size).to eq 2 - expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s]) + expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s]) end it 'does not return blocked users' do diff --git a/spec/controllers/api/v2/filters/statuses_controller_spec.rb b/spec/controllers/api/v2/filters/statuses_controller_spec.rb index 9740c1eb3..969b2ea73 100644 --- a/spec/controllers/api/v2/filters/statuses_controller_spec.rb +++ b/spec/controllers/api/v2/filters/statuses_controller_spec.rb @@ -64,7 +64,7 @@ RSpec.describe Api::V2::Filters::StatusesController, type: :controller do end describe 'GET #show' do - let(:scopes) { 'read:filters' } + let(:scopes) { 'read:filters' } let!(:status_filter) { Fabricate(:custom_filter_status, custom_filter: filter) } before do @@ -90,7 +90,7 @@ RSpec.describe Api::V2::Filters::StatusesController, type: :controller do end describe 'DELETE #destroy' do - let(:scopes) { 'write:filters' } + let(:scopes) { 'write:filters' } let(:status_filter) { Fabricate(:custom_filter_status, custom_filter: filter) } before do diff --git a/spec/controllers/auth/sessions_controller_spec.rb b/spec/controllers/auth/sessions_controller_spec.rb index d3db7aa1a..64433ddf4 100644 --- a/spec/controllers/auth/sessions_controller_spec.rb +++ b/spec/controllers/auth/sessions_controller_spec.rb @@ -339,11 +339,11 @@ RSpec.describe Auth::SessionsController, type: :controller do external_id: public_key_credential.id, public_key: public_key_credential.public_key, sign_count: '1000' - ) + ) user.webauthn_credentials.take end - let(:domain) { "#{Rails.configuration.x.use_https ? 'https' : 'http' }://#{Rails.configuration.x.web_domain}" } + let(:domain) { "#{Rails.configuration.x.use_https ? 'https' : 'http'}://#{Rails.configuration.x.web_domain}" } let(:fake_client) { WebAuthn::FakeClient.new(domain) } @@ -400,7 +400,7 @@ RSpec.describe Auth::SessionsController, type: :controller do describe 'GET #webauthn_options' do context 'with WebAuthn and OTP enabled as second factor' do - let(:domain) { "#{Rails.configuration.x.use_https ? 'https' : 'http' }://#{Rails.configuration.x.web_domain}" } + let(:domain) { "#{Rails.configuration.x.use_https ? 'https' : 'http'}://#{Rails.configuration.x.web_domain}" } let(:fake_client) { WebAuthn::FakeClient.new(domain) } diff --git a/spec/controllers/authorize_interactions_controller_spec.rb b/spec/controllers/authorize_interactions_controller_spec.rb index 44f52df69..e52103941 100644 --- a/spec/controllers/authorize_interactions_controller_spec.rb +++ b/spec/controllers/authorize_interactions_controller_spec.rb @@ -99,7 +99,6 @@ describe AuthorizeInteractionsController do allow(ResolveAccountService).to receive(:new).and_return(service) allow(service).to receive(:call).with('user@hostname').and_return(target_account) - post :create, params: { acct: 'acct:user@hostname' } expect(account.following?(target_account)).to be true diff --git a/spec/controllers/settings/applications_controller_spec.rb b/spec/controllers/settings/applications_controller_spec.rb index 1292e9ff8..9074574e4 100644 --- a/spec/controllers/settings/applications_controller_spec.rb +++ b/spec/controllers/settings/applications_controller_spec.rb @@ -73,7 +73,7 @@ describe Settings::ApplicationsController do name: 'My New App', redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', website: 'http://google.com', - scopes: [ 'read', 'write', 'follow' ] + scopes: ['read', 'write', 'follow'] } } response diff --git a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb index 569c8322b..0b807b280 100644 --- a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb +++ b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb @@ -5,7 +5,6 @@ require 'rails_helper' describe Settings::TwoFactorAuthentication::ConfirmationsController do render_views - shared_examples 'renders :new' do it 'renders the new view' do subject diff --git a/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb index fe53b4dfc..06989ffd2 100644 --- a/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb +++ b/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb @@ -7,7 +7,7 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do render_views let(:user) { Fabricate(:user) } - let(:domain) { "#{Rails.configuration.x.use_https ? 'https' : 'http' }://#{Rails.configuration.x.web_domain}" } + let(:domain) { "#{Rails.configuration.x.use_https ? 'https' : 'http'}://#{Rails.configuration.x.web_domain}" } let(:fake_client) { WebAuthn::FakeClient.new(domain) } def add_webauthn_credential(user) diff --git a/spec/controllers/well_known/host_meta_controller_spec.rb b/spec/controllers/well_known/host_meta_controller_spec.rb index c02aa0d59..654bad406 100644 --- a/spec/controllers/well_known/host_meta_controller_spec.rb +++ b/spec/controllers/well_known/host_meta_controller_spec.rb @@ -9,12 +9,12 @@ describe WellKnown::HostMetaController, type: :controller do expect(response).to have_http_status(200) expect(response.media_type).to eq 'application/xrd+xml' - expect(response.body).to eq < - - - -XML + expect(response.body).to eq <<~XML + + + + + XML end end end diff --git a/spec/fabricators/custom_filter_keyword_fabricator.rb b/spec/fabricators/custom_filter_keyword_fabricator.rb index 0f101dcd1..201566cbe 100644 --- a/spec/fabricators/custom_filter_keyword_fabricator.rb +++ b/spec/fabricators/custom_filter_keyword_fabricator.rb @@ -1,4 +1,4 @@ Fabricator(:custom_filter_keyword) do custom_filter - keyword 'discourse' + keyword 'discourse' end diff --git a/spec/fabricators/ip_block_fabricator.rb b/spec/fabricators/ip_block_fabricator.rb index 31dc336e6..1797f6877 100644 --- a/spec/fabricators/ip_block_fabricator.rb +++ b/spec/fabricators/ip_block_fabricator.rb @@ -3,4 +3,4 @@ Fabricator(:ip_block) do severity "" expires_at "2020-10-08 22:20:37" comment "MyText" -end \ No newline at end of file +end diff --git a/spec/fabricators/poll_vote_fabricator.rb b/spec/fabricators/poll_vote_fabricator.rb index 51f9b006e..c06e61f67 100644 --- a/spec/fabricators/poll_vote_fabricator.rb +++ b/spec/fabricators/poll_vote_fabricator.rb @@ -1,5 +1,5 @@ Fabricator(:poll_vote) do account poll - choice 0 + choice 0 end diff --git a/spec/fabricators/status_edit_fabricator.rb b/spec/fabricators/status_edit_fabricator.rb index 21b793747..3141759e5 100644 --- a/spec/fabricators/status_edit_fabricator.rb +++ b/spec/fabricators/status_edit_fabricator.rb @@ -4,4 +4,4 @@ Fabricator(:status_edit) do text "MyText" spoiler_text "MyText" media_attachments_changed false -end \ No newline at end of file +end diff --git a/spec/fabricators/system_key_fabricator.rb b/spec/fabricators/system_key_fabricator.rb index f808495e0..c744bb286 100644 --- a/spec/fabricators/system_key_fabricator.rb +++ b/spec/fabricators/system_key_fabricator.rb @@ -1,3 +1,2 @@ Fabricator(:system_key) do - end diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index 1a25395fa..cd0f2df6e 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -408,7 +408,6 @@ RSpec.describe ActivityPub::Activity::Create do end end - context 'with media attachments with long description' do let(:object_json) do { diff --git a/spec/lib/extractor_spec.rb b/spec/lib/extractor_spec.rb index dba4bd0bb..9c9f5ef04 100644 --- a/spec/lib/extractor_spec.rb +++ b/spec/lib/extractor_spec.rb @@ -20,7 +20,7 @@ describe Extractor do text = '@screen_name' extracted = Extractor.extract_mentions_or_lists_with_indices(text) expect(extracted).to eq [ - { screen_name: 'screen_name', indices: [ 0, 12 ] } + { screen_name: 'screen_name', indices: [0, 12] } ] end @@ -44,19 +44,19 @@ describe Extractor do it 'does not exclude normal hash text before ://' do text = '#hashtag://' extracted = Extractor.extract_hashtags_with_indices(text) - expect(extracted).to eq [ { hashtag: 'hashtag', indices: [ 0, 8 ] } ] + expect(extracted).to eq [{ hashtag: 'hashtag', indices: [0, 8] }] end it 'excludes http://' do text = '#hashtaghttp://' extracted = Extractor.extract_hashtags_with_indices(text) - expect(extracted).to eq [ { hashtag: 'hashtag', indices: [ 0, 8 ] } ] + expect(extracted).to eq [{ hashtag: 'hashtag', indices: [0, 8] }] end it 'excludes https://' do text = '#hashtaghttps://' extracted = Extractor.extract_hashtags_with_indices(text) - expect(extracted).to eq [ { hashtag: 'hashtag', indices: [ 0, 8 ] } ] + expect(extracted).to eq [{ hashtag: 'hashtag', indices: [0, 8] }] end it 'yields hashtags if a block is given' do diff --git a/spec/lib/fast_ip_map_spec.rb b/spec/lib/fast_ip_map_spec.rb index c66f64828..78b3ddb05 100644 --- a/spec/lib/fast_ip_map_spec.rb +++ b/spec/lib/fast_ip_map_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' describe FastIpMap do describe '#include?' do - subject { described_class.new([IPAddr.new('20.4.0.0/16'), IPAddr.new('145.22.30.0/24'), IPAddr.new('189.45.86.3')])} + subject { described_class.new([IPAddr.new('20.4.0.0/16'), IPAddr.new('145.22.30.0/24'), IPAddr.new('189.45.86.3')]) } it 'returns true for an exact match' do expect(subject.include?(IPAddr.new('189.45.86.3'))).to be true diff --git a/spec/lib/link_details_extractor_spec.rb b/spec/lib/link_details_extractor_spec.rb index 7ea867c61..7eb15ced3 100644 --- a/spec/lib/link_details_extractor_spec.rb +++ b/spec/lib/link_details_extractor_spec.rb @@ -39,17 +39,17 @@ RSpec.describe LinkDetailsExtractor do let(:original_url) { 'https://example.com/page.html' } context 'and is wrapped in CDATA tags' do - let(:html) { <<-HTML } - - - - - - + let(:html) { <<~HTML } + + + + + + HTML describe '#title' do @@ -78,57 +78,57 @@ RSpec.describe LinkDetailsExtractor do end context 'but the first tag is invalid JSON' do - let(:html) { <<-HTML } - - - - - - - + let(:html) { <<~HTML } + + + + + + + HTML describe '#title' do diff --git a/spec/models/account/field_spec.rb b/spec/models/account/field_spec.rb index 0ac9769bc..40bbee025 100644 --- a/spec/models/account/field_spec.rb +++ b/spec/models/account/field_spec.rb @@ -97,7 +97,7 @@ RSpec.describe Account::Field, type: :model do expect(subject.verifiable?).to be false end end - + context 'for text which is blank' do let(:value) { '' } @@ -149,7 +149,7 @@ RSpec.describe Account::Field, type: :model do expect(subject.verifiable?).to be false end end - + context 'for text which is blank' do let(:value) { '' } diff --git a/spec/models/account_alias_spec.rb b/spec/models/account_alias_spec.rb index 27ec215aa..c48b804b2 100644 --- a/spec/models/account_alias_spec.rb +++ b/spec/models/account_alias_spec.rb @@ -1,5 +1,4 @@ require 'rails_helper' RSpec.describe AccountAlias, type: :model do - end diff --git a/spec/models/account_statuses_cleanup_policy_spec.rb b/spec/models/account_statuses_cleanup_policy_spec.rb index 684a1aa41..f11684516 100644 --- a/spec/models/account_statuses_cleanup_policy_spec.rb +++ b/spec/models/account_statuses_cleanup_policy_spec.rb @@ -16,16 +16,15 @@ RSpec.describe AccountStatusesCleanupPolicy, type: :model do context 'when widening a policy' do let!(:account_statuses_cleanup_policy) do Fabricate(:account_statuses_cleanup_policy, - account: account, - keep_direct: true, - keep_pinned: true, - keep_polls: true, - keep_media: true, - keep_self_fav: true, - keep_self_bookmark: true, - min_favs: 1, - min_reblogs: 1 - ) + account: account, + keep_direct: true, + keep_pinned: true, + keep_polls: true, + keep_media: true, + keep_self_fav: true, + keep_self_bookmark: true, + min_favs: 1, + min_reblogs: 1) end before do @@ -96,16 +95,15 @@ RSpec.describe AccountStatusesCleanupPolicy, type: :model do context 'when narrowing a policy' do let!(:account_statuses_cleanup_policy) do Fabricate(:account_statuses_cleanup_policy, - account: account, - keep_direct: false, - keep_pinned: false, - keep_polls: false, - keep_media: false, - keep_self_fav: false, - keep_self_bookmark: false, - min_favs: nil, - min_reblogs: nil - ) + account: account, + keep_direct: false, + keep_pinned: false, + keep_polls: false, + keep_media: false, + keep_self_fav: false, + keep_self_bookmark: false, + min_favs: nil, + min_reblogs: nil) end it 'does not unnecessarily invalidate last_inspected' do @@ -232,7 +230,7 @@ RSpec.describe AccountStatusesCleanupPolicy, type: :model do end describe '#compute_cutoff_id' do - let!(:unrelated_status) { Fabricate(:status, created_at: 3.years.ago) } + let!(:unrelated_status) { Fabricate(:status, created_at: 3.years.ago) } let(:account_statuses_cleanup_policy) { Fabricate(:account_statuses_cleanup_policy, account: account) } subject { account_statuses_cleanup_policy.compute_cutoff_id } diff --git a/spec/models/concerns/account_interactions_spec.rb b/spec/models/concerns/account_interactions_spec.rb index 5cb4a83f7..e628384d0 100644 --- a/spec/models/concerns/account_interactions_spec.rb +++ b/spec/models/concerns/account_interactions_spec.rb @@ -400,7 +400,7 @@ describe AccountInteractions do subject { account.domain_blocking?(domain) } context 'blocking the domain' do - it' returns true' do + it ' returns true' do account_domain_block = Fabricate(:account_domain_block, domain: domain) account.domain_blocks << account_domain_block is_expected.to be true diff --git a/spec/models/device_spec.rb b/spec/models/device_spec.rb index f56fbf978..307552e91 100644 --- a/spec/models/device_spec.rb +++ b/spec/models/device_spec.rb @@ -1,5 +1,4 @@ require 'rails_helper' RSpec.describe Device, type: :model do - end diff --git a/spec/models/encrypted_message_spec.rb b/spec/models/encrypted_message_spec.rb index 1238d57b6..64f9c6912 100644 --- a/spec/models/encrypted_message_spec.rb +++ b/spec/models/encrypted_message_spec.rb @@ -1,5 +1,4 @@ require 'rails_helper' RSpec.describe EncryptedMessage, type: :model do - end diff --git a/spec/models/export_spec.rb b/spec/models/export_spec.rb index 135d7a36b..5202ae9e1 100644 --- a/spec/models/export_spec.rb +++ b/spec/models/export_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe Export do let(:account) { Fabricate(:account) } let(:target_accounts) do - [ {}, { username: 'one', domain: 'local.host' } ].map(&method(:Fabricate).curry(2).call(:account)) + [{}, { username: 'one', domain: 'local.host' }].map(&method(:Fabricate).curry(2).call(:account)) end describe 'to_csv' do diff --git a/spec/models/login_activity_spec.rb b/spec/models/login_activity_spec.rb index ba2d207c9..12d8c4363 100644 --- a/spec/models/login_activity_spec.rb +++ b/spec/models/login_activity_spec.rb @@ -1,5 +1,4 @@ require 'rails_helper' RSpec.describe LoginActivity, type: :model do - end diff --git a/spec/models/one_time_key_spec.rb b/spec/models/one_time_key_spec.rb index 34598334c..4b231c600 100644 --- a/spec/models/one_time_key_spec.rb +++ b/spec/models/one_time_key_spec.rb @@ -1,5 +1,4 @@ require 'rails_helper' RSpec.describe OneTimeKey, type: :model do - end diff --git a/spec/models/system_key_spec.rb b/spec/models/system_key_spec.rb index a138bc131..86f07f964 100644 --- a/spec/models/system_key_spec.rb +++ b/spec/models/system_key_spec.rb @@ -1,5 +1,4 @@ require 'rails_helper' RSpec.describe SystemKey, type: :model do - end diff --git a/spec/models/trends/statuses_spec.rb b/spec/models/trends/statuses_spec.rb index 5f338a65e..98a8c7264 100644 --- a/spec/models/trends/statuses_spec.rb +++ b/spec/models/trends/statuses_spec.rb @@ -76,7 +76,7 @@ RSpec.describe Trends::Statuses do before do 13.times { reblog(status1, today) } 13.times { reblog(status2, today) } - 4.times { reblog(status3, today) } + 4.times { reblog(status3, today) } end context do diff --git a/spec/models/user_role_spec.rb b/spec/models/user_role_spec.rb index 28019593e..abf7d0e27 100644 --- a/spec/models/user_role_spec.rb +++ b/spec/models/user_role_spec.rb @@ -58,7 +58,7 @@ RSpec.describe UserRole, type: :model do end describe '#permissions_as_keys=' do - let(:input) { } + let(:input) {} before do subject.permissions_as_keys = input diff --git a/spec/routing/api_routing_spec.rb b/spec/routing/api_routing_spec.rb index 2683ccb8d..a822fba4c 100644 --- a/spec/routing/api_routing_spec.rb +++ b/spec/routing/api_routing_spec.rb @@ -5,99 +5,99 @@ require 'rails_helper' describe 'API routes' do describe 'Credentials routes' do it 'routes to verify credentials' do - expect(get('/api/v1/accounts/verify_credentials')). - to route_to('api/v1/accounts/credentials#show') + expect(get('/api/v1/accounts/verify_credentials')) + .to route_to('api/v1/accounts/credentials#show') end it 'routes to update credentials' do - expect(patch('/api/v1/accounts/update_credentials')). - to route_to('api/v1/accounts/credentials#update') + expect(patch('/api/v1/accounts/update_credentials')) + .to route_to('api/v1/accounts/credentials#update') end end describe 'Account routes' do it 'routes to statuses' do - expect(get('/api/v1/accounts/user/statuses')). - to route_to('api/v1/accounts/statuses#index', account_id: 'user') + expect(get('/api/v1/accounts/user/statuses')) + .to route_to('api/v1/accounts/statuses#index', account_id: 'user') end it 'routes to followers' do - expect(get('/api/v1/accounts/user/followers')). - to route_to('api/v1/accounts/follower_accounts#index', account_id: 'user') + expect(get('/api/v1/accounts/user/followers')) + .to route_to('api/v1/accounts/follower_accounts#index', account_id: 'user') end it 'routes to following' do - expect(get('/api/v1/accounts/user/following')). - to route_to('api/v1/accounts/following_accounts#index', account_id: 'user') + expect(get('/api/v1/accounts/user/following')) + .to route_to('api/v1/accounts/following_accounts#index', account_id: 'user') end it 'routes to search' do - expect(get('/api/v1/accounts/search')). - to route_to('api/v1/accounts/search#show') + expect(get('/api/v1/accounts/search')) + .to route_to('api/v1/accounts/search#show') end it 'routes to relationships' do - expect(get('/api/v1/accounts/relationships')). - to route_to('api/v1/accounts/relationships#index') + expect(get('/api/v1/accounts/relationships')) + .to route_to('api/v1/accounts/relationships#index') end end describe 'Statuses routes' do it 'routes reblogged_by' do - expect(get('/api/v1/statuses/123/reblogged_by')). - to route_to('api/v1/statuses/reblogged_by_accounts#index', status_id: '123') + expect(get('/api/v1/statuses/123/reblogged_by')) + .to route_to('api/v1/statuses/reblogged_by_accounts#index', status_id: '123') end it 'routes favourited_by' do - expect(get('/api/v1/statuses/123/favourited_by')). - to route_to('api/v1/statuses/favourited_by_accounts#index', status_id: '123') + expect(get('/api/v1/statuses/123/favourited_by')) + .to route_to('api/v1/statuses/favourited_by_accounts#index', status_id: '123') end it 'routes reblog' do - expect(post('/api/v1/statuses/123/reblog')). - to route_to('api/v1/statuses/reblogs#create', status_id: '123') + expect(post('/api/v1/statuses/123/reblog')) + .to route_to('api/v1/statuses/reblogs#create', status_id: '123') end it 'routes unreblog' do - expect(post('/api/v1/statuses/123/unreblog')). - to route_to('api/v1/statuses/reblogs#destroy', status_id: '123') + expect(post('/api/v1/statuses/123/unreblog')) + .to route_to('api/v1/statuses/reblogs#destroy', status_id: '123') end it 'routes favourite' do - expect(post('/api/v1/statuses/123/favourite')). - to route_to('api/v1/statuses/favourites#create', status_id: '123') + expect(post('/api/v1/statuses/123/favourite')) + .to route_to('api/v1/statuses/favourites#create', status_id: '123') end it 'routes unfavourite' do - expect(post('/api/v1/statuses/123/unfavourite')). - to route_to('api/v1/statuses/favourites#destroy', status_id: '123') + expect(post('/api/v1/statuses/123/unfavourite')) + .to route_to('api/v1/statuses/favourites#destroy', status_id: '123') end it 'routes mute' do - expect(post('/api/v1/statuses/123/mute')). - to route_to('api/v1/statuses/mutes#create', status_id: '123') + expect(post('/api/v1/statuses/123/mute')) + .to route_to('api/v1/statuses/mutes#create', status_id: '123') end it 'routes unmute' do - expect(post('/api/v1/statuses/123/unmute')). - to route_to('api/v1/statuses/mutes#destroy', status_id: '123') + expect(post('/api/v1/statuses/123/unmute')) + .to route_to('api/v1/statuses/mutes#destroy', status_id: '123') end end describe 'Timeline routes' do it 'routes to home timeline' do - expect(get('/api/v1/timelines/home')). - to route_to('api/v1/timelines/home#show') + expect(get('/api/v1/timelines/home')) + .to route_to('api/v1/timelines/home#show') end it 'routes to public timeline' do - expect(get('/api/v1/timelines/public')). - to route_to('api/v1/timelines/public#show') + expect(get('/api/v1/timelines/public')) + .to route_to('api/v1/timelines/public#show') end it 'routes to tag timeline' do - expect(get('/api/v1/timelines/tag/test')). - to route_to('api/v1/timelines/tag#show', id: 'test') + expect(get('/api/v1/timelines/tag/test')) + .to route_to('api/v1/timelines/tag#show', id: 'test') end end end diff --git a/spec/routing/well_known_routes_spec.rb b/spec/routing/well_known_routes_spec.rb index 2e25605c2..03a562843 100644 --- a/spec/routing/well_known_routes_spec.rb +++ b/spec/routing/well_known_routes_spec.rb @@ -2,14 +2,14 @@ require 'rails_helper' describe 'the host-meta route' do it 'routes to correct place with xml format' do - expect(get('/.well-known/host-meta')). - to route_to('well_known/host_meta#show', format: 'xml') + expect(get('/.well-known/host-meta')) + .to route_to('well_known/host_meta#show', format: 'xml') end end describe 'the webfinger route' do it 'routes to correct place with json format' do - expect(get('/.well-known/webfinger')). - to route_to('well_known/webfinger#show') + expect(get('/.well-known/webfinger')) + .to route_to('well_known/webfinger#show') end end diff --git a/spec/serializers/rest/account_serializer_spec.rb b/spec/serializers/rest/account_serializer_spec.rb index 5b08d5aca..3bca06b73 100644 --- a/spec/serializers/rest/account_serializer_spec.rb +++ b/spec/serializers/rest/account_serializer_spec.rb @@ -5,7 +5,7 @@ require 'rails_helper' describe REST::AccountSerializer do let(:role) { Fabricate(:user_role, name: 'Role', highlighted: true) } let(:user) { Fabricate(:user, role: role) } - let(:account) { user.account} + let(:account) { user.account } subject { JSON.parse(ActiveModelSerializers::SerializableResource.new(account, serializer: REST::AccountSerializer).to_json) } diff --git a/spec/services/account_statuses_cleanup_service_spec.rb b/spec/services/account_statuses_cleanup_service_spec.rb index 257655c41..a30e14ab6 100644 --- a/spec/services/account_statuses_cleanup_service_spec.rb +++ b/spec/services/account_statuses_cleanup_service_spec.rb @@ -42,8 +42,8 @@ describe AccountStatusesCleanupService, type: :service do context 'when called repeatedly with a budget of 2' do it 'reports 2 then 1 deleted statuses' do - expect(subject.call(account_policy, 2)).to eq 2 - expect(subject.call(account_policy, 2)).to eq 1 + expect(subject.call(account_policy, 2)).to eq 2 + expect(subject.call(account_policy, 2)).to eq 1 end it 'actually deletes the statuses in the expected order' do diff --git a/spec/services/activitypub/fetch_remote_status_service_spec.rb b/spec/services/activitypub/fetch_remote_status_service_spec.rb index a81dcad81..d6145c9b8 100644 --- a/spec/services/activitypub/fetch_remote_status_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_status_service_spec.rb @@ -298,7 +298,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do first: { type: 'CollectionPage', partOf: "https://foo.bar/@foo/#{i}/replies", - items: ["https://foo.bar/@foo/#{i+1}"], + items: ["https://foo.bar/@foo/#{i + 1}"], }, }, attributedTo: ActivityPub::TagManager.instance.uri_for(sender), diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb index 2b20d17b1..40caa6eb0 100644 --- a/spec/services/activitypub/process_account_service_spec.rb +++ b/spec/services/activitypub/process_account_service_spec.rb @@ -172,10 +172,10 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do { type: 'Mention', href: "https://foo.test/users/#{i + 1}", - name: "@user#{i + 1 }", + name: "@user#{i + 1}", } ], - to: [ 'as:Public', "https://foo.test/users/#{i + 1}" ] + to: ['as:Public', "https://foo.test/users/#{i + 1}"] }.with_indifferent_access featured_json = { '@context': ['https://www.w3.org/ns/activitystreams'], diff --git a/spec/services/activitypub/process_collection_service_spec.rb b/spec/services/activitypub/process_collection_service_spec.rb index a308cede7..cb60e1cb8 100644 --- a/spec/services/activitypub/process_collection_service_spec.rb +++ b/spec/services/activitypub/process_collection_service_spec.rb @@ -95,11 +95,11 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do context 'when receiving a fabricated status' do let!(:actor) do Fabricate(:account, - username: 'bob', - domain: 'example.com', - uri: 'https://example.com/users/bob', - public_key: "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuuYyoyfsRkYnXRotMsId\nW3euBDDfiv9oVqOxUVC7bhel8KednIMrMCRWFAkgJhbrlzbIkjVr68o1MP9qLcn7\nCmH/BXHp7yhuFTr4byjdJKpwB+/i2jNEsvDH5jR8WTAeTCe0x/QHg21V3F7dSI5m\nCCZ/1dSIyOXLRTWVlfDlm3rE4ntlCo+US3/7oSWbg/4/4qEnt1HC32kvklgScxua\n4LR5ATdoXa5bFoopPWhul7MJ6NyWCyQyScUuGdlj8EN4kmKQJvphKHrI9fvhgOuG\nTvhTR1S5InA4azSSchY0tXEEw/VNxraeX0KPjbgr6DPcwhPd/m0nhVDq0zVyVBBD\nMwIDAQAB\n-----END PUBLIC KEY-----\n", - private_key: nil) + username: 'bob', + domain: 'example.com', + uri: 'https://example.com/users/bob', + public_key: "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuuYyoyfsRkYnXRotMsId\nW3euBDDfiv9oVqOxUVC7bhel8KednIMrMCRWFAkgJhbrlzbIkjVr68o1MP9qLcn7\nCmH/BXHp7yhuFTr4byjdJKpwB+/i2jNEsvDH5jR8WTAeTCe0x/QHg21V3F7dSI5m\nCCZ/1dSIyOXLRTWVlfDlm3rE4ntlCo+US3/7oSWbg/4/4qEnt1HC32kvklgScxua\n4LR5ATdoXa5bFoopPWhul7MJ6NyWCyQyScUuGdlj8EN4kmKQJvphKHrI9fvhgOuG\nTvhTR1S5InA4azSSchY0tXEEw/VNxraeX0KPjbgr6DPcwhPd/m0nhVDq0zVyVBBD\nMwIDAQAB\n-----END PUBLIC KEY-----\n", + private_key: nil) end let(:payload) do @@ -107,7 +107,7 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do '@context': [ 'https://www.w3.org/ns/activitystreams', nil, - {'object': 'https://www.w3.org/ns/activitystreams#object'} + { 'object': 'https://www.w3.org/ns/activitystreams#object' } ], 'id': 'https://example.com/users/bob/fake-status/activity', 'type': 'Create', diff --git a/spec/services/activitypub/process_status_update_service_spec.rb b/spec/services/activitypub/process_status_update_service_spec.rb index 750369d57..04292c507 100644 --- a/spec/services/activitypub/process_status_update_service_spec.rb +++ b/spec/services/activitypub/process_status_update_service_spec.rb @@ -104,20 +104,19 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do end context 'when the status has not been explicitly edited and features a poll' do - let(:account) { Fabricate(:account, domain: 'example.com') } + let(:account) { Fabricate(:account, domain: 'example.com') } let!(:expiration) { 10.days.from_now.utc } let!(:status) do Fabricate(:status, - text: 'Hello world', - account: account, - poll_attributes: { - options: %w(Foo Bar), - account: account, - multiple: false, - hide_totals: false, - expires_at: expiration - } - ) + text: 'Hello world', + account: account, + poll_attributes: { + options: %w(Foo Bar), + account: account, + multiple: false, + hide_totals: false, + expires_at: expiration + }) end let(:payload) do @@ -156,20 +155,19 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do end context 'when the status changes a poll despite being not explicitly marked as updated' do - let(:account) { Fabricate(:account, domain: 'example.com') } + let(:account) { Fabricate(:account, domain: 'example.com') } let!(:expiration) { 10.days.from_now.utc } let!(:status) do Fabricate(:status, - text: 'Hello world', - account: account, - poll_attributes: { - options: %w(Foo Bar), - account: account, - multiple: false, - hide_totals: false, - expires_at: expiration - } - ) + text: 'Hello world', + account: account, + poll_attributes: { + options: %w(Foo Bar), + account: account, + multiple: false, + hide_totals: false, + expires_at: expiration + }) end let(:payload) do diff --git a/spec/services/bootstrap_timeline_service_spec.rb b/spec/services/bootstrap_timeline_service_spec.rb index 16f3e9962..149f6e6df 100644 --- a/spec/services/bootstrap_timeline_service_spec.rb +++ b/spec/services/bootstrap_timeline_service_spec.rb @@ -32,6 +32,5 @@ RSpec.describe BootstrapTimelineService, type: :service do expect(service).to_not have_received(:call) end end - end end diff --git a/spec/services/fetch_oembed_service_spec.rb b/spec/services/fetch_oembed_service_spec.rb index 88f0113ed..da2a8d0d1 100644 --- a/spec/services/fetch_oembed_service_spec.rb +++ b/spec/services/fetch_oembed_service_spec.rb @@ -151,7 +151,6 @@ describe FetchOEmbedService, type: :service do expect(subject.format).to eq :json end end - end context 'when endpoint is cached' do diff --git a/spec/services/import_service_spec.rb b/spec/services/import_service_spec.rb index e2d182920..217d0ee24 100644 --- a/spec/services/import_service_spec.rb +++ b/spec/services/import_service_spec.rb @@ -178,7 +178,7 @@ RSpec.describe ImportService, type: :service do context 'utf-8 encoded domains' do subject { ImportService.new } - let!(:nare) { Fabricate(:account, username: 'nare', domain: 'թութ.հայ', locked: false, protocol: :activitypub, inbox_url: 'https://թութ.հայ/inbox') } + let!(:nare) { Fabricate(:account, username: 'nare', domain: 'թութ.հայ', locked: false, protocol: :activitypub, inbox_url: 'https://թութ.հայ/inbox') } # Make sure to not actually go to the remote server before do @@ -189,7 +189,7 @@ RSpec.describe ImportService, type: :service do let(:import) { Import.create(account: account, type: 'following', data: csv) } it 'follows the listed account' do - expect(account.follow_requests.count).to eq 0 + expect(account.follow_requests.count).to eq 0 subject.call(import) expect(account.follow_requests.count).to eq 1 end diff --git a/spec/services/remove_from_follwers_service_spec.rb b/spec/services/remove_from_follwers_service_spec.rb index a83f6f49a..9b9c846cf 100644 --- a/spec/services/remove_from_follwers_service_spec.rb +++ b/spec/services/remove_from_follwers_service_spec.rb @@ -7,7 +7,7 @@ RSpec.describe RemoveFromFollowersService, type: :service do describe 'local' do let(:sender) { Fabricate(:account, username: 'alice') } - + before do Follow.create(account: sender, target_account: bob) subject.call(bob, sender) diff --git a/spec/services/remove_status_service_spec.rb b/spec/services/remove_status_service_spec.rb index 482068d58..e253052f3 100644 --- a/spec/services/remove_status_service_spec.rb +++ b/spec/services/remove_status_service_spec.rb @@ -37,29 +37,29 @@ RSpec.describe RemoveStatusService, type: :service do it 'sends Delete activity to followers' do subject.call(@status) expect(a_request(:post, 'http://example.com/inbox').with( - body: hash_including({ - 'type' => 'Delete', - 'object' => { - 'type' => 'Tombstone', - 'id' => ActivityPub::TagManager.instance.uri_for(@status), - 'atomUri' => OStatus::TagManager.instance.uri_for(@status), - }, - }) - )).to have_been_made.once + body: hash_including({ + 'type' => 'Delete', + 'object' => { + 'type' => 'Tombstone', + 'id' => ActivityPub::TagManager.instance.uri_for(@status), + 'atomUri' => OStatus::TagManager.instance.uri_for(@status), + }, + }) + )).to have_been_made.once end it 'sends Delete activity to rebloggers' do subject.call(@status) expect(a_request(:post, 'http://example2.com/inbox').with( - body: hash_including({ - 'type' => 'Delete', - 'object' => { - 'type' => 'Tombstone', - 'id' => ActivityPub::TagManager.instance.uri_for(@status), - 'atomUri' => OStatus::TagManager.instance.uri_for(@status), - }, - }) - )).to have_been_made.once + body: hash_including({ + 'type' => 'Delete', + 'object' => { + 'type' => 'Tombstone', + 'id' => ActivityPub::TagManager.instance.uri_for(@status), + 'atomUri' => OStatus::TagManager.instance.uri_for(@status), + }, + }) + )).to have_been_made.once end it 'remove status from notifications' do @@ -78,14 +78,14 @@ RSpec.describe RemoveStatusService, type: :service do it 'sends Undo activity to followers' do subject.call(@status) expect(a_request(:post, 'http://example.com/inbox').with( - body: hash_including({ - 'type' => 'Undo', - 'object' => hash_including({ - 'type' => 'Announce', - 'object' => ActivityPub::TagManager.instance.uri_for(@original_status), - }), - }) - )).to have_been_made.once + body: hash_including({ + 'type' => 'Undo', + 'object' => hash_including({ + 'type' => 'Announce', + 'object' => ActivityPub::TagManager.instance.uri_for(@original_status), + }), + }) + )).to have_been_made.once end end @@ -98,14 +98,14 @@ RSpec.describe RemoveStatusService, type: :service do it 'sends Undo activity to followers' do subject.call(@status) expect(a_request(:post, 'http://example.com/inbox').with( - body: hash_including({ - 'type' => 'Undo', - 'object' => hash_including({ - 'type' => 'Announce', - 'object' => ActivityPub::TagManager.instance.uri_for(@original_status), - }), - }) - )).to have_been_made.once + body: hash_including({ + 'type' => 'Undo', + 'object' => hash_including({ + 'type' => 'Announce', + 'object' => ActivityPub::TagManager.instance.uri_for(@original_status), + }), + }) + )).to have_been_made.once end end end diff --git a/spec/services/resolve_account_service_spec.rb b/spec/services/resolve_account_service_spec.rb index 654606bea..1df30ea57 100644 --- a/spec/services/resolve_account_service_spec.rb +++ b/spec/services/resolve_account_service_spec.rb @@ -190,7 +190,7 @@ RSpec.describe ResolveAccountService, type: :service do context 'with an already-known acct: URI changing ActivityPub id' do let!(:old_account) { Fabricate(:account, username: 'foo', domain: 'ap.example.com', uri: 'https://old.example.com/users/foo', last_webfingered_at: nil) } - let!(:status) { Fabricate(:status, account: old_account, text: 'foo') } + let!(:status) { Fabricate(:status, account: old_account, text: 'foo') } it 'returns new remote account' do account = subject.call('foo@ap.example.com') diff --git a/spec/services/resolve_url_service_spec.rb b/spec/services/resolve_url_service_spec.rb index b3e3defbf..3598311ee 100644 --- a/spec/services/resolve_url_service_spec.rb +++ b/spec/services/resolve_url_service_spec.rb @@ -133,7 +133,7 @@ describe ResolveURLService, type: :service do let!(:status) { Fabricate(:status, account: poster, visibility: :public) } let(:url) { 'https://link.to/foobar' } let(:status_url) { ActivityPub::TagManager.instance.url_for(status) } - let(:uri) { ActivityPub::TagManager.instance.uri_for(status) } + let(:uri) { ActivityPub::TagManager.instance.uri_for(status) } before do stub_request(:get, url).to_return(status: 302, headers: { 'Location' => status_url }) diff --git a/spec/services/update_status_service_spec.rb b/spec/services/update_status_service_spec.rb index 16e981d2b..a7364ca8b 100644 --- a/spec/services/update_status_service_spec.rb +++ b/spec/services/update_status_service_spec.rb @@ -111,7 +111,7 @@ RSpec.describe UpdateStatusService, type: :service do context 'when poll changes' do let(:account) { Fabricate(:account) } - let!(:status) { Fabricate(:status, text: 'Foo', account: account, poll_attributes: {options: %w(Foo Bar), account: account, multiple: false, hide_totals: false, expires_at: 7.days.from_now }) } + let!(:status) { Fabricate(:status, text: 'Foo', account: account, poll_attributes: { options: %w(Foo Bar), account: account, multiple: false, hide_totals: false, expires_at: 7.days.from_now }) } let!(:poll) { status.poll } let!(:voter) { Fabricate(:account) } diff --git a/spec/support/stories/profile_stories.rb b/spec/support/stories/profile_stories.rb index 0c4a14d1c..de7ae17e6 100644 --- a/spec/support/stories/profile_stories.rb +++ b/spec/support/stories/profile_stories.rb @@ -20,8 +20,8 @@ module ProfileStories end def with_alice_as_local_user - @alice_bio = '@alice and @bob are fictional characters commonly used as'\ - 'placeholder names in #cryptology, as well as #science and'\ + @alice_bio = '@alice and @bob are fictional characters commonly used as' \ + 'placeholder names in #cryptology, as well as #science and' \ 'engineering 📖 literature. Not affiliated with @pepe.' @alice = Fabricate( diff --git a/spec/validators/note_length_validator_spec.rb b/spec/validators/note_length_validator_spec.rb index 6e9b4e132..390ac8d90 100644 --- a/spec/validators/note_length_validator_spec.rb +++ b/spec/validators/note_length_validator_spec.rb @@ -15,7 +15,7 @@ describe NoteLengthValidator do end it 'counts URLs as 23 characters flat' do - text = ('a' * 476) + " http://#{'b' * 30}.com/example" + text = ('a' * 476) + " http://#{'b' * 30}.com/example" account = double(note: text, errors: double(add: nil)) subject.validate_each(account, 'note', text) @@ -23,7 +23,7 @@ describe NoteLengthValidator do end it 'does not count non-autolinkable URLs as 23 characters flat' do - text = ('a' * 476) + "http://#{'b' * 30}.com/example" + text = ('a' * 476) + "http://#{'b' * 30}.com/example" account = double(note: text, errors: double(add: nil)) subject.validate_each(account, 'note', text) diff --git a/spec/validators/unreserved_username_validator_spec.rb b/spec/validators/unreserved_username_validator_spec.rb index 746b3866c..e2f051b08 100644 --- a/spec/validators/unreserved_username_validator_spec.rb +++ b/spec/validators/unreserved_username_validator_spec.rb @@ -11,10 +11,10 @@ RSpec.describe UnreservedUsernameValidator, type: :validator do let(:validator) { described_class.new } let(:account) { double(username: username, errors: errors) } - let(:errors ) { double(add: nil) } + let(:errors) { double(add: nil) } context '@username.blank?' do - let(:username) { nil } + let(:username) { nil } it 'not calls errors.add' do expect(errors).not_to have_received(:add).with(:username, any_args) @@ -22,7 +22,7 @@ RSpec.describe UnreservedUsernameValidator, type: :validator do end context '!@username.blank?' do - let(:username) { 'f' } + let(:username) { 'f' } context 'reserved_username?' do let(:reserved_username) { true } diff --git a/spec/workers/activitypub/distribution_worker_spec.rb b/spec/workers/activitypub/distribution_worker_spec.rb index 3a5900d9b..7f63e197b 100644 --- a/spec/workers/activitypub/distribution_worker_spec.rb +++ b/spec/workers/activitypub/distribution_worker_spec.rb @@ -34,7 +34,7 @@ describe ActivityPub::DistributionWorker do end context 'with direct status' do - let(:mentioned_account) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://foo.bar/inbox')} + let(:mentioned_account) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://foo.bar/inbox') } before do status.update(visibility: :direct) diff --git a/spec/workers/activitypub/move_distribution_worker_spec.rb b/spec/workers/activitypub/move_distribution_worker_spec.rb index af8c44cc0..57941065a 100644 --- a/spec/workers/activitypub/move_distribution_worker_spec.rb +++ b/spec/workers/activitypub/move_distribution_worker_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe ActivityPub::MoveDistributionWorker do subject { described_class.new } - let(:migration) { Fabricate(:account_migration) } + let(:migration) { Fabricate(:account_migration) } let(:follower) { Fabricate(:account, protocol: :activitypub, inbox_url: 'http://example.com') } let(:blocker) { Fabricate(:account, protocol: :activitypub, inbox_url: 'http://example2.com') } @@ -15,9 +15,9 @@ describe ActivityPub::MoveDistributionWorker do it 'delivers to followers and known blockers' do expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [ - [kind_of(String), migration.account.id, 'http://example.com'], - [kind_of(String), migration.account.id, 'http://example2.com'] - ]) + [kind_of(String), migration.account.id, 'http://example.com'], + [kind_of(String), migration.account.id, 'http://example2.com'] + ]) subject.perform(migration.id) end end diff --git a/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb b/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb index 8f20725c8..8faf04836 100644 --- a/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb +++ b/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb @@ -82,7 +82,7 @@ describe Scheduler::AccountsStatusesCleanupScheduler do describe '#get_budget' do context 'on a single thread' do - let(:process_set_stub) { [ { 'concurrency' => 1, 'queues' => ['push', 'default'] } ] } + let(:process_set_stub) { [{ 'concurrency' => 1, 'queues' => ['push', 'default'] }] } it 'returns a low value' do expect(subject.compute_budget).to be < 10 -- cgit From a6f77aa28ae805e89b0a38c468b7193050174df4 Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Fri, 17 Feb 2023 22:30:23 -0500 Subject: Autofix Rubocop Lint/AmbiguousOperatorPrecedence (#23681) --- .rubocop_todo.yml | 11 ----------- app/controllers/concerns/rate_limit_headers.rb | 2 +- app/lib/rate_limiter.rb | 2 +- app/models/system_key.rb | 2 +- app/models/webauthn_credential.rb | 2 +- app/workers/concerns/exponential_backoff.rb | 2 +- lib/paperclip/color_extractor.rb | 22 +++++++++++----------- 7 files changed, 16 insertions(+), 27 deletions(-) (limited to 'app/models') diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 68d3f2bd7..0fe77521d 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -183,17 +183,6 @@ Lint/AmbiguousBlockAssociation: - 'spec/services/unsuspend_account_service_spec.rb' - 'spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb' -# Offense count: 17 -# This cop supports safe autocorrection (--autocorrect). -Lint/AmbiguousOperatorPrecedence: - Exclude: - - 'app/controllers/concerns/rate_limit_headers.rb' - - 'app/lib/rate_limiter.rb' - - 'app/models/system_key.rb' - - 'app/models/webauthn_credential.rb' - - 'app/workers/concerns/exponential_backoff.rb' - - 'lib/paperclip/color_extractor.rb' - # Offense count: 15 # Configuration parameters: AllowedMethods. # AllowedMethods: enums diff --git a/app/controllers/concerns/rate_limit_headers.rb b/app/controllers/concerns/rate_limit_headers.rb index b8696df73..b21abfb03 100644 --- a/app/controllers/concerns/rate_limit_headers.rb +++ b/app/controllers/concerns/rate_limit_headers.rb @@ -67,6 +67,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/lib/rate_limiter.rb b/app/lib/rate_limiter.rb index 0e2c9a894..4a0b35b08 100644 --- a/app/lib/rate_limiter.rb +++ b/app/lib/rate_limiter.rb @@ -48,7 +48,7 @@ class RateLimiter { 'X-RateLimit-Limit' => @limit.to_s, 'X-RateLimit-Remaining' => (@limit - (redis.get(key) || 0).to_i).to_s, - 'X-RateLimit-Reset' => (now + (@period - now.to_i % @period)).iso8601(6), + 'X-RateLimit-Reset' => (now + (@period - (now.to_i % @period))).iso8601(6), } end diff --git a/app/models/system_key.rb b/app/models/system_key.rb index f17db7c2d..1be399dd6 100644 --- a/app/models/system_key.rb +++ b/app/models/system_key.rb @@ -14,7 +14,7 @@ class SystemKey < ApplicationRecord before_validation :set_key - scope :expired, ->(now = Time.now.utc) { where(arel_table[:created_at].lt(now - ROTATION_PERIOD * 3)) } + scope :expired, ->(now = Time.now.utc) { where(arel_table[:created_at].lt(now - (ROTATION_PERIOD * 3))) } class << self def current_key diff --git a/app/models/webauthn_credential.rb b/app/models/webauthn_credential.rb index 7d423e38d..48abfc1d4 100644 --- a/app/models/webauthn_credential.rb +++ b/app/models/webauthn_credential.rb @@ -18,5 +18,5 @@ class WebauthnCredential < ApplicationRecord validates :external_id, uniqueness: true validates :nickname, uniqueness: { scope: :user_id } validates :sign_count, - numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 2**63 - 1 } + numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: (2**63) - 1 } end diff --git a/app/workers/concerns/exponential_backoff.rb b/app/workers/concerns/exponential_backoff.rb index f2b931e33..7626b2151 100644 --- a/app/workers/concerns/exponential_backoff.rb +++ b/app/workers/concerns/exponential_backoff.rb @@ -5,7 +5,7 @@ module ExponentialBackoff included do sidekiq_retry_in do |count| - 15 + 10 * (count**4) + rand(10 * (count**4)) + 15 + (10 * (count**4)) + rand(10 * (count**4)) end end end diff --git a/lib/paperclip/color_extractor.rb b/lib/paperclip/color_extractor.rb index d3b8e1022..d8a042c90 100644 --- a/lib/paperclip/color_extractor.rb +++ b/lib/paperclip/color_extractor.rb @@ -79,8 +79,8 @@ module Paperclip private def w3c_contrast(color1, color2) - luminance1 = color1.to_xyz.y * 0.01 + 0.05 - luminance2 = color2.to_xyz.y * 0.01 + 0.05 + luminance1 = (color1.to_xyz.y * 0.01) + 0.05 + luminance2 = (color2.to_xyz.y * 0.01) + 0.05 if luminance1 > luminance2 luminance1 / luminance2 @@ -109,11 +109,11 @@ module Paperclip case max when r - h = (g - b) / d + (g < b ? 6.0 : 0) + h = ((g - b) / d) + (g < b ? 6.0 : 0) when g - h = (b - r) / d + 2.0 + h = ((b - r) / d) + 2.0 when b - h = (r - g) / d + 4.0 + h = ((r - g) / d) + 4.0 end h /= 6.0 @@ -126,9 +126,9 @@ module Paperclip t += 1 if t.negative? t -= 1 if t > 1 - return (p + (q - p) * 6 * t) if t < 1 / 6.0 + return (p + ((q - p) * 6 * t)) if t < 1 / 6.0 return q if t < 1 / 2.0 - return (p + (q - p) * (2 / 3.0 - t) * 6) if t < 2 / 3.0 + return (p + ((q - p) * ((2 / 3.0) - t) * 6)) if t < 2 / 3.0 p end @@ -147,11 +147,11 @@ module Paperclip g = l.to_f b = l.to_f # achromatic else - q = l < 0.5 ? l * (s + 1) : l + s - l * s - p = 2 * l - q - r = hue_to_rgb(p, q, h + 1 / 3.0) + q = l < 0.5 ? l * (s + 1) : l + s - (l * s) + p = (2 * l) - q + r = hue_to_rgb(p, q, h + (1 / 3.0)) g = hue_to_rgb(p, q, h) - b = hue_to_rgb(p, q, h - 1 / 3.0) + b = hue_to_rgb(p, q, h - (1 / 3.0)) end [(r * 255).round, (g * 255).round, (b * 255).round] -- cgit From e2a3ebb271017d800a448ad3ef3e8324ac1fab3b Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Sat, 18 Feb 2023 06:37:47 -0500 Subject: Autofix Rubocop Style/IfUnlessModifier (#23697) --- .rubocop_todo.yml | 106 --------------------- app/controllers/admin/domain_blocks_controller.rb | 4 +- .../v1/accounts/follower_accounts_controller.rb | 8 +- .../v1/accounts/following_accounts_controller.rb | 8 +- .../api/v1/accounts/statuses_controller.rb | 8 +- .../api/v1/admin/accounts_controller.rb | 4 +- app/controllers/api/v1/blocks_controller.rb | 8 +- app/controllers/api/v1/conversations_controller.rb | 8 +- app/controllers/api/v1/domain_blocks_controller.rb | 8 +- app/controllers/api/v1/endorsements_controller.rb | 8 +- app/controllers/api/v1/favourites_controller.rb | 8 +- .../api/v1/follow_requests_controller.rb | 8 +- .../api/v1/lists/accounts_controller.rb | 8 +- app/controllers/api/v1/mutes_controller.rb | 8 +- app/controllers/api/v1/notifications_controller.rb | 8 +- .../api/v1/scheduled_statuses_controller.rb | 8 +- .../statuses/favourited_by_accounts_controller.rb | 8 +- .../statuses/reblogged_by_accounts_controller.rb | 8 +- .../api/v2/admin/accounts_controller.rb | 4 +- app/controllers/auth/registrations_controller.rb | 4 +- app/controllers/auth/sessions_controller.rb | 4 +- app/controllers/filters/statuses_controller.rb | 4 +- app/helpers/application_helper.rb | 4 +- app/lib/activitypub/linked_data_signature.rb | 4 +- .../activitypub/parser/media_attachment_parser.rb | 4 +- app/lib/status_finder.rb | 4 +- app/models/account.rb | 4 +- app/models/account_statuses_cleanup_policy.rb | 8 +- app/models/concerns/account_interactions.rb | 4 +- app/models/concerns/omniauthable.rb | 4 +- app/serializers/initial_state_serializer.rb | 4 +- app/serializers/rest/instance_serializer.rb | 4 +- .../activitypub/fetch_remote_actor_service.rb | 4 +- .../activitypub/process_status_update_service.rb | 4 +- app/services/remove_from_followers_service.rb | 4 +- app/services/resolve_account_service.rb | 4 +- app/services/search_service.rb | 4 +- lib/mastodon/media_cli.rb | 4 +- lib/mastodon/redis_config.rb | 4 +- .../matchers/model/model_have_error_on_field.rb | 4 +- 40 files changed, 55 insertions(+), 271 deletions(-) (limited to 'app/models') diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 9a9c420df..0e94741ae 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -2921,112 +2921,6 @@ Style/HashTransformValues: - 'app/serializers/rest/web_push_subscription_serializer.rb' - 'app/services/import_service.rb' -# Offense count: 176 -# This cop supports safe autocorrection (--autocorrect). -Style/IfUnlessModifier: - Exclude: - - 'app/controllers/admin/domain_blocks_controller.rb' - - 'app/controllers/api/v1/accounts/follower_accounts_controller.rb' - - 'app/controllers/api/v1/accounts/following_accounts_controller.rb' - - 'app/controllers/api/v1/accounts/statuses_controller.rb' - - 'app/controllers/api/v1/admin/accounts_controller.rb' - - 'app/controllers/api/v1/admin/domain_blocks_controller.rb' - - 'app/controllers/api/v1/blocks_controller.rb' - - 'app/controllers/api/v1/conversations_controller.rb' - - 'app/controllers/api/v1/domain_blocks_controller.rb' - - 'app/controllers/api/v1/emails/confirmations_controller.rb' - - 'app/controllers/api/v1/endorsements_controller.rb' - - 'app/controllers/api/v1/favourites_controller.rb' - - 'app/controllers/api/v1/filters_controller.rb' - - 'app/controllers/api/v1/follow_requests_controller.rb' - - 'app/controllers/api/v1/lists/accounts_controller.rb' - - 'app/controllers/api/v1/mutes_controller.rb' - - 'app/controllers/api/v1/notifications_controller.rb' - - 'app/controllers/api/v1/scheduled_statuses_controller.rb' - - 'app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb' - - 'app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb' - - 'app/controllers/api/v1/trends/links_controller.rb' - - 'app/controllers/api/v1/trends/statuses_controller.rb' - - 'app/controllers/api/v1/trends/tags_controller.rb' - - 'app/controllers/api/v2/admin/accounts_controller.rb' - - 'app/controllers/api/v2/search_controller.rb' - - 'app/controllers/auth/registrations_controller.rb' - - 'app/controllers/auth/sessions_controller.rb' - - 'app/controllers/concerns/localized.rb' - - 'app/controllers/concerns/rate_limit_headers.rb' - - 'app/controllers/concerns/signature_verification.rb' - - 'app/controllers/filters/statuses_controller.rb' - - 'app/helpers/application_helper.rb' - - 'app/helpers/jsonld_helper.rb' - - 'app/lib/activitypub/activity/announce.rb' - - 'app/lib/activitypub/activity/create.rb' - - 'app/lib/activitypub/activity/like.rb' - - 'app/lib/activitypub/linked_data_signature.rb' - - 'app/lib/activitypub/parser/media_attachment_parser.rb' - - 'app/lib/feed_manager.rb' - - 'app/lib/status_cache_hydrator.rb' - - 'app/lib/status_finder.rb' - - 'app/models/account.rb' - - 'app/models/account_migration.rb' - - 'app/models/account_statuses_cleanup_policy.rb' - - 'app/models/admin/import.rb' - - 'app/models/admin/status_batch_action.rb' - - 'app/models/concerns/account_avatar.rb' - - 'app/models/concerns/account_counters.rb' - - 'app/models/concerns/account_header.rb' - - 'app/models/concerns/account_interactions.rb' - - 'app/models/concerns/attachmentable.rb' - - 'app/models/concerns/ldap_authenticable.rb' - - 'app/models/concerns/omniauthable.rb' - - 'app/models/form/redirect.rb' - - 'app/models/media_attachment.rb' - - 'app/models/scheduled_status.rb' - - 'app/models/status.rb' - - 'app/models/trends.rb' - - 'app/models/trends/links.rb' - - 'app/models/trends/statuses.rb' - - 'app/models/user_role.rb' - - 'app/presenters/status_relationships_presenter.rb' - - 'app/serializers/initial_state_serializer.rb' - - 'app/serializers/rest/instance_serializer.rb' - - 'app/services/activitypub/fetch_remote_actor_service.rb' - - 'app/services/activitypub/fetch_remote_status_service.rb' - - 'app/services/activitypub/prepare_followers_synchronization_service.rb' - - 'app/services/activitypub/process_status_update_service.rb' - - 'app/services/block_domain_service.rb' - - 'app/services/fetch_link_card_service.rb' - - 'app/services/fetch_resource_service.rb' - - 'app/services/notify_service.rb' - - 'app/services/post_status_service.rb' - - 'app/services/remove_from_followers_service.rb' - - 'app/services/report_service.rb' - - 'app/services/resolve_account_service.rb' - - 'app/services/search_service.rb' - - 'app/services/unblock_domain_service.rb' - - 'app/services/update_status_service.rb' - - 'app/validators/disallowed_hashtags_validator.rb' - - 'app/validators/existing_username_validator.rb' - - 'app/validators/follow_limit_validator.rb' - - 'app/validators/import_validator.rb' - - 'app/validators/note_length_validator.rb' - - 'app/validators/poll_validator.rb' - - 'app/validators/reaction_validator.rb' - - 'app/validators/registration_form_time_validator.rb' - - 'app/workers/activitypub/delivery_worker.rb' - - 'app/workers/move_worker.rb' - - 'db/migrate/20180514140000_revert_index_change_on_statuses_for_api_v1_accounts_account_id_statuses.rb' - - 'db/migrate/20180528141303_fix_accounts_unique_index.rb' - - 'db/migrate/20200510181721_remove_duplicated_indexes_pghero.rb' - - 'db/migrate/20200620164023_add_fixed_lowercase_index_to_accounts.rb' - - 'lib/cli.rb' - - 'lib/mastodon/accounts_cli.rb' - - 'lib/mastodon/domains_cli.rb' - - 'lib/mastodon/maintenance_cli.rb' - - 'lib/mastodon/media_cli.rb' - - 'lib/mastodon/redis_config.rb' - - 'lib/mastodon/statuses_cli.rb' - - 'spec/support/matchers/model/model_have_error_on_field.rb' - # Offense count: 3 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: InverseMethods, InverseBlocks. diff --git a/app/controllers/admin/domain_blocks_controller.rb b/app/controllers/admin/domain_blocks_controller.rb index 74764640b..060db11bb 100644 --- a/app/controllers/admin/domain_blocks_controller.rb +++ b/app/controllers/admin/domain_blocks_controller.rb @@ -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/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb index b61de13b9..68952de89 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 37d3c2d78..0a4d2ae7b 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 38c9f5a20..7ed48cf65 100644 --- a/app/controllers/api/v1/accounts/statuses_controller.rb +++ b/app/controllers/api/v1/accounts/statuses_controller.rb @@ -39,15 +39,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/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/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/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/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 41f7f93af..2024d521c 100644 --- a/app/controllers/api/v1/notifications_controller.rb +++ b/app/controllers/api/v1/notifications_controller.rb @@ -58,15 +58,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/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/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index 71c0cd827..c5418ba0c 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -30,9 +30,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 diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index afcf8b24b..3ce742638 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -110,9 +110,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/filters/statuses_controller.rb b/app/controllers/filters/statuses_controller.rb index cc493c22c..7779c6d95 100644 --- a/app/controllers/filters/statuses_controller.rb +++ b/app/controllers/filters/statuses_controller.rb @@ -38,9 +38,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/helpers/application_helper.rb b/app/helpers/application_helper.rb index b2687eddd..1f93b33f5 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -216,9 +216,7 @@ module ApplicationHelper state_params[:moved_to_account] = current_account.moved_to_account end - if single_user_mode? - state_params[:owner] = Account.local.without_suspended.where('id > 0').first - end + state_params[:owner] = Account.local.without_suspended.where('id > 0').first if single_user_mode? json = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(state_params), serializer: InitialStateSerializer).to_json # rubocop:disable Rails/OutputSafety diff --git a/app/lib/activitypub/linked_data_signature.rb b/app/lib/activitypub/linked_data_signature.rb index f90adaf6c..61759649a 100644 --- a/app/lib/activitypub/linked_data_signature.rb +++ b/app/lib/activitypub/linked_data_signature.rb @@ -27,9 +27,7 @@ class ActivityPub::LinkedDataSignature document_hash = hash(@json.without('signature')) to_be_verified = options_hash + document_hash - if creator.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), Base64.decode64(signature), to_be_verified) - creator - end + creator if creator.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), Base64.decode64(signature), to_be_verified) end def sign!(creator, sign_with: nil) diff --git a/app/lib/activitypub/parser/media_attachment_parser.rb b/app/lib/activitypub/parser/media_attachment_parser.rb index 656be84b7..56b8b23f8 100644 --- a/app/lib/activitypub/parser/media_attachment_parser.rb +++ b/app/lib/activitypub/parser/media_attachment_parser.rb @@ -50,9 +50,7 @@ class ActivityPub::Parser::MediaAttachmentParser components = begin blurhash = @json['blurhash'] - if blurhash.present? && /^[\w#$%*+,-.:;=?@\[\]^{|}~]+$/.match?(blurhash) - Blurhash.components(blurhash) - end + Blurhash.components(blurhash) if blurhash.present? && /^[\w#$%*+,-.:;=?@\[\]^{|}~]+$/.match?(blurhash) end components.present? && components.none? { |comp| comp > 5 } diff --git a/app/lib/status_finder.rb b/app/lib/status_finder.rb index 22ced8bf8..1a7f2fe69 100644 --- a/app/lib/status_finder.rb +++ b/app/lib/status_finder.rb @@ -27,8 +27,6 @@ class StatusFinder end def verify_action! - unless recognized_params[:action] == 'show' - raise ActiveRecord::RecordNotFound - end + raise ActiveRecord::RecordNotFound unless recognized_params[:action] == 'show' end end diff --git a/app/models/account.rb b/app/models/account.rb index 262285a09..a96e204fa 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -313,9 +313,7 @@ class Account < ApplicationRecord previous = old_fields.find { |item| item['value'] == attr[:value] } - if previous && previous['verified_at'].present? - attr[:verified_at] = previous['verified_at'] - end + attr[:verified_at] = previous['verified_at'] if previous && previous['verified_at'].present? fields << attr end diff --git a/app/models/account_statuses_cleanup_policy.rb b/app/models/account_statuses_cleanup_policy.rb index 49adc6ad0..14ce00abb 100644 --- a/app/models/account_statuses_cleanup_policy.rb +++ b/app/models/account_statuses_cleanup_policy.rb @@ -122,9 +122,7 @@ class AccountStatusesCleanupPolicy < ApplicationRecord # may need to be deleted, so we'll have to start again. redis.del("account_cleanup:#{account.id}") end - if EXCEPTION_THRESHOLDS.map { |name| attribute_change_to_be_saved(name) }.compact.any? { |old, new| old.present? && (new.nil? || new > old) } - redis.del("account_cleanup:#{account.id}") - end + redis.del("account_cleanup:#{account.id}") if EXCEPTION_THRESHOLDS.map { |name| attribute_change_to_be_saved(name) }.compact.any? { |old, new| old.present? && (new.nil? || new > old) } end def validate_local_account @@ -141,9 +139,7 @@ class AccountStatusesCleanupPolicy < ApplicationRecord # has switched to snowflake IDs significantly over 2 years ago anyway. snowflake_id = Mastodon::Snowflake.id_at(min_status_age.seconds.ago, with_random: false) - if max_id.nil? || snowflake_id < max_id - max_id = snowflake_id - end + max_id = snowflake_id if max_id.nil? || snowflake_id < max_id Status.where(Status.arel_table[:id].lteq(max_id)) end diff --git a/app/models/concerns/account_interactions.rb b/app/models/concerns/account_interactions.rb index de8bf338f..325619774 100644 --- a/app/models/concerns/account_interactions.rb +++ b/app/models/concerns/account_interactions.rb @@ -151,9 +151,7 @@ module AccountInteractions remove_potential_friendship(other_account) # When toggling a mute between hiding and allowing notifications, the mute will already exist, so the find_or_create_by! call will return the existing Mute without updating the hide_notifications attribute. Therefore, we check that hide_notifications? is what we want and set it if it isn't. - if mute.hide_notifications? != notifications - mute.update!(hide_notifications: notifications) - end + mute.update!(hide_notifications: notifications) if mute.hide_notifications? != notifications mute end diff --git a/app/models/concerns/omniauthable.rb b/app/models/concerns/omniauthable.rb index 7d54e9d6d..b0aa5be6f 100644 --- a/app/models/concerns/omniauthable.rb +++ b/app/models/concerns/omniauthable.rb @@ -56,9 +56,7 @@ module Omniauthable user = User.new(user_params_from_auth(email, auth)) begin - if /\A#{URI::DEFAULT_PARSER.make_regexp(%w(http https))}\z/.match?(auth.info.image) - user.account.avatar_remote_url = auth.info.image - end + user.account.avatar_remote_url = auth.info.image if /\A#{URI::DEFAULT_PARSER.make_regexp(%w(http https))}\z/.match?(auth.info.image) rescue Mastodon::UnexpectedResponseError user.account.avatar_remote_url = nil end diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 95b28fa15..fa1ddc6d3 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -61,9 +61,7 @@ class InitialStateSerializer < ActiveModel::Serializer store[:disabled_account_id] = object.disabled_account.id.to_s if object.disabled_account store[:moved_to_account_id] = object.moved_to_account.id.to_s if object.moved_to_account - if Rails.configuration.x.single_user_mode - store[:owner] = object.owner&.id&.to_s - end + store[:owner] = object.owner&.id&.to_s if Rails.configuration.x.single_user_mode store end diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb index e280f8eb6..a07840f0c 100644 --- a/app/serializers/rest/instance_serializer.rb +++ b/app/serializers/rest/instance_serializer.rb @@ -95,9 +95,7 @@ class REST::InstanceSerializer < ActiveModel::Serializer end def registrations_message - if Setting.closed_registrations_message.present? - markdown.render(Setting.closed_registrations_message) - end + markdown.render(Setting.closed_registrations_message) if Setting.closed_registrations_message.present? end def markdown diff --git a/app/services/activitypub/fetch_remote_actor_service.rb b/app/services/activitypub/fetch_remote_actor_service.rb index 8908d21e2..e8992b845 100644 --- a/app/services/activitypub/fetch_remote_actor_service.rb +++ b/app/services/activitypub/fetch_remote_actor_service.rb @@ -56,9 +56,7 @@ class ActivityPub::FetchRemoteActorService < BaseService webfinger = webfinger!("acct:#{confirmed_username}@#{confirmed_domain}") @username, @domain = split_acct(webfinger.subject) - unless confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero? - raise Webfinger::RedirectError, "Too many webfinger redirects for URI #{@uri} (stopped at #{@username}@#{@domain})" - end + raise Webfinger::RedirectError, "Too many webfinger redirects for URI #{@uri} (stopped at #{@username}@#{@domain})" unless confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero? raise Error, "Webfinger response for #{@username}@#{@domain} does not loop back to #{@uri}" if webfinger.link('self', 'href') != @uri rescue Webfinger::RedirectError => e diff --git a/app/services/activitypub/process_status_update_service.rb b/app/services/activitypub/process_status_update_service.rb index 1dc393e28..ac7372f74 100644 --- a/app/services/activitypub/process_status_update_service.rb +++ b/app/services/activitypub/process_status_update_service.rb @@ -80,9 +80,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService # If a previously existing media attachment was significantly updated, mark # media attachments as changed even if none were added or removed - if media_attachment_parser.significantly_changes?(media_attachment) - @media_attachments_changed = true - end + @media_attachments_changed = true if media_attachment_parser.significantly_changes?(media_attachment) media_attachment.description = media_attachment_parser.description media_attachment.focus = media_attachment_parser.focus diff --git a/app/services/remove_from_followers_service.rb b/app/services/remove_from_followers_service.rb index 3dac5467f..007d5b1fd 100644 --- a/app/services/remove_from_followers_service.rb +++ b/app/services/remove_from_followers_service.rb @@ -7,9 +7,7 @@ class RemoveFromFollowersService < BaseService source_account.passive_relationships.where(account_id: target_accounts).find_each do |follow| follow.destroy - if source_account.local? && !follow.account.local? && follow.account.activitypub? - create_notification(follow) - end + create_notification(follow) if source_account.local? && !follow.account.local? && follow.account.activitypub? end end diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb index 1ba372cd6..c76df5a0e 100644 --- a/app/services/resolve_account_service.rb +++ b/app/services/resolve_account_service.rb @@ -96,9 +96,7 @@ class ResolveAccountService < BaseService @webfinger = webfinger!("acct:#{confirmed_username}@#{confirmed_domain}") @username, @domain = split_acct(@webfinger.subject) - unless confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero? - raise Webfinger::RedirectError, "Too many webfinger redirects for URI #{uri} (stopped at #{@username}@#{@domain})" - end + raise Webfinger::RedirectError, "Too many webfinger redirects for URI #{uri} (stopped at #{@username}@#{@domain})" unless confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero? rescue Webfinger::GoneError @gone = true end diff --git a/app/services/search_service.rb b/app/services/search_service.rb index 1a76cbb38..93b72fa0c 100644 --- a/app/services/search_service.rb +++ b/app/services/search_service.rb @@ -37,9 +37,7 @@ class SearchService < BaseService def perform_statuses_search! definition = parsed_query.apply(StatusesIndex.filter(term: { searchable_by: @account.id })) - if @options[:account_id].present? - definition = definition.filter(term: { account_id: @options[:account_id] }) - end + definition = definition.filter(term: { account_id: @options[:account_id] }) if @options[:account_id].present? if @options[:min_id].present? || @options[:max_id].present? range = {} diff --git a/lib/mastodon/media_cli.rb b/lib/mastodon/media_cli.rb index 24cc98964..a901a6ab9 100644 --- a/lib/mastodon/media_cli.rb +++ b/lib/mastodon/media_cli.rb @@ -277,9 +277,7 @@ module Mastodon exit(1) end - if options[:days].present? - scope = scope.where('media_attachments.id > ?', Mastodon::Snowflake.id_at(options[:days].days.ago, with_random: false)) - end + scope = scope.where('media_attachments.id > ?', Mastodon::Snowflake.id_at(options[:days].days.ago, with_random: false)) if options[:days].present? processed, aggregate = parallelize_with_progress(scope) do |media_attachment| next if media_attachment.remote_url.blank? || (!options[:force] && media_attachment.file_file_name.present?) diff --git a/lib/mastodon/redis_config.rb b/lib/mastodon/redis_config.rb index 3522fa11e..037ca5edc 100644 --- a/lib/mastodon/redis_config.rb +++ b/lib/mastodon/redis_config.rb @@ -46,6 +46,4 @@ REDIS_SIDEKIQ_PARAMS = { namespace: sidekiq_namespace, }.freeze -if Rails.env.test? - ENV['REDIS_NAMESPACE'] = "mastodon_test#{ENV['TEST_ENV_NUMBER']}" -end +ENV['REDIS_NAMESPACE'] = "mastodon_test#{ENV['TEST_ENV_NUMBER']}" if Rails.env.test? diff --git a/spec/support/matchers/model/model_have_error_on_field.rb b/spec/support/matchers/model/model_have_error_on_field.rb index 85bdd8215..d85db2fca 100644 --- a/spec/support/matchers/model/model_have_error_on_field.rb +++ b/spec/support/matchers/model/model_have_error_on_field.rb @@ -1,8 +1,6 @@ RSpec::Matchers.define :model_have_error_on_field do |expected| match do |record| - if record.errors.empty? - record.valid? - end + record.valid? if record.errors.empty? record.errors.has_key?(expected) end -- cgit From ab7816a4141e88cf7e05ba49638ee95fcc6f71ff Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Sat, 18 Feb 2023 06:39:00 -0500 Subject: Autofix Rubocop Style/Lambda (#23696) --- .rubocop_todo.yml | 12 ------------ app/models/concerns/paginable.rb | 4 ++-- app/models/status.rb | 4 ++-- app/models/tag.rb | 2 +- lib/cli.rb | 2 +- lib/mastodon/domains_cli.rb | 2 +- 6 files changed, 7 insertions(+), 19 deletions(-) (limited to 'app/models') diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 0e94741ae..2ec33fd30 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -2930,18 +2930,6 @@ Style/InverseMethods: - 'app/services/update_account_service.rb' - 'spec/controllers/activitypub/replies_controller_spec.rb' -# Offense count: 7 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: line_count_dependent, lambda, literal -Style/Lambda: - Exclude: - - 'app/models/concerns/paginable.rb' - - 'app/models/status.rb' - - 'app/models/tag.rb' - - 'lib/cli.rb' - - 'lib/mastodon/domains_cli.rb' - # Offense count: 1 # This cop supports unsafe autocorrection (--autocorrect-all). Style/MapToHash: diff --git a/app/models/concerns/paginable.rb b/app/models/concerns/paginable.rb index 62e39f671..b76e78c1e 100644 --- a/app/models/concerns/paginable.rb +++ b/app/models/concerns/paginable.rb @@ -4,7 +4,7 @@ module Paginable extend ActiveSupport::Concern included do - scope :paginate_by_max_id, ->(limit, max_id = nil, since_id = nil) { + scope :paginate_by_max_id, lambda { |limit, max_id = nil, since_id = nil| query = order(arel_table[:id].desc).limit(limit) query = query.where(arel_table[:id].lt(max_id)) if max_id.present? query = query.where(arel_table[:id].gt(since_id)) if since_id.present? @@ -14,7 +14,7 @@ module Paginable # Differs from :paginate_by_max_id in that it gives the results immediately following min_id, # whereas since_id gives the items with largest id, but with since_id as a cutoff. # Results will be in ascending order by id. - scope :paginate_by_min_id, ->(limit, min_id = nil, max_id = nil) { + scope :paginate_by_min_id, lambda { |limit, min_id = nil, max_id = nil| query = reorder(arel_table[:id]).limit(limit) query = query.where(arel_table[:id].gt(min_id)) if min_id.present? query = query.where(arel_table[:id].lt(max_id)) if max_id.present? diff --git a/app/models/status.rb b/app/models/status.rb index b1c49e99a..a924a985f 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -101,12 +101,12 @@ class Status < ApplicationRecord scope :including_silenced_accounts, -> { left_outer_joins(:account).where.not(accounts: { silenced_at: nil }) } scope :not_excluded_by_account, ->(account) { where.not(account_id: account.excluded_from_timeline_account_ids) } scope :not_domain_blocked_by_account, ->(account) { account.excluded_from_timeline_domains.blank? ? left_outer_joins(:account) : left_outer_joins(:account).where('accounts.domain IS NULL OR accounts.domain NOT IN (?)', account.excluded_from_timeline_domains) } - scope :tagged_with_all, ->(tag_ids) { + scope :tagged_with_all, lambda { |tag_ids| Array(tag_ids).map(&:to_i).reduce(self) do |result, id| result.joins("INNER JOIN statuses_tags t#{id} ON t#{id}.status_id = statuses.id AND t#{id}.tag_id = #{id}") end } - scope :tagged_with_none, ->(tag_ids) { + scope :tagged_with_none, lambda { |tag_ids| where('NOT EXISTS (SELECT * FROM statuses_tags forbidden WHERE forbidden.status_id = statuses.id AND forbidden.tag_id IN (?))', tag_ids) } diff --git a/app/models/tag.rb b/app/models/tag.rb index 47a05d00a..98001d60a 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -49,7 +49,7 @@ class Tag < ApplicationRecord scope :listable, -> { where(listable: [true, nil]) } scope :trendable, -> { Setting.trendable_by_default ? where(trendable: [true, nil]) : where(trendable: true) } scope :not_trendable, -> { where(trendable: false) } - scope :recently_used, ->(account) { + scope :recently_used, lambda { |account| joins(:statuses) .where(statuses: { id: account.statuses.select(:id).limit(1000) }) .group(:id).order(Arel.sql('count(*) desc')) diff --git a/lib/cli.rb b/lib/cli.rb index 35c00e736..157465c4b 100644 --- a/lib/cli.rb +++ b/lib/cli.rb @@ -121,7 +121,7 @@ module Mastodon prompt.warn('Do NOT interrupt this process...') - delete_account = ->(account) do + delete_account = lambda do |account| payload = ActiveModelSerializers::SerializableResource.new( account, serializer: ActivityPub::DeleteActorSerializer, diff --git a/lib/mastodon/domains_cli.rb b/lib/mastodon/domains_cli.rb index 81ee53c18..f24a54e7e 100644 --- a/lib/mastodon/domains_cli.rb +++ b/lib/mastodon/domains_cli.rb @@ -139,7 +139,7 @@ module Mastodon pool = Concurrent::ThreadPoolExecutor.new(min_threads: 0, max_threads: options[:concurrency], idletime: 10, auto_terminate: true, max_queue: 0) - work_unit = ->(domain) do + work_unit = lambda do |domain| next if stats.key?(domain) next if options[:exclude_suspended] && domain.match?(blocked_domains) -- cgit From 2177daeae92b77be6797ba8f2ab6ebe1e641e078 Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Sat, 18 Feb 2023 17:09:40 -0500 Subject: Autofix Rubocop Style/RedundantBegin (#23703) --- .rubocop_todo.yml | 73 ---------------------- app/controllers/admin/dashboard_controller.rb | 12 ++-- app/controllers/api/v1/announcements_controller.rb | 4 +- app/controllers/api/v1/trends/links_controller.rb | 12 ++-- .../api/v1/trends/statuses_controller.rb | 12 ++-- app/controllers/api/v1/trends/tags_controller.rb | 12 ++-- app/controllers/concerns/rate_limit_headers.rb | 12 ++-- .../concerns/two_factor_authentication_concern.rb | 12 ++-- app/helpers/admin/dashboard_helper.rb | 24 ++++--- app/helpers/admin/trends/statuses_helper.rb | 12 ++-- app/helpers/branding_helper.rb | 14 ++--- app/helpers/domain_control_helper.rb | 12 ++-- app/helpers/formatting_helper.rb | 44 ++++++------- app/helpers/instance_helper.rb | 12 ++-- app/helpers/jsonld_helper.rb | 16 +++-- app/lib/activity_tracker.rb | 14 ++--- app/lib/activitypub/activity/create.rb | 38 ++++++----- app/lib/activitypub/forwarder.rb | 12 ++-- .../dimension/software_versions_dimension.rb | 12 ++-- .../metrics/dimension/space_usage_dimension.rb | 12 ++-- app/lib/extractor.rb | 10 ++- app/lib/importer/statuses_index_importer.rb | 12 ++-- app/lib/link_details_extractor.rb | 30 +++++---- app/lib/request.rb | 34 +++++----- app/models/account.rb | 13 ++-- app/models/account/field.rb | 12 ++-- app/models/admin/account_action.rb | 12 ++-- app/models/announcement.rb | 12 ++-- app/models/concerns/account_merging.rb | 16 ++--- app/models/concerns/pam_authenticable.rb | 12 ++-- app/models/email_domain_block.rb | 12 ++-- app/models/form/admin_settings.rb | 12 ++-- app/models/form/custom_emoji_batch.rb | 12 ++-- app/models/notification.rb | 12 ++-- app/models/remote_follow.rb | 12 ++-- app/models/status.rb | 13 ++-- app/models/status_edit.rb | 14 ++--- app/models/trends/links.rb | 24 +++---- app/models/trends/statuses.rb | 26 ++++---- app/models/trends/tag_filter.rb | 12 ++-- app/models/trends/tags.rb | 12 ++-- app/models/web/push_subscription.rb | 24 +++---- app/presenters/tag_relationships_presenter.rb | 12 ++-- app/services/account_search_service.rb | 16 +++-- .../fetch_featured_tags_collection_service.rb | 14 ++--- .../activitypub/fetch_remote_status_service.rb | 12 ++-- app/services/fetch_link_card_service.rb | 18 +++--- app/services/process_mentions_service.rb | 12 ++-- app/services/reblog_service.rb | 12 ++-- app/services/resolve_account_service.rb | 12 ++-- app/validators/domain_validator.rb | 12 ++-- app/validators/existing_username_validator.rb | 14 ++--- app/validators/import_validator.rb | 12 ++-- app/workers/backup_worker.rb | 10 ++- app/workers/post_process_media_worker.rb | 12 ++-- .../scheduler/follow_recommendations_scheduler.rb | 12 ++-- .../20180528141303_fix_accounts_unique_index.rb | 16 ++--- db/migrate/20180812173710_copy_status_stats.rb | 10 ++- db/migrate/20181116173541_copy_account_stats.rb | 10 ++- lib/mastodon/accounts_cli.rb | 28 ++++----- lib/mastodon/cli_helper.rb | 42 ++++++------- lib/mastodon/ip_blocks_cli.rb | 12 ++-- lib/mastodon/maintenance_cli.rb | 64 +++++++------------ lib/mastodon/media_cli.rb | 12 ++-- lib/mastodon/search_cli.rb | 12 ++-- lib/mastodon/upgrade_cli.rb | 18 +++--- lib/paperclip/color_extractor.rb | 12 ++-- lib/sanitize_ext/sanitize_config.rb | 12 ++-- lib/tasks/db.rake | 14 ++--- 69 files changed, 462 insertions(+), 699 deletions(-) (limited to 'app/models') diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 73dae59c5..7620025cf 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -2958,79 +2958,6 @@ Style/RedundantArgument: - 'app/helpers/application_helper.rb' - 'lib/tasks/emojis.rake' -# Offense count: 83 -# This cop supports safe autocorrection (--autocorrect). -Style/RedundantBegin: - Exclude: - - 'app/controllers/admin/dashboard_controller.rb' - - 'app/controllers/api/v1/announcements_controller.rb' - - 'app/controllers/api/v1/trends/links_controller.rb' - - 'app/controllers/api/v1/trends/statuses_controller.rb' - - 'app/controllers/api/v1/trends/tags_controller.rb' - - 'app/controllers/concerns/rate_limit_headers.rb' - - 'app/controllers/concerns/two_factor_authentication_concern.rb' - - 'app/helpers/admin/dashboard_helper.rb' - - 'app/helpers/admin/trends/statuses_helper.rb' - - 'app/helpers/branding_helper.rb' - - 'app/helpers/domain_control_helper.rb' - - 'app/helpers/formatting_helper.rb' - - 'app/helpers/instance_helper.rb' - - 'app/helpers/jsonld_helper.rb' - - 'app/lib/activity_tracker.rb' - - 'app/lib/activitypub/activity/create.rb' - - 'app/lib/activitypub/forwarder.rb' - - 'app/lib/admin/metrics/dimension/software_versions_dimension.rb' - - 'app/lib/admin/metrics/dimension/space_usage_dimension.rb' - - 'app/lib/extractor.rb' - - 'app/lib/importer/statuses_index_importer.rb' - - 'app/lib/link_details_extractor.rb' - - 'app/lib/request.rb' - - 'app/models/account.rb' - - 'app/models/account/field.rb' - - 'app/models/admin/account_action.rb' - - 'app/models/announcement.rb' - - 'app/models/concerns/account_merging.rb' - - 'app/models/concerns/pam_authenticable.rb' - - 'app/models/email_domain_block.rb' - - 'app/models/form/admin_settings.rb' - - 'app/models/form/custom_emoji_batch.rb' - - 'app/models/notification.rb' - - 'app/models/remote_follow.rb' - - 'app/models/status.rb' - - 'app/models/status_edit.rb' - - 'app/models/trends/links.rb' - - 'app/models/trends/statuses.rb' - - 'app/models/trends/tag_filter.rb' - - 'app/models/trends/tags.rb' - - 'app/models/web/push_subscription.rb' - - 'app/presenters/tag_relationships_presenter.rb' - - 'app/services/account_search_service.rb' - - 'app/services/activitypub/fetch_featured_tags_collection_service.rb' - - 'app/services/activitypub/fetch_remote_status_service.rb' - - 'app/services/fetch_link_card_service.rb' - - 'app/services/process_mentions_service.rb' - - 'app/services/reblog_service.rb' - - 'app/services/resolve_account_service.rb' - - 'app/validators/domain_validator.rb' - - 'app/validators/existing_username_validator.rb' - - 'app/validators/import_validator.rb' - - 'app/workers/backup_worker.rb' - - 'app/workers/post_process_media_worker.rb' - - 'app/workers/scheduler/follow_recommendations_scheduler.rb' - - 'db/migrate/20180528141303_fix_accounts_unique_index.rb' - - 'db/migrate/20180812173710_copy_status_stats.rb' - - 'db/migrate/20181116173541_copy_account_stats.rb' - - 'lib/mastodon/accounts_cli.rb' - - 'lib/mastodon/cli_helper.rb' - - 'lib/mastodon/ip_blocks_cli.rb' - - 'lib/mastodon/maintenance_cli.rb' - - 'lib/mastodon/media_cli.rb' - - 'lib/mastodon/search_cli.rb' - - 'lib/mastodon/upgrade_cli.rb' - - 'lib/paperclip/color_extractor.rb' - - 'lib/sanitize_ext/sanitize_config.rb' - - 'lib/tasks/db.rake' - # Offense count: 16 # This cop supports safe autocorrection (--autocorrect). Style/RedundantRegexpCharacterClass: 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/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/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 21adfa2a1..75c3ed218 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/concerns/rate_limit_headers.rb b/app/controllers/concerns/rate_limit_headers.rb index b21abfb03..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 diff --git a/app/controllers/concerns/two_factor_authentication_concern.rb b/app/controllers/concerns/two_factor_authentication_concern.rb index 27f2367a8..e69b67a79 100644 --- a/app/controllers/concerns/two_factor_authentication_concern.rb +++ b/app/controllers/concerns/two_factor_authentication_concern.rb @@ -79,13 +79,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/helpers/admin/dashboard_helper.rb b/app/helpers/admin/dashboard_helper.rb index c21d41341..6096ff138 100644 --- a/app/helpers/admin/dashboard_helper.rb +++ b/app/helpers/admin/dashboard_helper.rb @@ -19,19 +19,17 @@ module Admin::DashboardHelper end def relevant_account_timestamp(account) - timestamp, exact = begin - if account.user_current_sign_in_at && account.user_current_sign_in_at < 24.hours.ago - [account.user_current_sign_in_at, true] - elsif account.user_current_sign_in_at - [account.user_current_sign_in_at, false] - elsif account.user_pending? - [account.user_created_at, true] - elsif account.last_status_at.present? - [account.last_status_at, true] - else - [nil, false] - end - end + timestamp, exact = if account.user_current_sign_in_at && account.user_current_sign_in_at < 24.hours.ago + [account.user_current_sign_in_at, true] + elsif account.user_current_sign_in_at + [account.user_current_sign_in_at, false] + elsif account.user_pending? + [account.user_created_at, true] + elsif account.last_status_at.present? + [account.last_status_at, true] + else + [nil, false] + end return '-' if timestamp.nil? return t('generic.today') unless exact diff --git a/app/helpers/admin/trends/statuses_helper.rb b/app/helpers/admin/trends/statuses_helper.rb index 214c1e2a6..79fee44dc 100644 --- a/app/helpers/admin/trends/statuses_helper.rb +++ b/app/helpers/admin/trends/statuses_helper.rb @@ -2,13 +2,11 @@ module Admin::Trends::StatusesHelper def one_line_preview(status) - text = begin - if status.local? - status.text.split("\n").first - else - Nokogiri::HTML(status.text).css('html > body > *').first&.text - end - end + text = if status.local? + status.text.split("\n").first + else + Nokogiri::HTML(status.text).css('html > body > *').first&.text + end return '' if text.blank? diff --git a/app/helpers/branding_helper.rb b/app/helpers/branding_helper.rb index ad7702aea..548c95411 100644 --- a/app/helpers/branding_helper.rb +++ b/app/helpers/branding_helper.rb @@ -23,14 +23,12 @@ module BrandingHelper end def render_symbol(version = :icon) - path = begin - case version - when :icon - 'logo-symbol-icon.svg' - when :wordmark - 'logo-symbol-wordmark.svg' - end - end + path = case version + when :icon + 'logo-symbol-icon.svg' + when :wordmark + 'logo-symbol-wordmark.svg' + end render(file: Rails.root.join('app', 'javascript', 'images', path)).html_safe # rubocop:disable Rails/OutputSafety end diff --git a/app/helpers/domain_control_helper.rb b/app/helpers/domain_control_helper.rb index ac60cad29..ffcf375ea 100644 --- a/app/helpers/domain_control_helper.rb +++ b/app/helpers/domain_control_helper.rb @@ -4,13 +4,11 @@ module DomainControlHelper def domain_not_allowed?(uri_or_domain) return if uri_or_domain.blank? - domain = begin - if uri_or_domain.include?('://') - Addressable::URI.parse(uri_or_domain).host - else - uri_or_domain - end - end + domain = if uri_or_domain.include?('://') + Addressable::URI.parse(uri_or_domain).host + else + uri_or_domain + end if whitelist_mode? !DomainAllow.allowed?(domain) diff --git a/app/helpers/formatting_helper.rb b/app/helpers/formatting_helper.rb index c70931489..d390b9bc9 100644 --- a/app/helpers/formatting_helper.rb +++ b/app/helpers/formatting_helper.rb @@ -21,30 +21,26 @@ module FormattingHelper def rss_status_content_format(status) html = status_content_format(status) - before_html = begin - if status.spoiler_text? - tag.p do - tag.strong do - I18n.t('rss.content_warning', locale: available_locale_or_nil(status.language) || I18n.default_locale) - end - - status.spoiler_text - end + tag.hr - end - end - - after_html = begin - if status.preloadable_poll - tag.p do - safe_join( - status.preloadable_poll.options.map do |o| - tag.send(status.preloadable_poll.multiple? ? 'checkbox' : 'radio', o, disabled: true) - end, - tag.br - ) - end - end - end + before_html = if status.spoiler_text? + tag.p do + tag.strong do + I18n.t('rss.content_warning', locale: available_locale_or_nil(status.language) || I18n.default_locale) + end + + status.spoiler_text + end + tag.hr + end + + after_html = if status.preloadable_poll + tag.p do + safe_join( + status.preloadable_poll.options.map do |o| + tag.send(status.preloadable_poll.multiple? ? 'checkbox' : 'radio', o, disabled: true) + end, + tag.br + ) + end + end prerender_custom_emojis( safe_join([before_html, html, after_html]), diff --git a/app/helpers/instance_helper.rb b/app/helpers/instance_helper.rb index daacb535b..bedfe6f30 100644 --- a/app/helpers/instance_helper.rb +++ b/app/helpers/instance_helper.rb @@ -10,13 +10,11 @@ module InstanceHelper end def description_for_sign_up - prefix = begin - if @invite.present? - I18n.t('auth.description.prefix_invited_by_user', name: @invite.user.account.username) - else - I18n.t('auth.description.prefix_sign_up') - end - end + prefix = if @invite.present? + I18n.t('auth.description.prefix_invited_by_user', name: @invite.user.account.username) + else + I18n.t('auth.description.prefix_sign_up') + end safe_join([prefix, I18n.t('auth.description.suffix')], ' ') end diff --git a/app/helpers/jsonld_helper.rb b/app/helpers/jsonld_helper.rb index e5787fd47..24362b61e 100644 --- a/app/helpers/jsonld_helper.rb +++ b/app/helpers/jsonld_helper.rb @@ -26,15 +26,13 @@ module JsonLdHelper # The url attribute can be a string, an array of strings, or an array of objects. # The objects could include a mimeType. Not-included mimeType means it's text/html. def url_to_href(value, preferred_type = nil) - single_value = begin - if value.is_a?(Array) && !value.first.is_a?(String) - value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) } - elsif value.is_a?(Array) - value.first - else - value - end - end + single_value = if value.is_a?(Array) && !value.first.is_a?(String) + value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) } + elsif value.is_a?(Array) + value.first + else + value + end if single_value.nil? || single_value.is_a?(String) single_value diff --git a/app/lib/activity_tracker.rb b/app/lib/activity_tracker.rb index 6d3401b37..8829d8605 100644 --- a/app/lib/activity_tracker.rb +++ b/app/lib/activity_tracker.rb @@ -27,14 +27,12 @@ class ActivityTracker (start_at.to_date...end_at.to_date).map do |date| key = key_at(date.to_time(:utc)) - value = begin - case @type - when :basic - redis.get(key).to_i - when :unique - redis.pfcount(key) - end - end + value = case @type + when :basic + redis.get(key).to_i + when :unique + redis.pfcount(key) + end [date, value] end diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index f82112c02..e2355bfbc 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -108,26 +108,24 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def process_status_params @status_parser = ActivityPub::Parser::StatusParser.new(@json, followers_collection: @account.followers_url) - @params = begin - { - uri: @status_parser.uri, - url: @status_parser.url || @status_parser.uri, - account: @account, - text: converted_object_type? ? converted_text : (@status_parser.text || ''), - language: @status_parser.language, - spoiler_text: converted_object_type? ? '' : (@status_parser.spoiler_text || ''), - created_at: @status_parser.created_at, - edited_at: @status_parser.edited_at && @status_parser.edited_at != @status_parser.created_at ? @status_parser.edited_at : nil, - override_timestamps: @options[:override_timestamps], - reply: @status_parser.reply, - sensitive: @account.sensitized? || @status_parser.sensitive || false, - visibility: @status_parser.visibility, - thread: replied_to_status, - conversation: conversation_from_uri(@object['conversation']), - media_attachment_ids: process_attachments.take(4).map(&:id), - poll: process_poll, - } - end + @params = { + uri: @status_parser.uri, + url: @status_parser.url || @status_parser.uri, + account: @account, + text: converted_object_type? ? converted_text : (@status_parser.text || ''), + language: @status_parser.language, + spoiler_text: converted_object_type? ? '' : (@status_parser.spoiler_text || ''), + created_at: @status_parser.created_at, + edited_at: @status_parser.edited_at && @status_parser.edited_at != @status_parser.created_at ? @status_parser.edited_at : nil, + override_timestamps: @options[:override_timestamps], + reply: @status_parser.reply, + sensitive: @account.sensitized? || @status_parser.sensitive || false, + visibility: @status_parser.visibility, + thread: replied_to_status, + conversation: conversation_from_uri(@object['conversation']), + media_attachment_ids: process_attachments.take(4).map(&:id), + poll: process_poll, + } end def process_audience diff --git a/app/lib/activitypub/forwarder.rb b/app/lib/activitypub/forwarder.rb index 4206b9d82..b01d63e58 100644 --- a/app/lib/activitypub/forwarder.rb +++ b/app/lib/activitypub/forwarder.rb @@ -28,13 +28,11 @@ class ActivityPub::Forwarder end def signature_account_id - @signature_account_id ||= begin - if in_reply_to_local? - in_reply_to.account_id - else - reblogged_by_account_ids.first - end - end + @signature_account_id ||= if in_reply_to_local? + in_reply_to.account_id + else + reblogged_by_account_ids.first + end end def inboxes diff --git a/app/lib/admin/metrics/dimension/software_versions_dimension.rb b/app/lib/admin/metrics/dimension/software_versions_dimension.rb index 816615f99..9ab3776c9 100644 --- a/app/lib/admin/metrics/dimension/software_versions_dimension.rb +++ b/app/lib/admin/metrics/dimension/software_versions_dimension.rb @@ -58,12 +58,10 @@ class Admin::Metrics::Dimension::SoftwareVersionsDimension < Admin::Metrics::Dim end 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 diff --git a/app/lib/admin/metrics/dimension/space_usage_dimension.rb b/app/lib/admin/metrics/dimension/space_usage_dimension.rb index 5867c5bab..cc8560890 100644 --- a/app/lib/admin/metrics/dimension/space_usage_dimension.rb +++ b/app/lib/admin/metrics/dimension/space_usage_dimension.rb @@ -59,12 +59,10 @@ class Admin::Metrics::Dimension::SpaceUsageDimension < Admin::Metrics::Dimension end 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 diff --git a/app/lib/extractor.rb b/app/lib/extractor.rb index 1eba689ef..540bbe1a9 100644 --- a/app/lib/extractor.rb +++ b/app/lib/extractor.rb @@ -8,12 +8,10 @@ module Extractor module_function def extract_entities_with_indices(text, options = {}, &block) - entities = begin - extract_urls_with_indices(text, options) + - extract_hashtags_with_indices(text, check_url_overlap: false) + - extract_mentions_or_lists_with_indices(text) + - extract_extra_uris_with_indices(text) - end + entities = extract_urls_with_indices(text, options) + + extract_hashtags_with_indices(text, check_url_overlap: false) + + extract_mentions_or_lists_with_indices(text) + + extract_extra_uris_with_indices(text) return [] if entities.empty? diff --git a/app/lib/importer/statuses_index_importer.rb b/app/lib/importer/statuses_index_importer.rb index 5b5153d5c..b0721c2e0 100644 --- a/app/lib/importer/statuses_index_importer.rb +++ b/app/lib/importer/statuses_index_importer.rb @@ -24,13 +24,11 @@ class Importer::StatusesIndexImporter < Importer::BaseImporter # is called before rendering the data and we need to filter based # on the results of the filter, so this filtering happens here instead bulk.map! do |entry| - new_entry = begin - if entry[:index] && entry.dig(:index, :data, 'searchable_by').blank? - { delete: entry[:index].except(:data) } - else - entry - end - end + new_entry = if entry[:index] && entry.dig(:index, :data, 'searchable_by').blank? + { delete: entry[:index].except(:data) } + else + entry + end if new_entry[:index] indexed += 1 diff --git a/app/lib/link_details_extractor.rb b/app/lib/link_details_extractor.rb index 2e0672abe..74a7d0f3b 100644 --- a/app/lib/link_details_extractor.rb +++ b/app/lib/link_details_extractor.rb @@ -232,26 +232,24 @@ class LinkDetailsExtractor end def structured_data - @structured_data ||= begin - # Some publications have more than one JSON-LD definition on the page, - # and some of those definitions aren't valid JSON either, so we have - # to loop through here until we find something that is the right type - # and doesn't break - document.xpath('//script[@type="application/ld+json"]').filter_map do |element| - json_ld = element.content&.gsub(CDATA_JUNK_PATTERN, '') + # Some publications have more than one JSON-LD definition on the page, + # and some of those definitions aren't valid JSON either, so we have + # to loop through here until we find something that is the right type + # and doesn't break + @structured_data ||= document.xpath('//script[@type="application/ld+json"]').filter_map do |element| + json_ld = element.content&.gsub(CDATA_JUNK_PATTERN, '') - next if json_ld.blank? + next if json_ld.blank? - structured_data = StructuredData.new(html_entities.decode(json_ld)) + structured_data = StructuredData.new(html_entities.decode(json_ld)) - next unless structured_data.valid? + next unless structured_data.valid? - structured_data - rescue Oj::ParseError, EncodingError - Rails.logger.debug { "Invalid JSON-LD in #{@original_url}" } - next - end.first - end + structured_data + rescue Oj::ParseError, EncodingError + Rails.logger.debug { "Invalid JSON-LD in #{@original_url}" } + next + end.first end def document diff --git a/app/lib/request.rb b/app/lib/request.rb index 0508169dc..be6a69b3f 100644 --- a/app/lib/request.rb +++ b/app/lib/request.rb @@ -215,26 +215,24 @@ class Request addr_by_socket = {} addresses.each do |address| - begin - check_private_address(address, host) + check_private_address(address, host) - sock = ::Socket.new(address.is_a?(Resolv::IPv6) ? ::Socket::AF_INET6 : ::Socket::AF_INET, ::Socket::SOCK_STREAM, 0) - sockaddr = ::Socket.pack_sockaddr_in(port, address.to_s) + sock = ::Socket.new(address.is_a?(Resolv::IPv6) ? ::Socket::AF_INET6 : ::Socket::AF_INET, ::Socket::SOCK_STREAM, 0) + sockaddr = ::Socket.pack_sockaddr_in(port, address.to_s) - sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1) + sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1) - sock.connect_nonblock(sockaddr) + sock.connect_nonblock(sockaddr) - # If that hasn't raised an exception, we somehow managed to connect - # immediately, close pending sockets and return immediately - socks.each(&:close) - return sock - rescue IO::WaitWritable - socks << sock - addr_by_socket[sock] = sockaddr - rescue => e - outer_e = e - end + # If that hasn't raised an exception, we somehow managed to connect + # immediately, close pending sockets and return immediately + socks.each(&:close) + return sock + rescue IO::WaitWritable + socks << sock + addr_by_socket[sock] = sockaddr + rescue => e + outer_e = e end until socks.empty? @@ -279,9 +277,7 @@ class Request end def private_address_exceptions - @private_address_exceptions = begin - (ENV['ALLOWED_PRIVATE_ADDRESSES'] || '').split(',').map { |addr| IPAddr.new(addr) } - end + @private_address_exceptions = (ENV['ALLOWED_PRIVATE_ADDRESSES'] || '').split(',').map { |addr| IPAddr.new(addr) } end end end diff --git a/app/models/account.rb b/app/models/account.rb index a96e204fa..2c0cd577e 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -459,13 +459,12 @@ class Account < ApplicationRecord return [] if text.blank? text.scan(MENTION_RE).map { |match| match.first.split('@', 2) }.uniq.filter_map do |(username, domain)| - domain = begin - if TagManager.instance.local_domain?(domain) - nil - else - TagManager.instance.normalize_domain(domain) - end - end + domain = if TagManager.instance.local_domain?(domain) + nil + else + TagManager.instance.normalize_domain(domain) + end + EntityCache.instance.mention(username, domain) end end diff --git a/app/models/account/field.rb b/app/models/account/field.rb index 4db4cac30..98c29726d 100644 --- a/app/models/account/field.rb +++ b/app/models/account/field.rb @@ -25,13 +25,11 @@ class Account::Field < ActiveModelSerializers::Model end def value_for_verification - @value_for_verification ||= begin - if account.local? - value - else - extract_url_from_html - end - end + @value_for_verification ||= if account.local? + value + else + extract_url_from_html + end end def verifiable? diff --git a/app/models/admin/account_action.rb b/app/models/admin/account_action.rb index bce0d6e17..1ce28f5c8 100644 --- a/app/models/admin/account_action.rb +++ b/app/models/admin/account_action.rb @@ -166,13 +166,11 @@ class Admin::AccountAction end def reports - @reports ||= begin - if type == 'none' - with_report? ? [report] : [] - else - Report.where(target_account: target_account).unresolved - end - end + @reports ||= if type == 'none' + with_report? ? [report] : [] + else + Report.where(target_account: target_account).unresolved + end end def warning_preset diff --git a/app/models/announcement.rb b/app/models/announcement.rb index 4b2cb4c6d..898bf3efa 100644 --- a/app/models/announcement.rb +++ b/app/models/announcement.rb @@ -54,13 +54,11 @@ class Announcement < ApplicationRecord end def statuses - @statuses ||= begin - if status_ids.nil? - [] - else - Status.where(id: status_ids, visibility: [:public, :unlisted]) - end - end + @statuses ||= if status_ids.nil? + [] + else + Status.where(id: status_ids, visibility: [:public, :unlisted]) + end end def tags diff --git a/app/models/concerns/account_merging.rb b/app/models/concerns/account_merging.rb index 8161761fb..41071633d 100644 --- a/app/models/concerns/account_merging.rb +++ b/app/models/concerns/account_merging.rb @@ -21,11 +21,9 @@ module AccountMerging owned_classes.each do |klass| klass.where(account_id: other_account.id).find_each do |record| - begin - record.update_attribute(:account_id, id) - rescue ActiveRecord::RecordNotUnique - next - end + record.update_attribute(:account_id, id) + rescue ActiveRecord::RecordNotUnique + next end end @@ -36,11 +34,9 @@ module AccountMerging target_classes.each do |klass| klass.where(target_account_id: other_account.id).find_each do |record| - begin - record.update_attribute(:target_account_id, id) - rescue ActiveRecord::RecordNotUnique - next - end + record.update_attribute(:target_account_id, id) + rescue ActiveRecord::RecordNotUnique + next end end diff --git a/app/models/concerns/pam_authenticable.rb b/app/models/concerns/pam_authenticable.rb index 6169d4dfa..f97f986a4 100644 --- a/app/models/concerns/pam_authenticable.rb +++ b/app/models/concerns/pam_authenticable.rb @@ -42,13 +42,11 @@ module PamAuthenticable def self.pam_get_user(attributes = {}) return nil unless attributes[:email] - resource = begin - if Devise.check_at_sign && !attributes[:email].index('@') - joins(:account).find_by(accounts: { username: attributes[:email] }) - else - find_by(email: attributes[:email]) - end - end + resource = if Devise.check_at_sign && !attributes[:email].index('@') + joins(:account).find_by(accounts: { username: attributes[:email] }) + else + find_by(email: attributes[:email]) + end if resource.nil? resource = new(email: attributes[:email], agreement: true) diff --git a/app/models/email_domain_block.rb b/app/models/email_domain_block.rb index 10a0e5102..3a56e4f2a 100644 --- a/app/models/email_domain_block.rb +++ b/app/models/email_domain_block.rb @@ -69,13 +69,11 @@ class EmailDomainBlock < ApplicationRecord def extract_uris(domain_or_domains) Array(domain_or_domains).map do |str| - domain = begin - if str.include?('@') - str.split('@', 2).last - else - str - end - end + domain = if str.include?('@') + str.split('@', 2).last + else + str + end Addressable::URI.new.tap { |u| u.host = domain.strip } if domain.present? rescue Addressable::URI::InvalidURIError, IDN::Idna::IdnaError diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index 070478e8e..95c53084a 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -76,13 +76,11 @@ class Form::AdminSettings define_method(key) do return instance_variable_get("@#{key}") if instance_variable_defined?("@#{key}") - stored_value = begin - if UPLOAD_KEYS.include?(key) - SiteUpload.where(var: key).first_or_initialize(var: key) - else - Setting.public_send(key) - end - end + stored_value = if UPLOAD_KEYS.include?(key) + SiteUpload.where(var: key).first_or_initialize(var: key) + else + Setting.public_send(key) + end instance_variable_set("@#{key}", stored_value) end diff --git a/app/models/form/custom_emoji_batch.rb b/app/models/form/custom_emoji_batch.rb index f4fa84c10..484415f90 100644 --- a/app/models/form/custom_emoji_batch.rb +++ b/app/models/form/custom_emoji_batch.rb @@ -36,13 +36,11 @@ class Form::CustomEmojiBatch def update! custom_emojis.each { |custom_emoji| authorize(custom_emoji, :update?) } - category = begin - if category_id.present? - CustomEmojiCategory.find(category_id) - elsif category_name.present? - CustomEmojiCategory.find_or_create_by!(name: category_name) - end - end + category = if category_id.present? + CustomEmojiCategory.find(category_id) + elsif category_name.present? + CustomEmojiCategory.find_or_create_by!(name: category_name) + end custom_emojis.each do |custom_emoji| custom_emoji.update(category_id: category&.id) diff --git a/app/models/notification.rb b/app/models/notification.rb index bbc63c1c0..01155c363 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -87,13 +87,11 @@ class Notification < ApplicationRecord class << self def browserable(types: [], exclude_types: [], from_account_id: nil) - requested_types = begin - if types.empty? - TYPES - else - types.map(&:to_sym) & TYPES - end - end + requested_types = if types.empty? + TYPES + else + types.map(&:to_sym) & TYPES + end requested_types -= exclude_types.map(&:to_sym) diff --git a/app/models/remote_follow.rb b/app/models/remote_follow.rb index 911c06713..10715ac97 100644 --- a/app/models/remote_follow.rb +++ b/app/models/remote_follow.rb @@ -36,13 +36,11 @@ class RemoteFollow username, domain = value.strip.gsub(/\A@/, '').split('@') - domain = begin - if TagManager.instance.local_domain?(domain) - nil - else - TagManager.instance.normalize_domain(domain) - end - end + domain = if TagManager.instance.local_domain?(domain) + nil + else + TagManager.instance.normalize_domain(domain) + end [username, domain].compact.join('@') rescue Addressable::URI::InvalidURIError diff --git a/app/models/status.rb b/app/models/status.rb index a924a985f..102dfa994 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -368,13 +368,12 @@ class Status < ApplicationRecord return [] if text.blank? text.scan(FetchLinkCardService::URL_PATTERN).map(&:second).uniq.filter_map do |url| - status = begin - if TagManager.instance.local_url?(url) - ActivityPub::TagManager.instance.uri_to_resource(url, Status) - else - EntityCache.instance.status(url) - end - end + status = if TagManager.instance.local_url?(url) + ActivityPub::TagManager.instance.uri_to_resource(url, Status) + else + EntityCache.instance.status(url) + end + status&.distributable? ? status : nil end end diff --git a/app/models/status_edit.rb b/app/models/status_edit.rb index e33470226..dd2d5fc1e 100644 --- a/app/models/status_edit.rb +++ b/app/models/status_edit.rb @@ -51,14 +51,12 @@ class StatusEdit < ApplicationRecord def ordered_media_attachments return @ordered_media_attachments if defined?(@ordered_media_attachments) - @ordered_media_attachments = begin - if ordered_media_attachment_ids.nil? - [] - else - map = status.media_attachments.index_by(&:id) - ordered_media_attachment_ids.map.with_index { |media_attachment_id, index| PreservedMediaAttachment.new(media_attachment: map[media_attachment_id], description: media_descriptions[index]) } - end - end + @ordered_media_attachments = if ordered_media_attachment_ids.nil? + [] + else + map = status.media_attachments.index_by(&:id) + ordered_media_attachment_ids.map.with_index { |media_attachment_id, index| PreservedMediaAttachment.new(media_attachment: map[media_attachment_id], description: media_descriptions[index]) } + end end def proper diff --git a/app/models/trends/links.rb b/app/models/trends/links.rb index 8808b3ab6..c94f7c023 100644 --- a/app/models/trends/links.rb +++ b/app/models/trends/links.rb @@ -113,13 +113,11 @@ class Trends::Links < Trends::Base max_score = preview_card.max_score max_score = 0 if max_time.nil? || max_time < (at_time - options[:max_score_cooldown]) - score = begin - if expected > observed || observed < options[:threshold] - 0 - else - ((observed - expected)**2) / expected - end - end + score = if expected > observed || observed < options[:threshold] + 0 + else + ((observed - expected)**2) / expected + end if score > max_score max_score = score @@ -129,13 +127,11 @@ class Trends::Links < Trends::Base preview_card.update_columns(max_score: max_score, max_score_at: max_time) end - decaying_score = begin - if max_score.zero? || !valid_locale?(preview_card.language) - 0 - else - max_score * (0.5**((at_time.to_f - max_time.to_f) / options[:max_score_halflife].to_f)) - end - end + decaying_score = if max_score.zero? || !valid_locale?(preview_card.language) + 0 + else + max_score * (0.5**((at_time.to_f - max_time.to_f) / options[:max_score_halflife].to_f)) + end [decaying_score, preview_card] end diff --git a/app/models/trends/statuses.rb b/app/models/trends/statuses.rb index c9ef7c8f2..84bff9c02 100644 --- a/app/models/trends/statuses.rb +++ b/app/models/trends/statuses.rb @@ -99,21 +99,17 @@ class Trends::Statuses < Trends::Base expected = 1.0 observed = (status.reblogs_count + status.favourites_count).to_f - score = begin - if expected > observed || observed < options[:threshold] - 0 - else - ((observed - expected)**2) / expected - end - end - - decaying_score = begin - if score.zero? || !eligible?(status) - 0 - else - score * (0.5**((at_time.to_f - status.created_at.to_f) / options[:score_halflife].to_f)) - end - end + score = if expected > observed || observed < options[:threshold] + 0 + else + ((observed - expected)**2) / expected + end + + decaying_score = if score.zero? || !eligible?(status) + 0 + else + score * (0.5**((at_time.to_f - status.created_at.to_f) / options[:score_halflife].to_f)) + end [decaying_score, status] end diff --git a/app/models/trends/tag_filter.rb b/app/models/trends/tag_filter.rb index 3b142efc4..46b747819 100644 --- a/app/models/trends/tag_filter.rb +++ b/app/models/trends/tag_filter.rb @@ -13,13 +13,11 @@ class Trends::TagFilter end def results - scope = begin - if params[:status] == 'pending_review' - Tag.unscoped - else - trending_scope - end - end + scope = if params[:status] == 'pending_review' + Tag.unscoped + else + trending_scope + end params.each do |key, value| next if key.to_s == 'page' diff --git a/app/models/trends/tags.rb b/app/models/trends/tags.rb index 19ade52ba..931532990 100644 --- a/app/models/trends/tags.rb +++ b/app/models/trends/tags.rb @@ -63,13 +63,11 @@ class Trends::Tags < Trends::Base max_score = tag.max_score max_score = 0 if max_time.nil? || max_time < (at_time - options[:max_score_cooldown]) - score = begin - if expected > observed || observed < options[:threshold] - 0 - else - ((observed - expected)**2) / expected - end - end + score = if expected > observed || observed < options[:threshold] + 0 + else + ((observed - expected)**2) / expected + end if score > max_score max_score = score diff --git a/app/models/web/push_subscription.rb b/app/models/web/push_subscription.rb index 6e46573ae..dfaadf5cc 100644 --- a/app/models/web/push_subscription.rb +++ b/app/models/web/push_subscription.rb @@ -53,25 +53,21 @@ class Web::PushSubscription < ApplicationRecord def associated_user return @associated_user if defined?(@associated_user) - @associated_user = begin - if user_id.nil? - session_activation.user - else - user - end - end + @associated_user = if user_id.nil? + session_activation.user + else + user + end end def associated_access_token return @associated_access_token if defined?(@associated_access_token) - @associated_access_token = begin - if access_token_id.nil? - find_or_create_access_token.token - else - access_token.token - end - end + @associated_access_token = if access_token_id.nil? + find_or_create_access_token.token + else + access_token.token + end end class << self diff --git a/app/presenters/tag_relationships_presenter.rb b/app/presenters/tag_relationships_presenter.rb index c3bdbaf07..52e24314b 100644 --- a/app/presenters/tag_relationships_presenter.rb +++ b/app/presenters/tag_relationships_presenter.rb @@ -4,12 +4,10 @@ class TagRelationshipsPresenter attr_reader :following_map def initialize(tags, current_account_id = nil, **options) - @following_map = begin - if current_account_id.nil? - {} - else - TagFollow.select(:tag_id).where(tag_id: tags.map(&:id), account_id: current_account_id).each_with_object({}) { |f, h| h[f.tag_id] = true }.merge(options[:following_map] || {}) - end - end + @following_map = if current_account_id.nil? + {} + else + TagFollow.select(:tag_id).where(tag_id: tags.map(&:id), account_id: current_account_id).each_with_object({}) { |f, h| h[f.tag_id] = true }.merge(options[:following_map] || {}) + end end end diff --git a/app/services/account_search_service.rb b/app/services/account_search_service.rb index 85538870b..dfc3a45f8 100644 --- a/app/services/account_search_service.rb +++ b/app/services/account_search_service.rb @@ -32,15 +32,13 @@ class AccountSearchService < BaseService return @exact_match if defined?(@exact_match) - match = begin - if options[:resolve] - ResolveAccountService.new.call(query) - elsif domain_is_local? - Account.find_local(query_username) - else - Account.find_remote(query_username, query_domain) - end - end + match = if options[:resolve] + ResolveAccountService.new.call(query) + elsif domain_is_local? + Account.find_local(query_username) + else + Account.find_remote(query_username, query_domain) + end match = nil if !match.nil? && !account.nil? && options[:following] && !account.following?(match) diff --git a/app/services/activitypub/fetch_featured_tags_collection_service.rb b/app/services/activitypub/fetch_featured_tags_collection_service.rb index ab047a0f8..ff1a88aa1 100644 --- a/app/services/activitypub/fetch_featured_tags_collection_service.rb +++ b/app/services/activitypub/fetch_featured_tags_collection_service.rb @@ -22,14 +22,12 @@ class ActivityPub::FetchFeaturedTagsCollectionService < BaseService collection = fetch_collection(collection['first']) if collection['first'].present? while collection.is_a?(Hash) - items = begin - case collection['type'] - when 'Collection', 'CollectionPage' - collection['items'] - when 'OrderedCollection', 'OrderedCollectionPage' - collection['orderedItems'] - end - end + items = case collection['type'] + when 'Collection', 'CollectionPage' + collection['items'] + when 'OrderedCollection', 'OrderedCollectionPage' + collection['orderedItems'] + end break if items.blank? diff --git a/app/services/activitypub/fetch_remote_status_service.rb b/app/services/activitypub/fetch_remote_status_service.rb index 936737bf6..aea80f078 100644 --- a/app/services/activitypub/fetch_remote_status_service.rb +++ b/app/services/activitypub/fetch_remote_status_service.rb @@ -9,13 +9,11 @@ class ActivityPub::FetchRemoteStatusService < BaseService # Should be called when uri has already been checked for locality def call(uri, id: true, prefetched_body: nil, on_behalf_of: nil, expected_actor_uri: nil, request_id: nil) @request_id = request_id || "#{Time.now.utc.to_i}-status-#{uri}" - @json = begin - if prefetched_body.nil? - fetch_resource(uri, id, on_behalf_of) - else - body_to_json(prefetched_body, compare_id: id ? uri : nil) - end - end + @json = if prefetched_body.nil? + fetch_resource(uri, id, on_behalf_of) + else + body_to_json(prefetched_body, compare_id: id ? uri : nil) + end return unless supported_context? diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb index 4d55aa5e2..d5fa9af54 100644 --- a/app/services/fetch_link_card_service.rb +++ b/app/services/fetch_link_card_service.rb @@ -69,16 +69,14 @@ class FetchLinkCardService < BaseService end def parse_urls - urls = begin - if @status.local? - @status.text.scan(URL_PATTERN).map { |array| Addressable::URI.parse(array[1]).normalize } - else - document = Nokogiri::HTML(@status.text) - links = document.css('a') - - links.filter_map { |a| Addressable::URI.parse(a['href']) unless skip_link?(a) }.filter_map(&:normalize) - end - end + urls = if @status.local? + @status.text.scan(URL_PATTERN).map { |array| Addressable::URI.parse(array[1]).normalize } + else + document = Nokogiri::HTML(@status.text) + links = document.css('a') + + links.filter_map { |a| Addressable::URI.parse(a['href']) unless skip_link?(a) }.filter_map(&:normalize) + end urls.reject { |uri| bad_url?(uri) }.first end diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb index 93a96667e..b3b279147 100644 --- a/app/services/process_mentions_service.rb +++ b/app/services/process_mentions_service.rb @@ -28,13 +28,11 @@ class ProcessMentionsService < BaseService @status.text = @status.text.gsub(Account::MENTION_RE) do |match| username, domain = Regexp.last_match(1).split('@') - domain = begin - if TagManager.instance.local_domain?(domain) - nil - else - TagManager.instance.normalize_domain(domain) - end - end + domain = if TagManager.instance.local_domain?(domain) + nil + else + TagManager.instance.normalize_domain(domain) + end mentioned_account = Account.find_remote(username, domain) diff --git a/app/services/reblog_service.rb b/app/services/reblog_service.rb index 7d2981709..6ec094474 100644 --- a/app/services/reblog_service.rb +++ b/app/services/reblog_service.rb @@ -20,13 +20,11 @@ class ReblogService < BaseService return reblog unless reblog.nil? - visibility = begin - if reblogged_status.hidden? - reblogged_status.visibility - else - options[:visibility] || account.user&.setting_default_privacy - end - end + visibility = if reblogged_status.hidden? + reblogged_status.visibility + else + options[:visibility] || account.user&.setting_default_privacy + end reblog = account.statuses.create!(reblog: reblogged_status, text: '', visibility: visibility, rate_limit: options[:with_rate_limit]) diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb index c76df5a0e..abe1534a5 100644 --- a/app/services/resolve_account_service.rb +++ b/app/services/resolve_account_service.rb @@ -71,13 +71,11 @@ class ResolveAccountService < BaseService @username, @domain = uri.strip.gsub(/\A@/, '').split('@') end - @domain = begin - if TagManager.instance.local_domain?(@domain) - nil - else - TagManager.instance.normalize_domain(@domain) - end - end + @domain = if TagManager.instance.local_domain?(@domain) + nil + else + TagManager.instance.normalize_domain(@domain) + end @uri = [@username, @domain].compact.join('@') end diff --git a/app/validators/domain_validator.rb b/app/validators/domain_validator.rb index 6e4a854ff..3a951f9a7 100644 --- a/app/validators/domain_validator.rb +++ b/app/validators/domain_validator.rb @@ -4,13 +4,11 @@ class DomainValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) return if value.blank? - domain = begin - if options[:acct] - value.split('@').last - else - value - end - end + domain = if options[:acct] + value.split('@').last + else + value + end record.errors.add(attribute, I18n.t('domain_validator.invalid_domain')) unless compliant?(domain) end diff --git a/app/validators/existing_username_validator.rb b/app/validators/existing_username_validator.rb index 1c5596821..45de4f4a4 100644 --- a/app/validators/existing_username_validator.rb +++ b/app/validators/existing_username_validator.rb @@ -4,16 +4,14 @@ class ExistingUsernameValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) return if value.blank? - usernames_and_domains = begin - value.split(',').map do |str| - username, domain = str.strip.gsub(/\A@/, '').split('@', 2) - domain = nil if TagManager.instance.local_domain?(domain) + usernames_and_domains = value.split(',').map do |str| + username, domain = str.strip.gsub(/\A@/, '').split('@', 2) + domain = nil if TagManager.instance.local_domain?(domain) - next if username.blank? + next if username.blank? - [str, username, domain] - end.compact - end + [str, username, domain] + end.compact usernames_with_no_accounts = usernames_and_domains.filter_map do |(str, username, domain)| str unless Account.find_remote(username, domain) diff --git a/app/validators/import_validator.rb b/app/validators/import_validator.rb index cbad56df6..782baf5d6 100644 --- a/app/validators/import_validator.rb +++ b/app/validators/import_validator.rb @@ -35,13 +35,11 @@ class ImportValidator < ActiveModel::Validator def validate_following_import(import, row_count) base_limit = FollowLimitValidator.limit_for_account(import.account) - limit = begin - if import.overwrite? - base_limit - else - base_limit - import.account.following_count - end - end + limit = if import.overwrite? + base_limit + else + base_limit - import.account.following_count + end import.errors.add(:data, I18n.t('users.follow_limit_reached', limit: base_limit)) if row_count > limit end diff --git a/app/workers/backup_worker.rb b/app/workers/backup_worker.rb index 7b0b52844..df933142a 100644 --- a/app/workers/backup_worker.rb +++ b/app/workers/backup_worker.rb @@ -9,12 +9,10 @@ class BackupWorker backup_id = msg['args'].first ActiveRecord::Base.connection_pool.with_connection do - begin - backup = Backup.find(backup_id) - backup.destroy - rescue ActiveRecord::RecordNotFound - true - end + backup = Backup.find(backup_id) + backup.destroy + rescue ActiveRecord::RecordNotFound + true end end diff --git a/app/workers/post_process_media_worker.rb b/app/workers/post_process_media_worker.rb index 24201101c..996d5def9 100644 --- a/app/workers/post_process_media_worker.rb +++ b/app/workers/post_process_media_worker.rb @@ -9,13 +9,11 @@ class PostProcessMediaWorker media_attachment_id = msg['args'].first ActiveRecord::Base.connection_pool.with_connection do - begin - media_attachment = MediaAttachment.find(media_attachment_id) - media_attachment.processing = :failed - media_attachment.save - rescue ActiveRecord::RecordNotFound - true - end + media_attachment = MediaAttachment.find(media_attachment_id) + media_attachment.processing = :failed + media_attachment.save + rescue ActiveRecord::RecordNotFound + true end Sidekiq.logger.error("Processing media attachment #{media_attachment_id} failed with #{msg['error_message']}") diff --git a/app/workers/scheduler/follow_recommendations_scheduler.rb b/app/workers/scheduler/follow_recommendations_scheduler.rb index 57f78170e..04008a9d9 100644 --- a/app/workers/scheduler/follow_recommendations_scheduler.rb +++ b/app/workers/scheduler/follow_recommendations_scheduler.rb @@ -19,13 +19,11 @@ class Scheduler::FollowRecommendationsScheduler fallback_recommendations = FollowRecommendation.order(rank: :desc).limit(SET_SIZE) Trends.available_locales.each do |locale| - recommendations = begin - if AccountSummary.safe.filtered.localized(locale).exists? # We can skip the work if no accounts with that language exist - FollowRecommendation.localized(locale).order(rank: :desc).limit(SET_SIZE).map { |recommendation| [recommendation.account_id, recommendation.rank] } - else - [] - end - end + recommendations = if AccountSummary.safe.filtered.localized(locale).exists? # We can skip the work if no accounts with that language exist + FollowRecommendation.localized(locale).order(rank: :desc).limit(SET_SIZE).map { |recommendation| [recommendation.account_id, recommendation.rank] } + else + [] + end # Use language-agnostic results if there are not enough language-specific ones missing = SET_SIZE - recommendations.size diff --git a/db/migrate/20180528141303_fix_accounts_unique_index.rb b/db/migrate/20180528141303_fix_accounts_unique_index.rb index 3e33e2cac..0b39f7107 100644 --- a/db/migrate/20180528141303_fix_accounts_unique_index.rb +++ b/db/migrate/20180528141303_fix_accounts_unique_index.rb @@ -106,21 +106,17 @@ class FixAccountsUniqueIndex < ActiveRecord::Migration[5.2] # to check for (and skip past) uniqueness errors [Favourite, Follow, FollowRequest, Block, Mute].each do |klass| klass.where(account_id: duplicate_account.id).find_each do |record| - begin - record.update_attribute(:account_id, main_account.id) - rescue ActiveRecord::RecordNotUnique - next - end + record.update_attribute(:account_id, main_account.id) + rescue ActiveRecord::RecordNotUnique + next end end [Follow, FollowRequest, Block, Mute].each do |klass| klass.where(target_account_id: duplicate_account.id).find_each do |record| - begin - record.update_attribute(:target_account_id, main_account.id) - rescue ActiveRecord::RecordNotUnique - next - end + record.update_attribute(:target_account_id, main_account.id) + rescue ActiveRecord::RecordNotUnique + next end end end diff --git a/db/migrate/20180812173710_copy_status_stats.rb b/db/migrate/20180812173710_copy_status_stats.rb index 9b2971beb..45eb9501c 100644 --- a/db/migrate/20180812173710_copy_status_stats.rb +++ b/db/migrate/20180812173710_copy_status_stats.rb @@ -43,12 +43,10 @@ class CopyStatusStats < ActiveRecord::Migration[5.2] # We cannot use bulk INSERT or overarching transactions here because of possible # uniqueness violations that we need to skip over Status.unscoped.select('id, reblogs_count, favourites_count, created_at, updated_at').find_each do |status| - begin - params = [[nil, status.id], [nil, status.reblogs_count], [nil, status.favourites_count], [nil, status.created_at], [nil, status.updated_at]] - exec_insert('INSERT INTO status_stats (status_id, reblogs_count, favourites_count, created_at, updated_at) VALUES ($1, $2, $3, $4, $5)', nil, params) - rescue ActiveRecord::RecordNotUnique - next - end + params = [[nil, status.id], [nil, status.reblogs_count], [nil, status.favourites_count], [nil, status.created_at], [nil, status.updated_at]] + exec_insert('INSERT INTO status_stats (status_id, reblogs_count, favourites_count, created_at, updated_at) VALUES ($1, $2, $3, $4, $5)', nil, params) + rescue ActiveRecord::RecordNotUnique + next end end end diff --git a/db/migrate/20181116173541_copy_account_stats.rb b/db/migrate/20181116173541_copy_account_stats.rb index 20dc85195..f908575cb 100644 --- a/db/migrate/20181116173541_copy_account_stats.rb +++ b/db/migrate/20181116173541_copy_account_stats.rb @@ -43,12 +43,10 @@ class CopyAccountStats < ActiveRecord::Migration[5.2] # We cannot use bulk INSERT or overarching transactions here because of possible # uniqueness violations that we need to skip over Account.unscoped.select('id, statuses_count, following_count, followers_count, created_at, updated_at').find_each do |account| - begin - params = [[nil, account.id], [nil, account[:statuses_count]], [nil, account[:following_count]], [nil, account[:followers_count]], [nil, account.created_at], [nil, account.updated_at]] - exec_insert('INSERT INTO account_stats (account_id, statuses_count, following_count, followers_count, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6)', nil, params) - rescue ActiveRecord::RecordNotUnique - next - end + params = [[nil, account.id], [nil, account[:statuses_count]], [nil, account[:following_count]], [nil, account[:followers_count]], [nil, account.created_at], [nil, account.updated_at]] + exec_insert('INSERT INTO account_stats (account_id, statuses_count, following_count, followers_count, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6)', nil, params) + rescue ActiveRecord::RecordNotUnique + next end end end diff --git a/lib/mastodon/accounts_cli.rb b/lib/mastodon/accounts_cli.rb index 34afbc699..db379eb85 100644 --- a/lib/mastodon/accounts_cli.rb +++ b/lib/mastodon/accounts_cli.rb @@ -490,14 +490,12 @@ module Mastodon scope = Account.where(id: ::Follow.where(account: account).select(:target_account_id)) scope.find_each do |target_account| - begin - UnfollowService.new.call(account, target_account) - rescue => e - progress.log pastel.red("Error processing #{target_account.id}: #{e}") - ensure - progress.increment - processed += 1 - end + UnfollowService.new.call(account, target_account) + rescue => e + progress.log pastel.red("Error processing #{target_account.id}: #{e}") + ensure + progress.increment + processed += 1 end BootstrapTimelineWorker.perform_async(account.id) @@ -507,14 +505,12 @@ module Mastodon scope = Account.where(id: ::Follow.where(target_account: account).select(:account_id)) scope.find_each do |target_account| - begin - UnfollowService.new.call(target_account, account) - rescue => e - progress.log pastel.red("Error processing #{target_account.id}: #{e}") - ensure - progress.increment - processed += 1 - end + UnfollowService.new.call(target_account, account) + rescue => e + progress.log pastel.red("Error processing #{target_account.id}: #{e}") + ensure + progress.increment + processed += 1 end end diff --git a/lib/mastodon/cli_helper.rb b/lib/mastodon/cli_helper.rb index a78a28e27..8704edd75 100644 --- a/lib/mastodon/cli_helper.rb +++ b/lib/mastodon/cli_helper.rb @@ -42,30 +42,28 @@ module Mastodon items.each do |item| futures << Concurrent::Future.execute(executor: pool) do - begin - if !progress.total.nil? && progress.progress + 1 > progress.total - # The number of items has changed between start and now, - # since there is no good way to predict the final count from - # here, just change the progress bar to an indeterminate one - - progress.total = nil - end - - progress.log("Processing #{item.id}") if options[:verbose] - - result = ActiveRecord::Base.connection_pool.with_connection do - yield(item) - ensure - RedisConfiguration.pool.checkin if Thread.current[:redis] - Thread.current[:redis] = nil - end - - aggregate.increment(result) if result.is_a?(Integer) - rescue => e - progress.log pastel.red("Error processing #{item.id}: #{e}") + if !progress.total.nil? && progress.progress + 1 > progress.total + # The number of items has changed between start and now, + # since there is no good way to predict the final count from + # here, just change the progress bar to an indeterminate one + + progress.total = nil + end + + progress.log("Processing #{item.id}") if options[:verbose] + + result = ActiveRecord::Base.connection_pool.with_connection do + yield(item) ensure - progress.increment + RedisConfiguration.pool.checkin if Thread.current[:redis] + Thread.current[:redis] = nil end + + aggregate.increment(result) if result.is_a?(Integer) + rescue => e + progress.log pastel.red("Error processing #{item.id}: #{e}") + ensure + progress.increment end end diff --git a/lib/mastodon/ip_blocks_cli.rb b/lib/mastodon/ip_blocks_cli.rb index 5c38c1aca..08939c092 100644 --- a/lib/mastodon/ip_blocks_cli.rb +++ b/lib/mastodon/ip_blocks_cli.rb @@ -79,13 +79,11 @@ module Mastodon skipped = 0 addresses.each do |address| - ip_blocks = begin - if options[:force] - IpBlock.where('ip >>= ?', address) - else - IpBlock.where('ip <<= ?', address) - end - end + ip_blocks = if options[:force] + IpBlock.where('ip >>= ?', address) + else + IpBlock.where('ip <<= ?', address) + end if ip_blocks.empty? say("#{address} is not yet blocked", :yellow) diff --git a/lib/mastodon/maintenance_cli.rb b/lib/mastodon/maintenance_cli.rb index a86a4f2f6..bb3802f56 100644 --- a/lib/mastodon/maintenance_cli.rb +++ b/lib/mastodon/maintenance_cli.rb @@ -98,11 +98,9 @@ module Mastodon owned_classes.each do |klass| klass.where(account_id: other_account.id).find_each do |record| - begin - record.update_attribute(:account_id, id) - rescue ActiveRecord::RecordNotUnique - next - end + record.update_attribute(:account_id, id) + rescue ActiveRecord::RecordNotUnique + next end end @@ -111,11 +109,9 @@ module Mastodon target_classes.each do |klass| klass.where(target_account_id: other_account.id).find_each do |record| - begin - record.update_attribute(:target_account_id, id) - rescue ActiveRecord::RecordNotUnique - next - end + record.update_attribute(:target_account_id, id) + rescue ActiveRecord::RecordNotUnique + next end end @@ -601,11 +597,9 @@ module Mastodon owned_classes = [ConversationMute, AccountConversation] owned_classes.each do |klass| klass.where(conversation_id: duplicate_conv.id).find_each do |record| - begin - record.update_attribute(:account_id, main_conv.id) - rescue ActiveRecord::RecordNotUnique - next - end + record.update_attribute(:account_id, main_conv.id) + rescue ActiveRecord::RecordNotUnique + next end end end @@ -629,47 +623,37 @@ module Mastodon owned_classes << Bookmark if ActiveRecord::Base.connection.table_exists?(:bookmarks) owned_classes.each do |klass| klass.where(status_id: duplicate_status.id).find_each do |record| - begin - record.update_attribute(:status_id, main_status.id) - rescue ActiveRecord::RecordNotUnique - next - end - end - end - - StatusPin.where(account_id: main_status.account_id, status_id: duplicate_status.id).find_each do |record| - begin record.update_attribute(:status_id, main_status.id) rescue ActiveRecord::RecordNotUnique next end end + StatusPin.where(account_id: main_status.account_id, status_id: duplicate_status.id).find_each do |record| + record.update_attribute(:status_id, main_status.id) + rescue ActiveRecord::RecordNotUnique + next + end + Status.where(in_reply_to_id: duplicate_status.id).find_each do |record| - begin - record.update_attribute(:in_reply_to_id, main_status.id) - rescue ActiveRecord::RecordNotUnique - next - end + record.update_attribute(:in_reply_to_id, main_status.id) + rescue ActiveRecord::RecordNotUnique + next end Status.where(reblog_of_id: duplicate_status.id).find_each do |record| - begin - record.update_attribute(:reblog_of_id, main_status.id) - rescue ActiveRecord::RecordNotUnique - next - end + record.update_attribute(:reblog_of_id, main_status.id) + rescue ActiveRecord::RecordNotUnique + next end end def merge_tags!(main_tag, duplicate_tag) [FeaturedTag].each do |klass| klass.where(tag_id: duplicate_tag.id).find_each do |record| - begin - record.update_attribute(:tag_id, main_tag.id) - rescue ActiveRecord::RecordNotUnique - next - end + record.update_attribute(:tag_id, main_tag.id) + rescue ActiveRecord::RecordNotUnique + next end end end diff --git a/lib/mastodon/media_cli.rb b/lib/mastodon/media_cli.rb index a901a6ab9..fc70c8785 100644 --- a/lib/mastodon/media_cli.rb +++ b/lib/mastodon/media_cli.rb @@ -116,13 +116,11 @@ module Mastodon loop do objects = begin - begin - bucket.objects(start_after: last_key, prefix: prefix).limit(1000).map { |x| x } - rescue => e - progress.log(pastel.red("Error fetching list of files: #{e}")) - progress.log("If you want to continue from this point, add --start-after=#{last_key} to your command") if last_key - break - end + bucket.objects(start_after: last_key, prefix: prefix).limit(1000).map { |x| x } + rescue => e + progress.log(pastel.red("Error fetching list of files: #{e}")) + progress.log("If you want to continue from this point, add --start-after=#{last_key} to your command") if last_key + break end break if objects.empty? diff --git a/lib/mastodon/search_cli.rb b/lib/mastodon/search_cli.rb index b206854ab..31e9a3d5a 100644 --- a/lib/mastodon/search_cli.rb +++ b/lib/mastodon/search_cli.rb @@ -43,13 +43,11 @@ module Mastodon exit(1) end - indices = begin - if options[:only] - options[:only].map { |str| "#{str.camelize}Index".constantize } - else - INDICES - end - end + indices = if options[:only] + options[:only].map { |str| "#{str.camelize}Index".constantize } + else + INDICES + end pool = Concurrent::FixedThreadPool.new(options[:concurrency], max_queue: options[:concurrency] * 10) importers = indices.index_with { |index| "Importer::#{index.name}Importer".constantize.new(batch_size: options[:batch_size], executor: pool) } diff --git a/lib/mastodon/upgrade_cli.rb b/lib/mastodon/upgrade_cli.rb index 570b7e6fa..2b60f9eee 100644 --- a/lib/mastodon/upgrade_cli.rb +++ b/lib/mastodon/upgrade_cli.rb @@ -50,16 +50,14 @@ module Mastodon styles << :original unless styles.include?(:original) styles.each do |style| - success = begin - case Paperclip::Attachment.default_options[:storage] - when :s3 - upgrade_storage_s3(progress, attachment, style) - when :fog - upgrade_storage_fog(progress, attachment, style) - when :filesystem - upgrade_storage_filesystem(progress, attachment, style) - end - end + success = case Paperclip::Attachment.default_options[:storage] + when :s3 + upgrade_storage_s3(progress, attachment, style) + when :fog + upgrade_storage_fog(progress, attachment, style) + when :filesystem + upgrade_storage_filesystem(progress, attachment, style) + end upgraded = true if style == :original && success diff --git a/lib/paperclip/color_extractor.rb b/lib/paperclip/color_extractor.rb index d8a042c90..733dcba80 100644 --- a/lib/paperclip/color_extractor.rb +++ b/lib/paperclip/color_extractor.rb @@ -161,13 +161,11 @@ module Paperclip def lighten_or_darken(color, by) hue, saturation, light = rgb_to_hsl(color.r, color.g, color.b) - light = begin - if light < 50 - [100, light + by].min - else - [0, light - by].max - end - end + light = if light < 50 + [100, light + by].min + else + [0, light - by].max + end ColorDiff::Color::RGB.new(*hsl_to_rgb(hue, saturation, light)) end diff --git a/lib/sanitize_ext/sanitize_config.rb b/lib/sanitize_ext/sanitize_config.rb index baf652662..d5e62897f 100644 --- a/lib/sanitize_ext/sanitize_config.rb +++ b/lib/sanitize_ext/sanitize_config.rb @@ -41,13 +41,11 @@ class Sanitize current_node = env[:node] - scheme = begin - if current_node['href'] =~ Sanitize::REGEX_PROTOCOL - Regexp.last_match(1).downcase - else - :relative - end - end + scheme = if current_node['href'] =~ Sanitize::REGEX_PROTOCOL + Regexp.last_match(1).downcase + else + :relative + end current_node.replace(Nokogiri::XML::Text.new(current_node.text, current_node.document)) unless LINK_PROTOCOLS.include?(scheme) end diff --git a/lib/tasks/db.rake b/lib/tasks/db.rake index ca939fd1f..e8a64b8fb 100644 --- a/lib/tasks/db.rake +++ b/lib/tasks/db.rake @@ -4,16 +4,14 @@ namespace :db do namespace :migrate do desc 'Setup the db or migrate depending on state of db' task setup: :environment do - begin - if ActiveRecord::Migrator.current_version.zero? - Rake::Task['db:migrate'].invoke - Rake::Task['db:seed'].invoke - end - rescue ActiveRecord::NoDatabaseError - Rake::Task['db:setup'].invoke - else + if ActiveRecord::Migrator.current_version.zero? Rake::Task['db:migrate'].invoke + Rake::Task['db:seed'].invoke end + rescue ActiveRecord::NoDatabaseError + Rake::Task['db:setup'].invoke + else + Rake::Task['db:migrate'].invoke end end -- cgit From 597767a9f7ca846be9fbca826aba362f8387a60f Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Sun, 19 Feb 2023 20:19:40 -0500 Subject: Autofix Rubocop Rails/RedundantForeignKey (#23731) --- .rubocop_todo.yml | 12 ------------ app/models/custom_filter.rb | 4 ++-- app/models/follow_recommendation.rb | 2 +- app/models/report.rb | 2 +- app/models/status.rb | 2 +- app/models/user_ip.rb | 2 +- db/post_migrate/20221101190723_backfill_admin_action_logs.rb | 2 +- .../20221206114142_backfill_admin_action_logs_again.rb | 2 +- 8 files changed, 8 insertions(+), 20 deletions(-) (limited to 'app/models') diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 6fb471600..1a524e6fd 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -2459,18 +2459,6 @@ Rails/RakeEnvironment: - 'lib/tasks/repo.rake' - 'lib/tasks/statistics.rake' -# Offense count: 8 -# This cop supports safe autocorrection (--autocorrect). -Rails/RedundantForeignKey: - Exclude: - - 'app/models/custom_filter.rb' - - 'app/models/follow_recommendation.rb' - - 'app/models/report.rb' - - 'app/models/status.rb' - - 'app/models/user_ip.rb' - - 'db/post_migrate/20221101190723_backfill_admin_action_logs.rb' - - 'db/post_migrate/20221206114142_backfill_admin_action_logs_again.rb' - # Offense count: 29 # Configuration parameters: Include. # Include: db/**/*.rb diff --git a/app/models/custom_filter.rb b/app/models/custom_filter.rb index 5a4a974be..b70e53bd5 100644 --- a/app/models/custom_filter.rb +++ b/app/models/custom_filter.rb @@ -33,8 +33,8 @@ class CustomFilter < ApplicationRecord enum action: [:warn, :hide], _suffix: :action belongs_to :account - has_many :keywords, class_name: 'CustomFilterKeyword', foreign_key: :custom_filter_id, inverse_of: :custom_filter, dependent: :destroy - has_many :statuses, class_name: 'CustomFilterStatus', foreign_key: :custom_filter_id, inverse_of: :custom_filter, dependent: :destroy + has_many :keywords, class_name: 'CustomFilterKeyword', inverse_of: :custom_filter, dependent: :destroy + has_many :statuses, class_name: 'CustomFilterStatus', inverse_of: :custom_filter, dependent: :destroy accepts_nested_attributes_for :keywords, reject_if: :all_blank, allow_destroy: true validates :title, :context, presence: true diff --git a/app/models/follow_recommendation.rb b/app/models/follow_recommendation.rb index e552b5a88..501f8ecb6 100644 --- a/app/models/follow_recommendation.rb +++ b/app/models/follow_recommendation.rb @@ -12,7 +12,7 @@ class FollowRecommendation < ApplicationRecord self.primary_key = :account_id belongs_to :account_summary, foreign_key: :account_id - belongs_to :account, foreign_key: :account_id + belongs_to :account scope :localized, ->(locale) { joins(:account_summary).merge(AccountSummary.localized(locale)) } diff --git a/app/models/report.rb b/app/models/report.rb index 525d22ad5..fe6c292c5 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -32,7 +32,7 @@ class Report < ApplicationRecord belongs_to :action_taken_by_account, class_name: 'Account', optional: true belongs_to :assigned_account, class_name: 'Account', optional: true - has_many :notes, class_name: 'ReportNote', foreign_key: :report_id, inverse_of: :report, dependent: :destroy + has_many :notes, class_name: 'ReportNote', inverse_of: :report, dependent: :destroy has_many :notifications, as: :activity, dependent: :destroy scope :unresolved, -> { where(action_taken_at: nil) } diff --git a/app/models/status.rb b/app/models/status.rb index 102dfa994..e0ad29103 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -53,7 +53,7 @@ class Status < ApplicationRecord belongs_to :application, class_name: 'Doorkeeper::Application', optional: true belongs_to :account, inverse_of: :statuses - belongs_to :in_reply_to_account, foreign_key: 'in_reply_to_account_id', class_name: 'Account', optional: true + belongs_to :in_reply_to_account, class_name: 'Account', optional: true belongs_to :conversation, optional: true belongs_to :preloadable_poll, class_name: 'Poll', foreign_key: 'poll_id', optional: true diff --git a/app/models/user_ip.rb b/app/models/user_ip.rb index a8e802e13..1da615762 100644 --- a/app/models/user_ip.rb +++ b/app/models/user_ip.rb @@ -11,7 +11,7 @@ class UserIp < ApplicationRecord self.primary_key = :user_id - belongs_to :user, foreign_key: :user_id + belongs_to :user def readonly? true diff --git a/db/post_migrate/20221101190723_backfill_admin_action_logs.rb b/db/post_migrate/20221101190723_backfill_admin_action_logs.rb index 48ef1e6e3..6ab76a8f7 100644 --- a/db/post_migrate/20221101190723_backfill_admin_action_logs.rb +++ b/db/post_migrate/20221101190723_backfill_admin_action_logs.rb @@ -62,7 +62,7 @@ class BackfillAdminActionLogs < ActiveRecord::Migration[6.1] # Cannot use usual polymorphic support because of namespacing issues belongs_to :status, foreign_key: :target_id belongs_to :account, foreign_key: :target_id - belongs_to :user, foreign_key: :user_id + belongs_to :user belongs_to :domain_block, foreign_key: :target_id belongs_to :domain_allow, foreign_key: :target_id belongs_to :email_domain_block, foreign_key: :target_id diff --git a/db/post_migrate/20221206114142_backfill_admin_action_logs_again.rb b/db/post_migrate/20221206114142_backfill_admin_action_logs_again.rb index 279053ab9..42b7f3625 100644 --- a/db/post_migrate/20221206114142_backfill_admin_action_logs_again.rb +++ b/db/post_migrate/20221206114142_backfill_admin_action_logs_again.rb @@ -62,7 +62,7 @@ class BackfillAdminActionLogsAgain < ActiveRecord::Migration[6.1] # Cannot use usual polymorphic support because of namespacing issues belongs_to :status, foreign_key: :target_id belongs_to :account, foreign_key: :target_id - belongs_to :user, foreign_key: :user_id + belongs_to :user belongs_to :domain_block, foreign_key: :target_id belongs_to :domain_allow, foreign_key: :target_id belongs_to :email_domain_block, foreign_key: :target_id -- cgit From 63e63538861bd850a38a282e37de046639afa993 Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Sun, 19 Feb 2023 23:00:36 -0500 Subject: Autofix Rubocop Rails/EnumHash (#23737) --- .rubocop_todo.yml | 16 ---------------- app/models/account.rb | 4 ++-- app/models/custom_filter.rb | 2 +- app/models/domain_block.rb | 2 +- app/models/import.rb | 2 +- app/models/list.rb | 2 +- app/models/media_attachment.rb | 4 ++-- app/models/preview_card.rb | 4 ++-- app/models/relay.rb | 2 +- app/models/status.rb | 2 +- 10 files changed, 12 insertions(+), 28 deletions(-) (limited to 'app/models') diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index c452d1bd2..7cb4d55e0 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1871,22 +1871,6 @@ Rails/DuplicateAssociation: - 'app/serializers/activitypub/collection_serializer.rb' - 'app/serializers/activitypub/note_serializer.rb' -# Offense count: 12 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: Include. -# Include: app/models/**/*.rb -Rails/EnumHash: - Exclude: - - 'app/models/account.rb' - - 'app/models/custom_filter.rb' - - 'app/models/domain_block.rb' - - 'app/models/import.rb' - - 'app/models/list.rb' - - 'app/models/media_attachment.rb' - - 'app/models/preview_card.rb' - - 'app/models/relay.rb' - - 'app/models/status.rb' - # Offense count: 76 # Configuration parameters: EnforcedStyle. # SupportedStyles: slashes, arguments diff --git a/app/models/account.rb b/app/models/account.rb index 2c0cd577e..d33110d55 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -78,8 +78,8 @@ class Account < ApplicationRecord include DomainMaterializable include AccountMerging - enum protocol: [:ostatus, :activitypub] - enum suspension_origin: [:local, :remote], _prefix: true + enum protocol: { ostatus: 0, activitypub: 1 } + enum suspension_origin: { local: 0, remote: 1 }, _prefix: true validates :username, presence: true validates_with UniqueUsernameValidator, if: -> { will_save_change_to_username? } diff --git a/app/models/custom_filter.rb b/app/models/custom_filter.rb index b70e53bd5..781bf4db8 100644 --- a/app/models/custom_filter.rb +++ b/app/models/custom_filter.rb @@ -30,7 +30,7 @@ class CustomFilter < ApplicationRecord include Expireable include Redisable - enum action: [:warn, :hide], _suffix: :action + enum action: { warn: 0, hide: 1 }, _suffix: :action belongs_to :account has_many :keywords, class_name: 'CustomFilterKeyword', inverse_of: :custom_filter, dependent: :destroy diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb index 8e298ac9d..190f5ba2e 100644 --- a/app/models/domain_block.rb +++ b/app/models/domain_block.rb @@ -20,7 +20,7 @@ class DomainBlock < ApplicationRecord include DomainNormalizable include DomainMaterializable - enum severity: [:silence, :suspend, :noop] + enum severity: { silence: 0, suspend: 1, noop: 2 } validates :domain, presence: true, uniqueness: true, domain: true diff --git a/app/models/import.rb b/app/models/import.rb index 00a54892e..cd33eb07b 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -24,7 +24,7 @@ class Import < ApplicationRecord belongs_to :account - enum type: [:following, :blocking, :muting, :domain_blocking, :bookmarks] + enum type: { following: 0, blocking: 1, muting: 2, domain_blocking: 3, bookmarks: 4 } validates :type, presence: true validates_with ImportValidator, on: :create diff --git a/app/models/list.rb b/app/models/list.rb index cdc6ebdb3..7b8cf6636 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -16,7 +16,7 @@ class List < ApplicationRecord PER_ACCOUNT_LIMIT = 50 - enum replies_policy: [:list, :followed, :none], _prefix: :show + enum replies_policy: { list: 0, followed: 1, none: 2 }, _prefix: :show belongs_to :account, optional: true diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index 5916b0b4b..c6f2352e0 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -33,8 +33,8 @@ class MediaAttachment < ApplicationRecord include Attachmentable - enum type: [:image, :gifv, :video, :unknown, :audio] - enum processing: [:queued, :in_progress, :complete, :failed], _prefix: true + enum type: { :image => 0, :gifv => 1, :video => 2, :unknown => 3, :audio => 4 } + enum processing: { :queued => 0, :in_progress => 1, :complete => 2, :failed => 3 }, _prefix: true MAX_DESCRIPTION_LENGTH = 1_500 diff --git a/app/models/preview_card.rb b/app/models/preview_card.rb index 56ca62d5e..d25fe6dad 100644 --- a/app/models/preview_card.rb +++ b/app/models/preview_card.rb @@ -44,8 +44,8 @@ class PreviewCard < ApplicationRecord self.inheritance_column = false - enum type: [:link, :photo, :video, :rich] - enum link_type: [:unknown, :article] + enum type: { link: 0, photo: 1, video: 2, rich: 3 } + enum link_type: { unknown: 0, article: 1 } has_and_belongs_to_many :statuses has_one :trend, class_name: 'PreviewCardTrend', inverse_of: :preview_card, dependent: :destroy diff --git a/app/models/relay.rb b/app/models/relay.rb index c66bfe4ff..e9c425743 100644 --- a/app/models/relay.rb +++ b/app/models/relay.rb @@ -14,7 +14,7 @@ class Relay < ApplicationRecord validates :inbox_url, presence: true, uniqueness: true, url: true, if: :will_save_change_to_inbox_url? - enum state: [:idle, :pending, :accepted, :rejected] + enum state: { idle: 0, pending: 1, accepted: 2, rejected: 3 } scope :enabled, -> { accepted } diff --git a/app/models/status.rb b/app/models/status.rb index e0ad29103..44a297a08 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -48,7 +48,7 @@ class Status < ApplicationRecord update_index('statuses', :proper) - enum visibility: [:public, :unlisted, :private, :direct, :limited], _suffix: :visibility + enum visibility: { public: 0, unlisted: 1, private: 2, direct: 3, limited: 4 }, _suffix: :visibility belongs_to :application, class_name: 'Doorkeeper::Application', optional: true -- cgit From d2dcb6c45a9db5439772f0553046e2c03a739a16 Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Mon, 20 Feb 2023 00:51:43 -0500 Subject: Autofix Rubocop Style/UnpackFirst (#23741) --- .rubocop_todo.yml | 7 ------- app/models/concerns/account_interactions.rb | 4 ++-- lib/paperclip/gif_transcoder.rb | 4 ++-- 3 files changed, 4 insertions(+), 11 deletions(-) (limited to 'app/models') diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 86a48a170..0f98d25d6 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -2617,10 +2617,3 @@ Style/SymbolArray: Style/SymbolProc: Exclude: - 'spec/lib/request_spec.rb' - -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -Style/UnpackFirst: - Exclude: - - 'app/models/concerns/account_interactions.rb' - - 'lib/paperclip/gif_transcoder.rb' diff --git a/app/models/concerns/account_interactions.rb b/app/models/concerns/account_interactions.rb index 325619774..1898516b0 100644 --- a/app/models/concerns/account_interactions.rb +++ b/app/models/concerns/account_interactions.rb @@ -278,7 +278,7 @@ module AccountInteractions followers.where(Account.arel_table[:uri].matches("#{Account.sanitize_sql_like(url_prefix)}/%", false, true)).or(followers.where(uri: url_prefix)).pluck_each(:uri) do |uri| Xorcist.xor!(digest, Digest::SHA256.digest(uri)) end - digest.unpack('H*')[0] + digest.unpack1('H*') end end @@ -288,7 +288,7 @@ module AccountInteractions followers.where(domain: nil).pluck_each(:username) do |username| Xorcist.xor!(digest, Digest::SHA256.digest(ActivityPub::TagManager.instance.uri_for_username(username))) end - digest.unpack('H*')[0] + digest.unpack1('H*') end end diff --git a/lib/paperclip/gif_transcoder.rb b/lib/paperclip/gif_transcoder.rb index d14465c01..f385b00a3 100644 --- a/lib/paperclip/gif_transcoder.rb +++ b/lib/paperclip/gif_transcoder.rb @@ -57,7 +57,7 @@ class GifReader end # Skip lzw min code size - raise InvalidValue unless s.read(1).unpack('C')[0] >= 2 + raise InvalidValue unless s.read(1).unpack1('C') >= 2 # Skip image data sub-blocks skip_sub_blocks!(s) @@ -77,7 +77,7 @@ class GifReader private def skip_extension_block!(file) - if EXTENSION_LABELS.include?(file.read(1).unpack('C')[0]) + if EXTENSION_LABELS.include?(file.read(1).unpack1('C')) block_size, = file.read(1).unpack('C') file.seek(block_size, IO::SEEK_CUR) end -- cgit From 717683d1c39d2fe85d1cc3f5223e1f4cf43f1900 Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Mon, 20 Feb 2023 00:58:28 -0500 Subject: Autofix Rubocop remaining Layout rules (#23679) --- .rubocop_todo.yml | 148 --------------------- Capfile | 1 + app/controllers/api/v1/tags_controller.rb | 1 + app/controllers/application_controller.rb | 1 + .../concerns/session_tracking_concern.rb | 1 + app/controllers/concerns/signature_verification.rb | 1 + app/helpers/application_helper.rb | 1 + app/helpers/languages_helper.rb | 1 + app/lib/activitypub/activity.rb | 1 + app/lib/activitypub/linked_data_signature.rb | 2 +- app/lib/activitypub/tag_manager.rb | 2 + app/lib/ostatus/tag_manager.rb | 32 ++--- app/lib/request.rb | 1 + app/lib/settings/scoped_settings.rb | 2 + app/lib/status_filter.rb | 1 + app/lib/tag_manager.rb | 1 + app/lib/webfinger.rb | 1 + app/models/account.rb | 2 + app/models/account/field.rb | 4 +- app/models/account_conversation.rb | 2 + app/models/account_domain_block.rb | 1 + app/models/account_moderation_note.rb | 1 + app/models/account_note.rb | 1 + app/models/account_pin.rb | 1 + app/models/account_stat.rb | 1 + app/models/account_summary.rb | 1 + app/models/account_warning.rb | 13 +- app/models/admin/import.rb | 1 + app/models/backup.rb | 1 + app/models/block.rb | 1 + app/models/bookmark.rb | 1 + app/models/canonical_email_block.rb | 1 + app/models/conversation.rb | 1 + app/models/conversation_mute.rb | 1 + app/models/custom_emoji.rb | 1 + app/models/custom_filter.rb | 3 + app/models/custom_filter_keyword.rb | 1 + app/models/custom_filter_status.rb | 1 + app/models/device.rb | 1 + app/models/domain_block.rb | 1 + app/models/email_domain_block.rb | 1 + app/models/encrypted_message.rb | 1 + app/models/favourite.rb | 2 + app/models/featured_tag.rb | 1 + app/models/follow.rb | 1 + app/models/follow_recommendation.rb | 1 + app/models/follow_recommendation_suppression.rb | 1 + app/models/follow_request.rb | 1 + app/models/form/admin_settings.rb | 1 + app/models/identity.rb | 1 + app/models/import.rb | 1 + app/models/instance.rb | 1 + app/models/invite.rb | 1 + app/models/ip_block.rb | 1 + app/models/list.rb | 1 + app/models/list_account.rb | 1 + app/models/login_activity.rb | 1 + app/models/media_attachment.rb | 3 +- app/models/mention.rb | 1 + app/models/mute.rb | 1 + app/models/notification.rb | 11 +- app/models/one_time_key.rb | 1 + app/models/poll.rb | 8 +- app/models/poll_vote.rb | 1 + app/models/preview_card.rb | 1 + app/models/preview_card_provider.rb | 1 + app/models/relay.rb | 1 + app/models/report.rb | 1 + app/models/report_note.rb | 1 + app/models/session_activation.rb | 2 + app/models/setting.rb | 4 + app/models/site_upload.rb | 1 + app/models/status.rb | 1 + app/models/status_edit.rb | 2 + app/models/status_pin.rb | 1 + app/models/status_stat.rb | 1 + app/models/tag.rb | 1 + app/models/unavailable_domain.rb | 1 + app/models/user.rb | 4 + app/models/user_ip.rb | 1 + app/models/user_role.rb | 2 + app/models/web/push_subscription.rb | 1 + app/models/web/setting.rb | 1 + app/models/webauthn_credential.rb | 1 + app/presenters/account_relationships_presenter.rb | 18 +-- .../activitypub/fetch_remote_actor_service.rb | 1 + .../activitypub/fetch_remote_status_service.rb | 1 + app/services/activitypub/fetch_replies_service.rb | 1 + .../activitypub/process_account_service.rb | 2 + app/services/favourite_service.rb | 1 + app/services/keys/claim_service.rb | 6 +- app/services/keys/query_service.rb | 6 +- app/services/notify_service.rb | 1 + app/services/post_status_service.rb | 3 + app/services/vote_service.rb | 2 + app/validators/follow_limit_validator.rb | 1 + app/validators/unreserved_username_validator.rb | 2 + .../accounts_statuses_cleanup_scheduler.rb | 2 + app/workers/web/push_notification_worker.rb | 12 +- config.ru | 1 + ...314181829_migrate_open_registrations_setting.rb | 2 + ...43559_preserve_old_layout_for_existing_users.rb | 1 + ...431_add_case_insensitive_btree_index_to_tags.rb | 1 + .../20220613110834_add_action_to_custom_filters.rb | 1 + .../20200917193528_migrate_notifications_type.rb | 10 +- ...110802_remove_whole_word_from_custom_filters.rb | 1 + ...0903_remove_irreversible_from_custom_filters.rb | 1 + .../20221101190723_backfill_admin_action_logs.rb | 13 ++ ...21206114142_backfill_admin_action_logs_again.rb | 13 ++ lib/mastodon/domains_cli.rb | 2 + lib/sanitize_ext/sanitize_config.rb | 12 +- lib/tasks/auto_annotate_models.rake | 70 +++++----- lib/tasks/mastodon.rake | 16 +-- .../api/v1/accounts/statuses_controller_spec.rb | 1 + spec/models/admin/account_action_spec.rb | 4 +- spec/models/concerns/account_interactions_spec.rb | 4 +- spec/models/tag_spec.rb | 1 + 117 files changed, 265 insertions(+), 261 deletions(-) (limited to 'app/models') diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 0f98d25d6..e667a7786 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -14,154 +14,6 @@ Bundler/OrderedGems: Exclude: - 'Gemfile' -# Offense count: 81 -# This cop supports safe autocorrection (--autocorrect). -Layout/EmptyLineAfterGuardClause: - Exclude: - - 'app/controllers/api/v1/tags_controller.rb' - - 'app/controllers/application_controller.rb' - - 'app/controllers/concerns/session_tracking_concern.rb' - - 'app/controllers/concerns/signature_verification.rb' - - 'app/helpers/application_helper.rb' - - 'app/lib/activitypub/activity.rb' - - 'app/lib/activitypub/tag_manager.rb' - - 'app/lib/request.rb' - - 'app/lib/settings/scoped_settings.rb' - - 'app/lib/status_filter.rb' - - 'app/lib/tag_manager.rb' - - 'app/lib/webfinger.rb' - - 'app/models/account.rb' - - 'app/models/account_conversation.rb' - - 'app/models/admin/import.rb' - - 'app/models/custom_filter.rb' - - 'app/models/favourite.rb' - - 'app/models/form/admin_settings.rb' - - 'app/models/poll.rb' - - 'app/models/session_activation.rb' - - 'app/models/setting.rb' - - 'app/models/status_edit.rb' - - 'app/models/user.rb' - - 'app/models/user_role.rb' - - 'app/services/activitypub/fetch_remote_actor_service.rb' - - 'app/services/activitypub/fetch_remote_status_service.rb' - - 'app/services/activitypub/fetch_replies_service.rb' - - 'app/services/activitypub/process_account_service.rb' - - 'app/services/favourite_service.rb' - - 'app/services/notify_service.rb' - - 'app/services/post_status_service.rb' - - 'app/services/vote_service.rb' - - 'app/validators/follow_limit_validator.rb' - - 'app/validators/unreserved_username_validator.rb' - - 'app/workers/scheduler/accounts_statuses_cleanup_scheduler.rb' - - 'db/migrate/20190314181829_migrate_open_registrations_setting.rb' - - 'db/migrate/20190529143559_preserve_old_layout_for_existing_users.rb' - - 'db/migrate/20210421121431_add_case_insensitive_btree_index_to_tags.rb' - - 'db/post_migrate/20221101190723_backfill_admin_action_logs.rb' - - 'db/post_migrate/20221206114142_backfill_admin_action_logs_again.rb' - - 'lib/mastodon/domains_cli.rb' - -# Offense count: 71 -# This cop supports safe autocorrection (--autocorrect). -Layout/EmptyLineAfterMagicComment: - Exclude: - - 'Capfile' - - 'app/helpers/languages_helper.rb' - - 'app/models/account.rb' - - 'app/models/account_conversation.rb' - - 'app/models/account_domain_block.rb' - - 'app/models/account_moderation_note.rb' - - 'app/models/account_note.rb' - - 'app/models/account_pin.rb' - - 'app/models/account_stat.rb' - - 'app/models/account_summary.rb' - - 'app/models/account_warning.rb' - - 'app/models/backup.rb' - - 'app/models/block.rb' - - 'app/models/bookmark.rb' - - 'app/models/canonical_email_block.rb' - - 'app/models/conversation.rb' - - 'app/models/conversation_mute.rb' - - 'app/models/custom_emoji.rb' - - 'app/models/custom_filter.rb' - - 'app/models/custom_filter_keyword.rb' - - 'app/models/custom_filter_status.rb' - - 'app/models/device.rb' - - 'app/models/domain_block.rb' - - 'app/models/email_domain_block.rb' - - 'app/models/encrypted_message.rb' - - 'app/models/favourite.rb' - - 'app/models/featured_tag.rb' - - 'app/models/follow.rb' - - 'app/models/follow_recommendation.rb' - - 'app/models/follow_recommendation_suppression.rb' - - 'app/models/follow_request.rb' - - 'app/models/identity.rb' - - 'app/models/import.rb' - - 'app/models/instance.rb' - - 'app/models/invite.rb' - - 'app/models/ip_block.rb' - - 'app/models/list.rb' - - 'app/models/list_account.rb' - - 'app/models/login_activity.rb' - - 'app/models/media_attachment.rb' - - 'app/models/mention.rb' - - 'app/models/mute.rb' - - 'app/models/notification.rb' - - 'app/models/one_time_key.rb' - - 'app/models/poll.rb' - - 'app/models/poll_vote.rb' - - 'app/models/preview_card.rb' - - 'app/models/preview_card_provider.rb' - - 'app/models/relay.rb' - - 'app/models/report.rb' - - 'app/models/report_note.rb' - - 'app/models/session_activation.rb' - - 'app/models/setting.rb' - - 'app/models/site_upload.rb' - - 'app/models/status.rb' - - 'app/models/status_edit.rb' - - 'app/models/status_pin.rb' - - 'app/models/status_stat.rb' - - 'app/models/tag.rb' - - 'app/models/unavailable_domain.rb' - - 'app/models/user.rb' - - 'app/models/user_ip.rb' - - 'app/models/web/push_subscription.rb' - - 'app/models/web/setting.rb' - - 'app/models/webauthn_credential.rb' - - 'config.ru' - - 'db/migrate/20220613110834_add_action_to_custom_filters.rb' - - 'db/post_migrate/20220613110802_remove_whole_word_from_custom_filters.rb' - - 'db/post_migrate/20220613110903_remove_irreversible_from_custom_filters.rb' - - 'spec/controllers/api/v1/accounts/statuses_controller_spec.rb' - - 'spec/models/tag_spec.rb' - -# Offense count: 113 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. -# SupportedHashRocketStyles: key, separator, table -# SupportedColonStyles: key, separator, table -# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit -Layout/HashAlignment: - Exclude: - - 'app/lib/activitypub/linked_data_signature.rb' - - 'app/lib/ostatus/tag_manager.rb' - - 'app/models/account/field.rb' - - 'app/models/account_warning.rb' - - 'app/models/media_attachment.rb' - - 'app/models/notification.rb' - - 'app/models/poll.rb' - - 'app/presenters/account_relationships_presenter.rb' - - 'app/services/keys/claim_service.rb' - - 'app/services/keys/query_service.rb' - - 'app/workers/web/push_notification_worker.rb' - - 'db/post_migrate/20200917193528_migrate_notifications_type.rb' - - 'lib/sanitize_ext/sanitize_config.rb' - - 'lib/tasks/auto_annotate_models.rake' - - 'lib/tasks/mastodon.rake' - - 'spec/models/admin/account_action_spec.rb' - - 'spec/models/concerns/account_interactions_spec.rb' - # Offense count: 581 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns. diff --git a/Capfile b/Capfile index bf3ae7e24..86efa5bac 100644 --- a/Capfile +++ b/Capfile @@ -1,4 +1,5 @@ # frozen_string_literal: true + require 'capistrano/setup' require 'capistrano/deploy' require 'capistrano/scm/git' 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/application_controller.rb b/app/controllers/application_controller.rb index 615536b96..ad70e28ab 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -128,6 +128,7 @@ class ApplicationController < ActionController::Base def current_theme return Setting.theme unless Themes.instance.names.include? current_user&.setting_theme + current_user.setting_theme 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 9c04ab4ca..b0a087d53 100644 --- a/app/controllers/concerns/signature_verification.rb +++ b/app/controllers/concerns/signature_verification.rb @@ -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 diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 1f93b33f5..08020a65a 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -105,6 +105,7 @@ module ApplicationHelper def can?(action, record) return false if record.nil? + policy(record).public_send("#{action}?") end diff --git a/app/helpers/languages_helper.rb b/app/helpers/languages_helper.rb index bb35ce08c..584394758 100644 --- a/app/helpers/languages_helper.rb +++ b/app/helpers/languages_helper.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # rubocop:disable Metrics/ModuleLength, Style/WordArray module LanguagesHelper diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index 900428e92..5d9596254 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -153,6 +153,7 @@ class ActivityPub::Activity def fetch_remote_original_status if object_uri.start_with?('http') return if ActivityPub::TagManager.instance.local_uri?(object_uri) + ActivityPub::FetchRemoteStatusService.new.call(object_uri, id: true, on_behalf_of: @account.followers.local.first, request_id: @options[:request_id]) elsif @object['url'].present? ::FetchRemoteStatusService.new.call(@object['url'], request_id: @options[:request_id]) diff --git a/app/lib/activitypub/linked_data_signature.rb b/app/lib/activitypub/linked_data_signature.rb index 61759649a..ea59879f3 100644 --- a/app/lib/activitypub/linked_data_signature.rb +++ b/app/lib/activitypub/linked_data_signature.rb @@ -32,7 +32,7 @@ class ActivityPub::LinkedDataSignature def sign!(creator, sign_with: nil) options = { - 'type' => 'RsaSignature2017', + 'type' => 'RsaSignature2017', 'creator' => ActivityPub::TagManager.instance.key_uri_for(creator), 'created' => Time.now.utc.iso8601, } diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb index 3d6b28ef5..a65a9565a 100644 --- a/app/lib/activitypub/tag_manager.rb +++ b/app/lib/activitypub/tag_manager.rb @@ -26,6 +26,7 @@ class ActivityPub::TagManager target.instance_actor? ? about_more_url(instance_actor: true) : short_account_url(target) when :note, :comment, :activity return activity_account_status_url(target.account, target) if target.reblog? + short_account_status_url(target.account, target) end end @@ -38,6 +39,7 @@ class ActivityPub::TagManager target.instance_actor? ? instance_actor_url : account_url(target) when :note, :comment, :activity return activity_account_status_url(target.account, target) if target.reblog? + account_status_url(target.account, target) when :emoji emoji_url(target) diff --git a/app/lib/ostatus/tag_manager.rb b/app/lib/ostatus/tag_manager.rb index 4f4501312..7d8131622 100644 --- a/app/lib/ostatus/tag_manager.rb +++ b/app/lib/ostatus/tag_manager.rb @@ -5,27 +5,27 @@ class OStatus::TagManager include RoutingHelper VERBS = { - post: 'http://activitystrea.ms/schema/1.0/post', - share: 'http://activitystrea.ms/schema/1.0/share', - favorite: 'http://activitystrea.ms/schema/1.0/favorite', - unfavorite: 'http://activitystrea.ms/schema/1.0/unfavorite', - delete: 'http://activitystrea.ms/schema/1.0/delete', - follow: 'http://activitystrea.ms/schema/1.0/follow', + post: 'http://activitystrea.ms/schema/1.0/post', + share: 'http://activitystrea.ms/schema/1.0/share', + favorite: 'http://activitystrea.ms/schema/1.0/favorite', + unfavorite: 'http://activitystrea.ms/schema/1.0/unfavorite', + delete: 'http://activitystrea.ms/schema/1.0/delete', + follow: 'http://activitystrea.ms/schema/1.0/follow', request_friend: 'http://activitystrea.ms/schema/1.0/request-friend', - authorize: 'http://activitystrea.ms/schema/1.0/authorize', - reject: 'http://activitystrea.ms/schema/1.0/reject', - unfollow: 'http://ostatus.org/schema/1.0/unfollow', - block: 'http://mastodon.social/schema/1.0/block', - unblock: 'http://mastodon.social/schema/1.0/unblock', + authorize: 'http://activitystrea.ms/schema/1.0/authorize', + reject: 'http://activitystrea.ms/schema/1.0/reject', + unfollow: 'http://ostatus.org/schema/1.0/unfollow', + block: 'http://mastodon.social/schema/1.0/block', + unblock: 'http://mastodon.social/schema/1.0/unblock', }.freeze TYPES = { - activity: 'http://activitystrea.ms/schema/1.0/activity', - note: 'http://activitystrea.ms/schema/1.0/note', - comment: 'http://activitystrea.ms/schema/1.0/comment', - person: 'http://activitystrea.ms/schema/1.0/person', + activity: 'http://activitystrea.ms/schema/1.0/activity', + note: 'http://activitystrea.ms/schema/1.0/note', + comment: 'http://activitystrea.ms/schema/1.0/comment', + person: 'http://activitystrea.ms/schema/1.0/person', collection: 'http://activitystrea.ms/schema/1.0/collection', - group: 'http://activitystrea.ms/schema/1.0/group', + group: 'http://activitystrea.ms/schema/1.0/group', }.freeze COLLECTIONS = { diff --git a/app/lib/request.rb b/app/lib/request.rb index be6a69b3f..85716f999 100644 --- a/app/lib/request.rb +++ b/app/lib/request.rb @@ -182,6 +182,7 @@ class Request contents = truncated_body(limit) raise Mastodon::LengthValidationError if contents.bytesize > limit + contents end end diff --git a/app/lib/settings/scoped_settings.rb b/app/lib/settings/scoped_settings.rb index 1e18d6d46..3ad57cc1e 100644 --- a/app/lib/settings/scoped_settings.rb +++ b/app/lib/settings/scoped_settings.rb @@ -34,6 +34,7 @@ module Settings Setting.default_settings.each do |key, default_value| next if records.key?(key) || default_value.is_a?(Hash) + records[key] = Setting.new(var: key, value: default_value) end @@ -54,6 +55,7 @@ module Settings if db_val default_value = ScopedSettings.default_settings[key] return default_value.with_indifferent_access.merge!(db_val.value) if default_value.is_a?(Hash) + db_val.value else ScopedSettings.default_settings[key] diff --git a/app/lib/status_filter.rb b/app/lib/status_filter.rb index b6c80b801..c0e6f3331 100644 --- a/app/lib/status_filter.rb +++ b/app/lib/status_filter.rb @@ -11,6 +11,7 @@ class StatusFilter def filtered? return false if !account.nil? && account.id == status.account_id + blocked_by_policy? || (account_present? && filtered_status?) || silenced_account? end diff --git a/app/lib/tag_manager.rb b/app/lib/tag_manager.rb index a1d12a654..7fbf4437d 100644 --- a/app/lib/tag_manager.rb +++ b/app/lib/tag_manager.rb @@ -25,6 +25,7 @@ class TagManager def local_url?(url) uri = Addressable::URI.parse(url).normalize return false unless uri.host + domain = uri.host + (uri.port ? ":#{uri.port}" : '') TagManager.instance.web_domain?(domain) diff --git a/app/lib/webfinger.rb b/app/lib/webfinger.rb index 42ddef47b..ae8a3b1ea 100644 --- a/app/lib/webfinger.rb +++ b/app/lib/webfinger.rb @@ -57,6 +57,7 @@ class Webfinger if res.code == 200 body = res.body_with_limit raise Webfinger::Error, "Request for #{@uri} returned empty response" if body.empty? + body elsif res.code == 404 && use_fallback body_from_host_meta diff --git a/app/models/account.rb b/app/models/account.rb index d33110d55..09c450f2a 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: accounts @@ -539,6 +540,7 @@ class Account < ApplicationRecord def ensure_keys! return unless local? && private_key.blank? && public_key.blank? + generate_keys save! end diff --git a/app/models/account/field.rb b/app/models/account/field.rb index 98c29726d..2bada6954 100644 --- a/app/models/account/field.rb +++ b/app/models/account/field.rb @@ -14,8 +14,8 @@ class Account::Field < ActiveModelSerializers::Model @account = account super( - name: sanitize(attributes['name']), - value: sanitize(attributes['value']), + name: sanitize(attributes['name']), + value: sanitize(attributes['value']), verified_at: attributes['verified_at']&.to_datetime, ) end diff --git a/app/models/account_conversation.rb b/app/models/account_conversation.rb index 45e74bbeb..b3ddc04c1 100644 --- a/app/models/account_conversation.rb +++ b/app/models/account_conversation.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: account_conversations @@ -107,6 +108,7 @@ class AccountConversation < ApplicationRecord def push_to_streaming_api return if destroyed? || !subscribed_to_timeline? + PushConversationWorker.perform_async(id) end diff --git a/app/models/account_domain_block.rb b/app/models/account_domain_block.rb index 3aaffde9a..af1e6a68d 100644 --- a/app/models/account_domain_block.rb +++ b/app/models/account_domain_block.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: account_domain_blocks diff --git a/app/models/account_moderation_note.rb b/app/models/account_moderation_note.rb index 22e312bb2..ff399bab0 100644 --- a/app/models/account_moderation_note.rb +++ b/app/models/account_moderation_note.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: account_moderation_notes diff --git a/app/models/account_note.rb b/app/models/account_note.rb index b338bc92f..9bc704d98 100644 --- a/app/models/account_note.rb +++ b/app/models/account_note.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: account_notes diff --git a/app/models/account_pin.rb b/app/models/account_pin.rb index b51d3d4cd..6c78e8c44 100644 --- a/app/models/account_pin.rb +++ b/app/models/account_pin.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: account_pins diff --git a/app/models/account_stat.rb b/app/models/account_stat.rb index a5d71a5b8..834f8ba4c 100644 --- a/app/models/account_stat.rb +++ b/app/models/account_stat.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: account_stats diff --git a/app/models/account_summary.rb b/app/models/account_summary.rb index 3a3cebc55..0d8835b83 100644 --- a/app/models/account_summary.rb +++ b/app/models/account_summary.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: account_summaries diff --git a/app/models/account_warning.rb b/app/models/account_warning.rb index a181cd18d..4f8cc5320 100644 --- a/app/models/account_warning.rb +++ b/app/models/account_warning.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: account_warnings @@ -17,13 +18,13 @@ class AccountWarning < ApplicationRecord enum action: { - none: 0, - disable: 1_000, + none: 0, + disable: 1_000, mark_statuses_as_sensitive: 1_250, - delete_statuses: 1_500, - sensitive: 2_000, - silence: 3_000, - suspend: 4_000, + delete_statuses: 1_500, + sensitive: 2_000, + silence: 3_000, + suspend: 4_000, }, _suffix: :action before_validation :before_validate diff --git a/app/models/admin/import.rb b/app/models/admin/import.rb index fecde4878..0fd4bdb82 100644 --- a/app/models/admin/import.rb +++ b/app/models/admin/import.rb @@ -56,6 +56,7 @@ class Admin::Import def validate_data return if data.nil? + errors.add(:data, I18n.t('imports.errors.over_rows_processing_limit', count: ROWS_PROCESSING_LIMIT)) if csv_row_count > ROWS_PROCESSING_LIMIT rescue CSV::MalformedCSVError => e errors.add(:data, I18n.t('imports.errors.invalid_csv_file', error: e.message)) diff --git a/app/models/backup.rb b/app/models/backup.rb index 277b9395b..bec3cbfe5 100644 --- a/app/models/backup.rb +++ b/app/models/backup.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: backups diff --git a/app/models/block.rb b/app/models/block.rb index bf3e07600..b42c1569b 100644 --- a/app/models/block.rb +++ b/app/models/block.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: blocks diff --git a/app/models/bookmark.rb b/app/models/bookmark.rb index 6334ef0df..04b660372 100644 --- a/app/models/bookmark.rb +++ b/app/models/bookmark.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: bookmarks diff --git a/app/models/canonical_email_block.rb b/app/models/canonical_email_block.rb index 1eb69ac67..d09df6f5e 100644 --- a/app/models/canonical_email_block.rb +++ b/app/models/canonical_email_block.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: canonical_email_blocks diff --git a/app/models/conversation.rb b/app/models/conversation.rb index 4dfaea889..5de259962 100644 --- a/app/models/conversation.rb +++ b/app/models/conversation.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: conversations diff --git a/app/models/conversation_mute.rb b/app/models/conversation_mute.rb index 52c1a33e0..31f8e1966 100644 --- a/app/models/conversation_mute.rb +++ b/app/models/conversation_mute.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: conversation_mutes diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb index 304805659..3d7900226 100644 --- a/app/models/custom_emoji.rb +++ b/app/models/custom_emoji.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: custom_emojis diff --git a/app/models/custom_filter.rb b/app/models/custom_filter.rb index 781bf4db8..d85e196e9 100644 --- a/app/models/custom_filter.rb +++ b/app/models/custom_filter.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: custom_filters @@ -101,6 +102,7 @@ class CustomFilter < ApplicationRecord status_matches = [status.id, status.reblog_of_id].compact & rules[:status_ids] if rules[:status_ids].present? next if keyword_matches.blank? && status_matches.blank? + FilterResultPresenter.new(filter: filter, keyword_matches: keyword_matches, status_matches: status_matches) end end @@ -111,6 +113,7 @@ class CustomFilter < ApplicationRecord def invalidate_cache! return unless @should_invalidate_cache + @should_invalidate_cache = false Rails.cache.delete("filters:v3:#{account_id}") diff --git a/app/models/custom_filter_keyword.rb b/app/models/custom_filter_keyword.rb index e0d0289ae..3158b3b79 100644 --- a/app/models/custom_filter_keyword.rb +++ b/app/models/custom_filter_keyword.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: custom_filter_keywords diff --git a/app/models/custom_filter_status.rb b/app/models/custom_filter_status.rb index e748d6963..0a5650204 100644 --- a/app/models/custom_filter_status.rb +++ b/app/models/custom_filter_status.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: custom_filter_statuses diff --git a/app/models/device.rb b/app/models/device.rb index 97d0d2774..5dc6cf1e6 100644 --- a/app/models/device.rb +++ b/app/models/device.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: devices diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb index 190f5ba2e..fbb045416 100644 --- a/app/models/domain_block.rb +++ b/app/models/domain_block.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: domain_blocks diff --git a/app/models/email_domain_block.rb b/app/models/email_domain_block.rb index 3a56e4f2a..276e7d31a 100644 --- a/app/models/email_domain_block.rb +++ b/app/models/email_domain_block.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: email_domain_blocks diff --git a/app/models/encrypted_message.rb b/app/models/encrypted_message.rb index 7b4e32283..3e7e95594 100644 --- a/app/models/encrypted_message.rb +++ b/app/models/encrypted_message.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: encrypted_messages diff --git a/app/models/favourite.rb b/app/models/favourite.rb index 2f355739a..042f72bea 100644 --- a/app/models/favourite.rb +++ b/app/models/favourite.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: favourites @@ -38,6 +39,7 @@ class Favourite < ApplicationRecord def decrement_cache_counters return if association(:status).loaded? && status.marked_for_destruction? + status&.decrement_count!(:favourites_count) end diff --git a/app/models/featured_tag.rb b/app/models/featured_tag.rb index 70f949b6a..587dcf991 100644 --- a/app/models/featured_tag.rb +++ b/app/models/featured_tag.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: featured_tags diff --git a/app/models/follow.rb b/app/models/follow.rb index e5cecbbc1..108f5c5d5 100644 --- a/app/models/follow.rb +++ b/app/models/follow.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: follows diff --git a/app/models/follow_recommendation.rb b/app/models/follow_recommendation.rb index 501f8ecb6..602d32985 100644 --- a/app/models/follow_recommendation.rb +++ b/app/models/follow_recommendation.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: follow_recommendations diff --git a/app/models/follow_recommendation_suppression.rb b/app/models/follow_recommendation_suppression.rb index 170506b85..a9dbbfc18 100644 --- a/app/models/follow_recommendation_suppression.rb +++ b/app/models/follow_recommendation_suppression.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: follow_recommendation_suppressions diff --git a/app/models/follow_request.rb b/app/models/follow_request.rb index 9034250c0..78f79c18f 100644 --- a/app/models/follow_request.rb +++ b/app/models/follow_request.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: follow_requests diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index 95c53084a..de965cb0b 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -128,6 +128,7 @@ class Form::AdminSettings def validate_site_uploads UPLOAD_KEYS.each do |key| next unless instance_variable_defined?("@#{key}") + upload = instance_variable_get("@#{key}") next if upload.valid? diff --git a/app/models/identity.rb b/app/models/identity.rb index 8cc65aef4..6f10fed4d 100644 --- a/app/models/identity.rb +++ b/app/models/identity.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: identities diff --git a/app/models/import.rb b/app/models/import.rb index cd33eb07b..21634005e 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: imports diff --git a/app/models/instance.rb b/app/models/instance.rb index edbf02a6d..1f96d3728 100644 --- a/app/models/instance.rb +++ b/app/models/instance.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: instances diff --git a/app/models/invite.rb b/app/models/invite.rb index 7ea4e2f98..8e816cef0 100644 --- a/app/models/invite.rb +++ b/app/models/invite.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: invites diff --git a/app/models/ip_block.rb b/app/models/ip_block.rb index 31343f0e1..99783050b 100644 --- a/app/models/ip_block.rb +++ b/app/models/ip_block.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: ip_blocks diff --git a/app/models/list.rb b/app/models/list.rb index 7b8cf6636..bd1bdbd24 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: lists diff --git a/app/models/list_account.rb b/app/models/list_account.rb index 785923c4c..a5767d3d8 100644 --- a/app/models/list_account.rb +++ b/app/models/list_account.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: list_accounts diff --git a/app/models/login_activity.rb b/app/models/login_activity.rb index 52a0fd01d..2b7b37f8e 100644 --- a/app/models/login_activity.rb +++ b/app/models/login_activity.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: login_activities diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index c6f2352e0..08abd4e43 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: media_attachments @@ -372,7 +373,7 @@ class MediaAttachment < ApplicationRecord return {} if width.nil? { - width: width, + width: width, height: height, size: "#{width}x#{height}", aspect: width.to_f / height, diff --git a/app/models/mention.rb b/app/models/mention.rb index d01a88e32..2348b2905 100644 --- a/app/models/mention.rb +++ b/app/models/mention.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: mentions diff --git a/app/models/mute.rb b/app/models/mute.rb index 578345ef6..8fc542262 100644 --- a/app/models/mute.rb +++ b/app/models/mute.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: mutes diff --git a/app/models/notification.rb b/app/models/notification.rb index 01155c363..3eaf557b0 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: notifications @@ -19,12 +20,12 @@ class Notification < ApplicationRecord include Paginable LEGACY_TYPE_CLASS_MAP = { - 'Mention' => :mention, - 'Status' => :reblog, - 'Follow' => :follow, + 'Mention' => :mention, + 'Status' => :reblog, + 'Follow' => :follow, 'FollowRequest' => :follow_request, - 'Favourite' => :favourite, - 'Poll' => :poll, + 'Favourite' => :favourite, + 'Poll' => :poll, }.freeze TYPES = %i( diff --git a/app/models/one_time_key.rb b/app/models/one_time_key.rb index 8ada34824..23604e2f7 100644 --- a/app/models/one_time_key.rb +++ b/app/models/one_time_key.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: one_time_keys diff --git a/app/models/poll.rb b/app/models/poll.rb index af3b09315..dd35e953b 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: polls @@ -74,9 +75,9 @@ class Poll < ApplicationRecord def initialize(poll, id, title, votes_count) super( - poll: poll, - id: id, - title: title, + poll: poll, + id: id, + title: title, votes_count: votes_count, ) end @@ -105,6 +106,7 @@ class Poll < ApplicationRecord def reset_parent_cache return if status_id.nil? + Rails.cache.delete("statuses/#{status_id}") end diff --git a/app/models/poll_vote.rb b/app/models/poll_vote.rb index ad24eb691..00eaedd12 100644 --- a/app/models/poll_vote.rb +++ b/app/models/poll_vote.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: poll_votes diff --git a/app/models/preview_card.rb b/app/models/preview_card.rb index d25fe6dad..6bce16562 100644 --- a/app/models/preview_card.rb +++ b/app/models/preview_card.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: preview_cards diff --git a/app/models/preview_card_provider.rb b/app/models/preview_card_provider.rb index d61fe6020..1dd95fc91 100644 --- a/app/models/preview_card_provider.rb +++ b/app/models/preview_card_provider.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: preview_card_providers diff --git a/app/models/relay.rb b/app/models/relay.rb index e9c425743..a5fa03a99 100644 --- a/app/models/relay.rb +++ b/app/models/relay.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: relays diff --git a/app/models/report.rb b/app/models/report.rb index fe6c292c5..a9940459d 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: reports diff --git a/app/models/report_note.rb b/app/models/report_note.rb index 6d7167e0e..74b46027e 100644 --- a/app/models/report_note.rb +++ b/app/models/report_note.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: report_notes diff --git a/app/models/session_activation.rb b/app/models/session_activation.rb index 0b7fa6fe4..10c3a6c25 100644 --- a/app/models/session_activation.rb +++ b/app/models/session_activation.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: session_activations @@ -51,6 +52,7 @@ class SessionActivation < ApplicationRecord def deactivate(id) return unless id + where(session_id: id).destroy_all end diff --git a/app/models/setting.rb b/app/models/setting.rb index c6558d692..3bdc6ffb4 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: settings @@ -30,6 +31,7 @@ class Setting < RailsSettings::Base default_value = default_settings[key] return default_value.with_indifferent_access.merge!(db_val.value) if default_value.is_a?(Hash) + db_val.value else default_settings[key] @@ -43,6 +45,7 @@ class Setting < RailsSettings::Base default_settings.each do |key, default_value| next if records.key?(key) || default_value.is_a?(Hash) + records[key] = Setting.new(var: key, value: default_value) end @@ -51,6 +54,7 @@ class Setting < RailsSettings::Base def default_settings return {} unless RailsSettings::Default.enabled? + RailsSettings::Default.instance end end diff --git a/app/models/site_upload.rb b/app/models/site_upload.rb index 167131fdd..e17668110 100644 --- a/app/models/site_upload.rb +++ b/app/models/site_upload.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: site_uploads diff --git a/app/models/status.rb b/app/models/status.rb index 44a297a08..2eb47d72c 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: statuses diff --git a/app/models/status_edit.rb b/app/models/status_edit.rb index dd2d5fc1e..683441bb5 100644 --- a/app/models/status_edit.rb +++ b/app/models/status_edit.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: status_edits @@ -45,6 +46,7 @@ class StatusEdit < ApplicationRecord def emojis return @emojis if defined?(@emojis) + @emojis = CustomEmoji.from_text([spoiler_text, text].join(' '), status.account.domain) end diff --git a/app/models/status_pin.rb b/app/models/status_pin.rb index 93a0ea1c0..dae4a5b4e 100644 --- a/app/models/status_pin.rb +++ b/app/models/status_pin.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: status_pins diff --git a/app/models/status_stat.rb b/app/models/status_stat.rb index 437861d1c..d101cc178 100644 --- a/app/models/status_stat.rb +++ b/app/models/status_stat.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: status_stats diff --git a/app/models/tag.rb b/app/models/tag.rb index 98001d60a..554a92d90 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: tags diff --git a/app/models/unavailable_domain.rb b/app/models/unavailable_domain.rb index dfc0ef14e..c3f2f20e9 100644 --- a/app/models/unavailable_domain.rb +++ b/app/models/unavailable_domain.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: unavailable_domains diff --git a/app/models/user.rb b/app/models/user.rb index c767f8984..5e106dee5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: users @@ -492,12 +493,14 @@ class User < ApplicationRecord def sanitize_languages return if chosen_languages.nil? + chosen_languages.reject!(&:blank?) self.chosen_languages = nil if chosen_languages.empty? end def sanitize_role return if role.nil? + self.role = nil if role.everyone? end @@ -516,6 +519,7 @@ class User < ApplicationRecord def notify_staff_about_pending_account! User.those_who_can(:manage_users).includes(:account).find_each do |u| next unless u.allows_pending_account_emails? + AdminMailer.new_pending_account(u.account, self).deliver_later end end diff --git a/app/models/user_ip.rb b/app/models/user_ip.rb index 1da615762..38287c2a6 100644 --- a/app/models/user_ip.rb +++ b/app/models/user_ip.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: user_ips diff --git a/app/models/user_role.rb b/app/models/user_role.rb index 74dfdc220..a1b91dc0f 100644 --- a/app/models/user_role.rb +++ b/app/models/user_role.rb @@ -163,6 +163,7 @@ class UserRole < ApplicationRecord def in_permissions?(privilege) raise ArgumentError, "Unknown privilege: #{privilege}" unless FLAGS.key?(privilege) + computed_permissions & FLAGS[privilege] == FLAGS[privilege] end @@ -172,6 +173,7 @@ class UserRole < ApplicationRecord def validate_own_role_edition return unless defined?(@current_account) && @current_account.user_role.id == id + errors.add(:permissions_as_keys, :own_role) if permissions_changed? errors.add(:position, :own_role) if position_changed? end diff --git a/app/models/web/push_subscription.rb b/app/models/web/push_subscription.rb index dfaadf5cc..0ffbe068e 100644 --- a/app/models/web/push_subscription.rb +++ b/app/models/web/push_subscription.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: web_push_subscriptions diff --git a/app/models/web/setting.rb b/app/models/web/setting.rb index 99588d26c..3d5efe664 100644 --- a/app/models/web/setting.rb +++ b/app/models/web/setting.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: web_settings diff --git a/app/models/webauthn_credential.rb b/app/models/webauthn_credential.rb index 48abfc1d4..4fa31ece5 100644 --- a/app/models/webauthn_credential.rb +++ b/app/models/webauthn_credential.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # == Schema Information # # Table name: webauthn_credentials diff --git a/app/presenters/account_relationships_presenter.rb b/app/presenters/account_relationships_presenter.rb index ab8bac412..5d2b5435d 100644 --- a/app/presenters/account_relationships_presenter.rb +++ b/app/presenters/account_relationships_presenter.rb @@ -70,16 +70,16 @@ class AccountRelationshipsPresenter def cache_uncached! @uncached_account_ids.each do |account_id| maps_for_account = { - following: { account_id => following[account_id] }, - followed_by: { account_id => followed_by[account_id] }, - blocking: { account_id => blocking[account_id] }, - blocked_by: { account_id => blocked_by[account_id] }, - muting: { account_id => muting[account_id] }, - requested: { account_id => requested[account_id] }, - requested_by: { account_id => requested_by[account_id] }, + following: { account_id => following[account_id] }, + followed_by: { account_id => followed_by[account_id] }, + blocking: { account_id => blocking[account_id] }, + blocked_by: { account_id => blocked_by[account_id] }, + muting: { account_id => muting[account_id] }, + requested: { account_id => requested[account_id] }, + requested_by: { account_id => requested_by[account_id] }, domain_blocking: { account_id => domain_blocking[account_id] }, - endorsed: { account_id => endorsed[account_id] }, - account_note: { account_id => account_note[account_id] }, + endorsed: { account_id => endorsed[account_id] }, + account_note: { account_id => account_note[account_id] }, } Rails.cache.write("relationship:#{@current_account_id}:#{account_id}", maps_for_account, expires_in: 1.day) diff --git a/app/services/activitypub/fetch_remote_actor_service.rb b/app/services/activitypub/fetch_remote_actor_service.rb index e8992b845..ee0eaff08 100644 --- a/app/services/activitypub/fetch_remote_actor_service.rb +++ b/app/services/activitypub/fetch_remote_actor_service.rb @@ -50,6 +50,7 @@ class ActivityPub::FetchRemoteActorService < BaseService if @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero? raise Error, "Webfinger response for #{@username}@#{@domain} does not loop back to #{@uri}" if webfinger.link('self', 'href') != @uri + return end diff --git a/app/services/activitypub/fetch_remote_status_service.rb b/app/services/activitypub/fetch_remote_status_service.rb index aea80f078..ab0acf7f0 100644 --- a/app/services/activitypub/fetch_remote_status_service.rb +++ b/app/services/activitypub/fetch_remote_status_service.rb @@ -56,6 +56,7 @@ class ActivityPub::FetchRemoteStatusService < BaseService def trustworthy_attribution?(uri, attributed_to) return false if uri.nil? || attributed_to.nil? + Addressable::URI.parse(uri).normalized_host.casecmp(Addressable::URI.parse(attributed_to).normalized_host).zero? end diff --git a/app/services/activitypub/fetch_replies_service.rb b/app/services/activitypub/fetch_replies_service.rb index 4128df9ca..3fe150ba2 100644 --- a/app/services/activitypub/fetch_replies_service.rb +++ b/app/services/activitypub/fetch_replies_service.rb @@ -36,6 +36,7 @@ class ActivityPub::FetchRepliesService < BaseService return collection_or_uri if collection_or_uri.is_a?(Hash) return unless @allow_synchronous_requests return if invalid_origin?(collection_or_uri) + fetch_resource_without_id_validation(collection_or_uri, nil, true) end diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb index 2da9096c7..603e4cf48 100644 --- a/app/services/activitypub/process_account_service.rb +++ b/app/services/activitypub/process_account_service.rb @@ -226,6 +226,7 @@ class ActivityPub::ProcessAccountService < BaseService def property_values return unless @json['attachment'].is_a?(Array) + as_array(@json['attachment']).select { |attachment| attachment['type'] == 'PropertyValue' }.map { |attachment| attachment.slice('name', 'value') } end @@ -289,6 +290,7 @@ class ActivityPub::ProcessAccountService < BaseService def domain_block return @domain_block if defined?(@domain_block) + @domain_block = DomainBlock.rule_for(@domain) end diff --git a/app/services/favourite_service.rb b/app/services/favourite_service.rb index dc7fe8855..6fdc92a17 100644 --- a/app/services/favourite_service.rb +++ b/app/services/favourite_service.rb @@ -40,6 +40,7 @@ class FavouriteService < BaseService def bump_potential_friendship(account, status) ActivityTracker.increment('activity:interactions') return if account.following?(status.account_id) + PotentialFriendshipTracker.record(account.id, status.account_id, :favourite) end diff --git a/app/services/keys/claim_service.rb b/app/services/keys/claim_service.rb index 0451c3cb1..ebce9cce7 100644 --- a/app/services/keys/claim_service.rb +++ b/app/services/keys/claim_service.rb @@ -9,10 +9,10 @@ class Keys::ClaimService < BaseService def initialize(account, device_id, key_attributes = {}) super( - account: account, + account: account, device_id: device_id, - key_id: key_attributes[:key_id], - key: key_attributes[:key], + key_id: key_attributes[:key_id], + key: key_attributes[:key], signature: key_attributes[:signature], ) end diff --git a/app/services/keys/query_service.rb b/app/services/keys/query_service.rb index 404854c9f..14c9d9205 100644 --- a/app/services/keys/query_service.rb +++ b/app/services/keys/query_service.rb @@ -23,9 +23,9 @@ class Keys::QueryService < BaseService def initialize(attributes = {}) super( - device_id: attributes[:device_id], - name: attributes[:name], - identity_key: attributes[:identity_key], + device_id: attributes[:device_id], + name: attributes[:name], + identity_key: attributes[:identity_key], fingerprint_key: attributes[:fingerprint_key], ) @claim_url = attributes[:claim_url] diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index c7454fc60..4c7acbcac 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -31,6 +31,7 @@ class NotifyService < BaseService def following_sender? return @following_sender if defined?(@following_sender) + @following_sender = @recipient.following?(@notification.from_account) || @recipient.requested?(@notification.from_account) end diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb index 258af8827..ea27f374e 100644 --- a/app/services/post_status_service.rb +++ b/app/services/post_status_service.rb @@ -86,6 +86,7 @@ class PostStatusService < BaseService def safeguard_mentions!(status) return if @options[:allowed_mentions].nil? + expected_account_ids = @options[:allowed_mentions].map(&:to_i) unexpected_accounts = status.mentions.map(&:account).to_a.reject { |mentioned_account| expected_account_ids.include?(mentioned_account.id) } @@ -175,8 +176,10 @@ class PostStatusService < BaseService def bump_potential_friendship! return if !@status.reply? || @account.id == @status.in_reply_to_account_id + ActivityTracker.increment('activity:interactions') return if @account.following?(@status.in_reply_to_account_id) + PotentialFriendshipTracker.record(@account.id, @status.in_reply_to_account_id, :reply) end diff --git a/app/services/vote_service.rb b/app/services/vote_service.rb index 114ec285c..9ebf5a98d 100644 --- a/app/services/vote_service.rb +++ b/app/services/vote_service.rb @@ -44,11 +44,13 @@ class VoteService < BaseService def distribute_poll! return if @poll.hide_totals? + ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, @poll.status.id) end def queue_final_poll_check! return unless @poll.expires? + PollExpirationNotifyWorker.perform_at(@poll.expires_at + 5.minutes, @poll.id) end diff --git a/app/validators/follow_limit_validator.rb b/app/validators/follow_limit_validator.rb index 409bf0176..c619cb9a3 100644 --- a/app/validators/follow_limit_validator.rb +++ b/app/validators/follow_limit_validator.rb @@ -6,6 +6,7 @@ class FollowLimitValidator < ActiveModel::Validator def validate(follow) return if follow.account.nil? || !follow.account.local? + follow.errors.add(:base, I18n.t('users.follow_limit_reached', limit: self.class.limit_for_account(follow.account))) if limit_reached?(follow.account) end diff --git a/app/validators/unreserved_username_validator.rb b/app/validators/unreserved_username_validator.rb index 974f3ba62..f82f4b91d 100644 --- a/app/validators/unreserved_username_validator.rb +++ b/app/validators/unreserved_username_validator.rb @@ -13,12 +13,14 @@ class UnreservedUsernameValidator < ActiveModel::Validator def pam_controlled? return false unless Devise.pam_authentication && Devise.pam_controlled_service + Rpam2.account(Devise.pam_controlled_service, @username).present? end def reserved_username? return true if pam_controlled? return false unless Setting.reserved_usernames + Setting.reserved_usernames.include?(@username.downcase) end end diff --git a/app/workers/scheduler/accounts_statuses_cleanup_scheduler.rb b/app/workers/scheduler/accounts_statuses_cleanup_scheduler.rb index cc5b6e137..09e0b37f0 100644 --- a/app/workers/scheduler/accounts_statuses_cleanup_scheduler.rb +++ b/app/workers/scheduler/accounts_statuses_cleanup_scheduler.rb @@ -62,6 +62,7 @@ class Scheduler::AccountsStatusesCleanupScheduler # The idea here is to loop through all policies at least once until the budget is exhausted # and start back after the last processed account otherwise break if budget.zero? || (num_processed_accounts.zero? && first_policy_id.nil?) + first_policy_id = nil end end @@ -73,6 +74,7 @@ class Scheduler::AccountsStatusesCleanupScheduler def under_load? return true if Sidekiq::Stats.new.retry_size > MAX_RETRY_SIZE + queue_under_load?('default', MAX_DEFAULT_SIZE, MAX_DEFAULT_LATENCY) || queue_under_load?('push', MAX_PUSH_SIZE, MAX_PUSH_LATENCY) || queue_under_load?('pull', MAX_PULL_SIZE, MAX_PULL_LATENCY) end diff --git a/app/workers/web/push_notification_worker.rb b/app/workers/web/push_notification_worker.rb index 1ed5bb9e0..7e9691aab 100644 --- a/app/workers/web/push_notification_worker.rb +++ b/app/workers/web/push_notification_worker.rb @@ -22,13 +22,13 @@ class Web::PushNotificationWorker request = Request.new(:post, @subscription.endpoint, body: payload.fetch(:ciphertext), http_client: http_client) request.add_headers( - 'Content-Type' => 'application/octet-stream', - 'Ttl' => TTL, - 'Urgency' => URGENCY, + 'Content-Type' => 'application/octet-stream', + 'Ttl' => TTL, + 'Urgency' => URGENCY, 'Content-Encoding' => 'aesgcm', - 'Encryption' => "salt=#{Webpush.encode64(payload.fetch(:salt)).delete('=')}", - 'Crypto-Key' => "dh=#{Webpush.encode64(payload.fetch(:server_public_key)).delete('=')};#{@subscription.crypto_key_header}", - 'Authorization' => @subscription.authorization_header + 'Encryption' => "salt=#{Webpush.encode64(payload.fetch(:salt)).delete('=')}", + 'Crypto-Key' => "dh=#{Webpush.encode64(payload.fetch(:server_public_key)).delete('=')};#{@subscription.crypto_key_header}", + 'Authorization' => @subscription.authorization_header ) request.perform do |response| diff --git a/config.ru b/config.ru index 5e071f530..afd13e211 100644 --- a/config.ru +++ b/config.ru @@ -1,4 +1,5 @@ # frozen_string_literal: true + # This file is used by Rack-based servers to start the application. require File.expand_path('config/environment', __dir__) diff --git a/db/migrate/20190314181829_migrate_open_registrations_setting.rb b/db/migrate/20190314181829_migrate_open_registrations_setting.rb index e5fe95009..d2f6bf2c1 100644 --- a/db/migrate/20190314181829_migrate_open_registrations_setting.rb +++ b/db/migrate/20190314181829_migrate_open_registrations_setting.rb @@ -2,6 +2,7 @@ class MigrateOpenRegistrationsSetting < ActiveRecord::Migration[5.2] def up open_registrations = Setting.find_by(var: 'open_registrations') return if open_registrations.nil? || open_registrations.value + setting = Setting.where(var: 'registrations_mode').first_or_initialize(var: 'registrations_mode') setting.update(value: 'none') end @@ -9,6 +10,7 @@ class MigrateOpenRegistrationsSetting < ActiveRecord::Migration[5.2] def down registrations_mode = Setting.find_by(var: 'registrations_mode') return if registrations_mode.nil? + setting = Setting.where(var: 'open_registrations').first_or_initialize(var: 'open_registrations') setting.update(value: registrations_mode.value == 'open') end diff --git a/db/migrate/20190529143559_preserve_old_layout_for_existing_users.rb b/db/migrate/20190529143559_preserve_old_layout_for_existing_users.rb index 19e86fbfe..1c18b85cb 100644 --- a/db/migrate/20190529143559_preserve_old_layout_for_existing_users.rb +++ b/db/migrate/20190529143559_preserve_old_layout_for_existing_users.rb @@ -8,6 +8,7 @@ class PreserveOldLayoutForExistingUsers < ActiveRecord::Migration[5.2] User.where(User.arel_table[:current_sign_in_at].gteq(1.month.ago)).find_each do |user| next if Setting.unscoped.where(thing_type: 'User', thing_id: user.id, var: 'advanced_layout').exists? + user.settings.advanced_layout = true end end diff --git a/db/migrate/20210421121431_add_case_insensitive_btree_index_to_tags.rb b/db/migrate/20210421121431_add_case_insensitive_btree_index_to_tags.rb index 7f6a2c6dd..a3cc854d7 100644 --- a/db/migrate/20210421121431_add_case_insensitive_btree_index_to_tags.rb +++ b/db/migrate/20210421121431_add_case_insensitive_btree_index_to_tags.rb @@ -11,6 +11,7 @@ class AddCaseInsensitiveBtreeIndexToTags < ActiveRecord::Migration[5.2] rescue ActiveRecord::StatementInvalid => e remove_index :tags, name: 'index_tags_on_name_lower_btree' raise CorruptionError, 'index_tags_on_name_lower_btree' if e.is_a?(ActiveRecord::RecordNotUnique) + raise e end diff --git a/db/migrate/20220613110834_add_action_to_custom_filters.rb b/db/migrate/20220613110834_add_action_to_custom_filters.rb index 9427a66fc..c1daf3c94 100644 --- a/db/migrate/20220613110834_add_action_to_custom_filters.rb +++ b/db/migrate/20220613110834_add_action_to_custom_filters.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require Rails.root.join('lib', 'mastodon', 'migration_helpers') class AddActionToCustomFilters < ActiveRecord::Migration[6.1] diff --git a/db/post_migrate/20200917193528_migrate_notifications_type.rb b/db/post_migrate/20200917193528_migrate_notifications_type.rb index 88e423084..9dc9ecd48 100644 --- a/db/post_migrate/20200917193528_migrate_notifications_type.rb +++ b/db/post_migrate/20200917193528_migrate_notifications_type.rb @@ -4,12 +4,12 @@ class MigrateNotificationsType < ActiveRecord::Migration[5.2] disable_ddl_transaction! TYPES_TO_MIGRATE = { - 'Mention' => :mention, - 'Status' => :reblog, - 'Follow' => :follow, + 'Mention' => :mention, + 'Status' => :reblog, + 'Follow' => :follow, 'FollowRequest' => :follow_request, - 'Favourite' => :favourite, - 'Poll' => :poll, + 'Favourite' => :favourite, + 'Poll' => :poll, }.freeze def up diff --git a/db/post_migrate/20220613110802_remove_whole_word_from_custom_filters.rb b/db/post_migrate/20220613110802_remove_whole_word_from_custom_filters.rb index 7ef0749e5..99c3366a2 100644 --- a/db/post_migrate/20220613110802_remove_whole_word_from_custom_filters.rb +++ b/db/post_migrate/20220613110802_remove_whole_word_from_custom_filters.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require Rails.root.join('lib', 'mastodon', 'migration_helpers') class RemoveWholeWordFromCustomFilters < ActiveRecord::Migration[6.1] diff --git a/db/post_migrate/20220613110903_remove_irreversible_from_custom_filters.rb b/db/post_migrate/20220613110903_remove_irreversible_from_custom_filters.rb index 6ed8bcfee..1c366ee53 100644 --- a/db/post_migrate/20220613110903_remove_irreversible_from_custom_filters.rb +++ b/db/post_migrate/20220613110903_remove_irreversible_from_custom_filters.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require Rails.root.join('lib', 'mastodon', 'migration_helpers') class RemoveIrreversibleFromCustomFilters < ActiveRecord::Migration[6.1] diff --git a/db/post_migrate/20221101190723_backfill_admin_action_logs.rb b/db/post_migrate/20221101190723_backfill_admin_action_logs.rb index 6ab76a8f7..fa2ddbbca 100644 --- a/db/post_migrate/20221101190723_backfill_admin_action_logs.rb +++ b/db/post_migrate/20221101190723_backfill_admin_action_logs.rb @@ -79,11 +79,13 @@ class BackfillAdminActionLogs < ActiveRecord::Migration[6.1] safety_assured do AdminActionLog.includes(:account).where(target_type: 'Account', human_identifier: nil).find_each do |log| next if log.account.nil? + log.update_attribute('human_identifier', log.account.acct) end AdminActionLog.includes(user: :account).where(target_type: 'User', human_identifier: nil).find_each do |log| next if log.user.nil? + log.update_attribute('human_identifier', log.user.account.acct) log.update_attribute('route_param', log.user.account_id) end @@ -92,57 +94,68 @@ class BackfillAdminActionLogs < ActiveRecord::Migration[6.1] AdminActionLog.includes(:domain_block).where(target_type: 'DomainBlock').find_each do |log| next if log.domain_block.nil? + log.update_attribute('human_identifier', log.domain_block.domain) end AdminActionLog.includes(:domain_allow).where(target_type: 'DomainAllow').find_each do |log| next if log.domain_allow.nil? + log.update_attribute('human_identifier', log.domain_allow.domain) end AdminActionLog.includes(:email_domain_block).where(target_type: 'EmailDomainBlock').find_each do |log| next if log.email_domain_block.nil? + log.update_attribute('human_identifier', log.email_domain_block.domain) end AdminActionLog.includes(:unavailable_domain).where(target_type: 'UnavailableDomain').find_each do |log| next if log.unavailable_domain.nil? + log.update_attribute('human_identifier', log.unavailable_domain.domain) end AdminActionLog.includes(status: :account).where(target_type: 'Status', human_identifier: nil).find_each do |log| next if log.status.nil? + log.update_attribute('human_identifier', log.status.account.acct) log.update_attribute('permalink', log.status.uri) end AdminActionLog.includes(account_warning: :account).where(target_type: 'AccountWarning', human_identifier: nil).find_each do |log| next if log.account_warning.nil? + log.update_attribute('human_identifier', log.account_warning.account.acct) end AdminActionLog.includes(:announcement).where(target_type: 'Announcement', human_identifier: nil).find_each do |log| next if log.announcement.nil? + log.update_attribute('human_identifier', log.announcement.text) end AdminActionLog.includes(:ip_block).where(target_type: 'IpBlock', human_identifier: nil).find_each do |log| next if log.ip_block.nil? + log.update_attribute('human_identifier', "#{log.ip_block.ip}/#{log.ip_block.ip.prefix}") end AdminActionLog.includes(:custom_emoji).where(target_type: 'CustomEmoji', human_identifier: nil).find_each do |log| next if log.custom_emoji.nil? + log.update_attribute('human_identifier', log.custom_emoji.shortcode) end AdminActionLog.includes(:canonical_email_block).where(target_type: 'CanonicalEmailBlock', human_identifier: nil).find_each do |log| next if log.canonical_email_block.nil? + log.update_attribute('human_identifier', log.canonical_email_block.canonical_email_hash) end AdminActionLog.includes(appeal: :account).where(target_type: 'Appeal', human_identifier: nil).find_each do |log| next if log.appeal.nil? + log.update_attribute('human_identifier', log.appeal.account.acct) log.update_attribute('route_param', log.appeal.account_warning_id) end diff --git a/db/post_migrate/20221206114142_backfill_admin_action_logs_again.rb b/db/post_migrate/20221206114142_backfill_admin_action_logs_again.rb index 42b7f3625..9c7ac7120 100644 --- a/db/post_migrate/20221206114142_backfill_admin_action_logs_again.rb +++ b/db/post_migrate/20221206114142_backfill_admin_action_logs_again.rb @@ -79,11 +79,13 @@ class BackfillAdminActionLogsAgain < ActiveRecord::Migration[6.1] safety_assured do AdminActionLog.includes(:account).where(target_type: 'Account', human_identifier: nil).find_each do |log| next if log.account.nil? + log.update_attribute('human_identifier', log.account.acct) end AdminActionLog.includes(user: :account).where(target_type: 'User', human_identifier: nil).find_each do |log| next if log.user.nil? + log.update_attribute('human_identifier', log.user.account.acct) log.update_attribute('route_param', log.user.account_id) end @@ -92,57 +94,68 @@ class BackfillAdminActionLogsAgain < ActiveRecord::Migration[6.1] AdminActionLog.includes(:domain_block).where(target_type: 'DomainBlock').find_each do |log| next if log.domain_block.nil? + log.update_attribute('human_identifier', log.domain_block.domain) end AdminActionLog.includes(:domain_allow).where(target_type: 'DomainAllow').find_each do |log| next if log.domain_allow.nil? + log.update_attribute('human_identifier', log.domain_allow.domain) end AdminActionLog.includes(:email_domain_block).where(target_type: 'EmailDomainBlock').find_each do |log| next if log.email_domain_block.nil? + log.update_attribute('human_identifier', log.email_domain_block.domain) end AdminActionLog.includes(:unavailable_domain).where(target_type: 'UnavailableDomain').find_each do |log| next if log.unavailable_domain.nil? + log.update_attribute('human_identifier', log.unavailable_domain.domain) end AdminActionLog.includes(status: :account).where(target_type: 'Status', human_identifier: nil).find_each do |log| next if log.status.nil? + log.update_attribute('human_identifier', log.status.account.acct) log.update_attribute('permalink', log.status.uri) end AdminActionLog.includes(account_warning: :account).where(target_type: 'AccountWarning', human_identifier: nil).find_each do |log| next if log.account_warning.nil? + log.update_attribute('human_identifier', log.account_warning.account.acct) end AdminActionLog.includes(:announcement).where(target_type: 'Announcement', human_identifier: nil).find_each do |log| next if log.announcement.nil? + log.update_attribute('human_identifier', log.announcement.text) end AdminActionLog.includes(:ip_block).where(target_type: 'IpBlock', human_identifier: nil).find_each do |log| next if log.ip_block.nil? + log.update_attribute('human_identifier', "#{log.ip_block.ip}/#{log.ip_block.ip.prefix}") end AdminActionLog.includes(:custom_emoji).where(target_type: 'CustomEmoji', human_identifier: nil).find_each do |log| next if log.custom_emoji.nil? + log.update_attribute('human_identifier', log.custom_emoji.shortcode) end AdminActionLog.includes(:canonical_email_block).where(target_type: 'CanonicalEmailBlock', human_identifier: nil).find_each do |log| next if log.canonical_email_block.nil? + log.update_attribute('human_identifier', log.canonical_email_block.canonical_email_hash) end AdminActionLog.includes(appeal: :account).where(target_type: 'Appeal', human_identifier: nil).find_each do |log| next if log.appeal.nil? + log.update_attribute('human_identifier', log.appeal.account.acct) log.update_attribute('route_param', log.appeal.account_warning_id) end diff --git a/lib/mastodon/domains_cli.rb b/lib/mastodon/domains_cli.rb index f24a54e7e..41ea5b152 100644 --- a/lib/mastodon/domains_cli.rb +++ b/lib/mastodon/domains_cli.rb @@ -148,6 +148,7 @@ module Mastodon begin Request.new(:get, "https://#{domain}/api/v1/instance").perform do |res| next unless res.code == 200 + stats[domain] = Oj.load(res.to_s) end @@ -161,6 +162,7 @@ module Mastodon Request.new(:get, "https://#{domain}/api/v1/instance/activity").perform do |res| next unless res.code == 200 + stats[domain]['activity'] = Oj.load(res.to_s) end rescue StandardError diff --git a/lib/sanitize_ext/sanitize_config.rb b/lib/sanitize_ext/sanitize_config.rb index d5e62897f..dc39e9c90 100644 --- a/lib/sanitize_ext/sanitize_config.rb +++ b/lib/sanitize_ext/sanitize_config.rb @@ -72,7 +72,7 @@ class Sanitize elements: %w(p br span a), attributes: { - 'a' => %w(href rel class), + 'a' => %w(href rel class), 'span' => %w(class), }, @@ -98,17 +98,17 @@ class Sanitize attributes: merge( RELAXED[:attributes], - 'audio' => %w(controls), - 'embed' => %w(height src type width), + 'audio' => %w(controls), + 'embed' => %w(height src type width), 'iframe' => %w(allowfullscreen frameborder height scrolling src width), 'source' => %w(src type), - 'video' => %w(controls height loop width), - 'div' => [:data] + 'video' => %w(controls height loop width), + 'div' => [:data] ), protocols: merge( RELAXED[:protocols], - 'embed' => { 'src' => HTTP_PROTOCOLS }, + 'embed' => { 'src' => HTTP_PROTOCOLS }, 'iframe' => { 'src' => HTTP_PROTOCOLS }, 'source' => { 'src' => HTTP_PROTOCOLS } ) diff --git a/lib/tasks/auto_annotate_models.rake b/lib/tasks/auto_annotate_models.rake index a374e33ad..4b5997920 100644 --- a/lib/tasks/auto_annotate_models.rake +++ b/lib/tasks/auto_annotate_models.rake @@ -3,42 +3,42 @@ if Rails.env.development? task :set_annotation_options do Annotate.set_defaults( - 'routes' => 'false', - 'models' => 'true', - 'position_in_routes' => 'before', - 'position_in_class' => 'before', - 'position_in_test' => 'before', - 'position_in_fixture' => 'before', - 'position_in_factory' => 'before', - 'position_in_serializer' => 'before', - 'show_foreign_keys' => 'false', - 'show_indexes' => 'false', - 'simple_indexes' => 'false', - 'model_dir' => 'app/models', - 'root_dir' => '', - 'include_version' => 'false', - 'require' => '', - 'exclude_tests' => 'true', - 'exclude_fixtures' => 'true', - 'exclude_factories' => 'true', - 'exclude_serializers' => 'true', - 'exclude_scaffolds' => 'true', - 'exclude_controllers' => 'true', - 'exclude_helpers' => 'true', - 'ignore_model_sub_dir' => 'false', - 'ignore_columns' => nil, - 'ignore_routes' => nil, - 'ignore_unknown_models' => 'false', + 'routes' => 'false', + 'models' => 'true', + 'position_in_routes' => 'before', + 'position_in_class' => 'before', + 'position_in_test' => 'before', + 'position_in_fixture' => 'before', + 'position_in_factory' => 'before', + 'position_in_serializer' => 'before', + 'show_foreign_keys' => 'false', + 'show_indexes' => 'false', + 'simple_indexes' => 'false', + 'model_dir' => 'app/models', + 'root_dir' => '', + 'include_version' => 'false', + 'require' => '', + 'exclude_tests' => 'true', + 'exclude_fixtures' => 'true', + 'exclude_factories' => 'true', + 'exclude_serializers' => 'true', + 'exclude_scaffolds' => 'true', + 'exclude_controllers' => 'true', + 'exclude_helpers' => 'true', + 'ignore_model_sub_dir' => 'false', + 'ignore_columns' => nil, + 'ignore_routes' => nil, + 'ignore_unknown_models' => 'false', 'hide_limit_column_types' => 'integer,boolean', - 'skip_on_db_migrate' => 'false', - 'format_bare' => 'true', - 'format_rdoc' => 'false', - 'format_markdown' => 'false', - 'sort' => 'false', - 'force' => 'false', - 'trace' => 'false', - 'wrapper_open' => nil, - 'wrapper_close' => nil + 'skip_on_db_migrate' => 'false', + 'format_bare' => 'true', + 'format_rdoc' => 'false', + 'format_markdown' => 'false', + 'sort' => 'false', + 'force' => 'false', + 'trace' => 'false', + 'wrapper_open' => nil, + 'wrapper_close' => nil ) end diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake index 179a730bc..f919ba989 100644 --- a/lib/tasks/mastodon.rake +++ b/lib/tasks/mastodon.rake @@ -399,14 +399,14 @@ namespace :mastodon do end ActionMailer::Base.smtp_settings = { - port: env['SMTP_PORT'], - address: env['SMTP_SERVER'], - user_name: env['SMTP_LOGIN'].presence, - password: env['SMTP_PASSWORD'].presence, - domain: env['LOCAL_DOMAIN'], - authentication: env['SMTP_AUTH_METHOD'] == 'none' ? nil : env['SMTP_AUTH_METHOD'] || :plain, - openssl_verify_mode: env['SMTP_OPENSSL_VERIFY_MODE'], - enable_starttls: enable_starttls, + port: env['SMTP_PORT'], + address: env['SMTP_SERVER'], + user_name: env['SMTP_LOGIN'].presence, + password: env['SMTP_PASSWORD'].presence, + domain: env['LOCAL_DOMAIN'], + authentication: env['SMTP_AUTH_METHOD'] == 'none' ? nil : env['SMTP_AUTH_METHOD'] || :plain, + openssl_verify_mode: env['SMTP_OPENSSL_VERIFY_MODE'], + enable_starttls: enable_starttls, enable_starttls_auto: enable_starttls_auto, } diff --git a/spec/controllers/api/v1/accounts/statuses_controller_spec.rb b/spec/controllers/api/v1/accounts/statuses_controller_spec.rb index 4630fac90..e57c37179 100644 --- a/spec/controllers/api/v1/accounts/statuses_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/statuses_controller_spec.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require 'rails_helper' describe Api::V1::Accounts::StatusesController do diff --git a/spec/models/admin/account_action_spec.rb b/spec/models/admin/account_action_spec.rb index 4516df2c2..7248356e5 100644 --- a/spec/models/admin/account_action_spec.rb +++ b/spec/models/admin/account_action_spec.rb @@ -12,9 +12,9 @@ RSpec.describe Admin::AccountAction, type: :model do before do account_action.assign_attributes( - type: type, + type: type, current_account: account, - target_account: target_account + target_account: target_account ) end diff --git a/spec/models/concerns/account_interactions_spec.rb b/spec/models/concerns/account_interactions_spec.rb index ed3fc056b..50ff0b149 100644 --- a/spec/models/concerns/account_interactions_spec.rb +++ b/spec/models/concerns/account_interactions_spec.rb @@ -149,8 +149,8 @@ describe AccountInteractions do let(:mute) do Fabricate(:mute, - account: account, - target_account: target_account, + account: account, + target_account: target_account, hide_notifications: hide_notifications) end diff --git a/spec/models/tag_spec.rb b/spec/models/tag_spec.rb index 7043449c5..4d6e5c380 100644 --- a/spec/models/tag_spec.rb +++ b/spec/models/tag_spec.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require 'rails_helper' RSpec.describe Tag do -- cgit From 9909b4b653d2f1cef662211a4b8e0b02cbb42fc1 Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Mon, 20 Feb 2023 13:20:56 -0500 Subject: Autofix Rubocop Rails/WhereEquals (#23759) --- .rubocop_todo.yml | 7 ------- app/models/announcement.rb | 2 +- app/models/status.rb | 2 +- 3 files changed, 2 insertions(+), 9 deletions(-) (limited to 'app/models') diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index bb214a70b..2a272b095 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1916,13 +1916,6 @@ Rails/UnusedIgnoredColumns: - 'app/models/status_edit.rb' - 'app/models/user.rb' -# Offense count: 2 -# This cop supports unsafe autocorrection (--autocorrect-all). -Rails/WhereEquals: - Exclude: - - 'app/models/announcement.rb' - - 'app/models/status.rb' - # Offense count: 61 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle. diff --git a/app/models/announcement.rb b/app/models/announcement.rb index 898bf3efa..339f5ae70 100644 --- a/app/models/announcement.rb +++ b/app/models/announcement.rb @@ -20,7 +20,7 @@ class Announcement < ApplicationRecord scope :unpublished, -> { where(published: false) } scope :published, -> { where(published: true) } - scope :without_muted, ->(account) { joins("LEFT OUTER JOIN announcement_mutes ON announcement_mutes.announcement_id = announcements.id AND announcement_mutes.account_id = #{account.id}").where('announcement_mutes.id IS NULL') } + scope :without_muted, ->(account) { joins("LEFT OUTER JOIN announcement_mutes ON announcement_mutes.announcement_id = announcements.id AND announcement_mutes.account_id = #{account.id}").where(announcement_mutes: { id: nil }) } scope :chronological, -> { order(Arel.sql('COALESCE(announcements.starts_at, announcements.scheduled_at, announcements.published_at, announcements.created_at) ASC')) } scope :reverse_chronological, -> { order(Arel.sql('COALESCE(announcements.starts_at, announcements.scheduled_at, announcements.published_at, announcements.created_at) DESC')) } diff --git a/app/models/status.rb b/app/models/status.rb index 2eb47d72c..e7ea191a8 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -95,7 +95,7 @@ class Status < ApplicationRecord scope :local, -> { where(local: true).or(where(uri: nil)) } scope :with_accounts, ->(ids) { where(id: ids).includes(:account) } scope :without_replies, -> { where('statuses.reply = FALSE OR statuses.in_reply_to_account_id = statuses.account_id') } - scope :without_reblogs, -> { where('statuses.reblog_of_id IS NULL') } + scope :without_reblogs, -> { where(statuses: { reblog_of_id: nil }) } scope :with_public_visibility, -> { where(visibility: :public) } scope :tagged_with, ->(tag_ids) { joins(:statuses_tags).where(statuses_tags: { tag_id: tag_ids }) } scope :excluding_silenced_accounts, -> { left_outer_joins(:account).where(accounts: { silenced_at: nil }) } -- cgit From f682478de8b5a6e0b524bfca88f3469fd098d64c Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 22 Feb 2023 11:53:13 +0100 Subject: Fix inefficiency when searching accounts per username in admin interface (#23801) --- app/models/account.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/account.rb b/app/models/account.rb index 09c450f2a..1ff083e54 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -108,7 +108,7 @@ class Account < ApplicationRecord scope :bots, -> { where(actor_type: %w(Application Service)) } scope :groups, -> { where(actor_type: 'Group') } scope :alphabetic, -> { order(domain: :asc, username: :asc) } - scope :matches_username, ->(value) { where(arel_table[:username].matches("#{value}%")) } + scope :matches_username, ->(value) { where('lower((username)::text) LIKE lower(?)', "#{value}%") } scope :matches_display_name, ->(value) { where(arel_table[:display_name].matches("#{value}%")) } scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) } scope :without_unapproved, -> { left_outer_joins(:user).remote.or(left_outer_joins(:user).merge(User.approved.confirmed)) } -- cgit From 4bb39ac3c37fc5319898300c1067bb47443d6041 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 27 Feb 2023 03:31:15 -0500 Subject: Fix single-record invalid condition on PollVote (#23810) --- app/models/poll_vote.rb | 1 + app/validators/vote_validator.rb | 26 ++++++++++++++++++--- spec/models/poll_vote_spec.rb | 49 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/models/poll_vote.rb b/app/models/poll_vote.rb index 00eaedd12..92d74a6db 100644 --- a/app/models/poll_vote.rb +++ b/app/models/poll_vote.rb @@ -23,6 +23,7 @@ class PollVote < ApplicationRecord after_create_commit :increment_counter_cache delegate :local?, to: :account + delegate :multiple?, :expired?, to: :poll, prefix: true def object_type :vote diff --git a/app/validators/vote_validator.rb b/app/validators/vote_validator.rb index b1692562d..9c55f9ab6 100644 --- a/app/validators/vote_validator.rb +++ b/app/validators/vote_validator.rb @@ -2,13 +2,13 @@ class VoteValidator < ActiveModel::Validator def validate(vote) - vote.errors.add(:base, I18n.t('polls.errors.expired')) if vote.poll.expired? + vote.errors.add(:base, I18n.t('polls.errors.expired')) if vote.poll_expired? vote.errors.add(:base, I18n.t('polls.errors.invalid_choice')) if invalid_choice?(vote) - if vote.poll.multiple? && vote.poll.votes.where(account: vote.account, choice: vote.choice).exists? + if vote.poll_multiple? && already_voted_for_same_choice_on_multiple_poll?(vote) vote.errors.add(:base, I18n.t('polls.errors.already_voted')) - elsif !vote.poll.multiple? && vote.poll.votes.where(account: vote.account).exists? + elsif !vote.poll_multiple? && already_voted_on_non_multiple_poll?(vote) vote.errors.add(:base, I18n.t('polls.errors.already_voted')) end end @@ -18,4 +18,24 @@ class VoteValidator < ActiveModel::Validator def invalid_choice?(vote) vote.choice.negative? || vote.choice >= vote.poll.options.size end + + def already_voted_for_same_choice_on_multiple_poll?(vote) + if vote.persisted? + account_votes_on_same_poll(vote).where(choice: vote.choice).where.not(poll_votes: { id: vote }).exists? + else + account_votes_on_same_poll(vote).where(choice: vote.choice).exists? + end + end + + def already_voted_on_non_multiple_poll?(vote) + if vote.persisted? + account_votes_on_same_poll(vote).where.not(poll_votes: { id: vote }).exists? + else + account_votes_on_same_poll(vote).exists? + end + end + + def account_votes_on_same_poll(vote) + vote.poll.votes.where(account: vote.account) + end end diff --git a/spec/models/poll_vote_spec.rb b/spec/models/poll_vote_spec.rb index 563f34699..6886a82aa 100644 --- a/spec/models/poll_vote_spec.rb +++ b/spec/models/poll_vote_spec.rb @@ -10,4 +10,53 @@ RSpec.describe PollVote, type: :model do expect(poll_vote.object_type).to eq :vote end end + + describe 'validations' do + context 'with a vote on an expired poll' do + it 'marks the vote invalid' do + poll = Fabricate.build(:poll, expires_at: 30.days.ago) + + vote = Fabricate.build(:poll_vote, poll: poll) + expect(vote).to_not be_valid + end + end + + context 'with invalid choices' do + it 'marks vote invalid with negative choice' do + poll = Fabricate.build(:poll) + + vote = Fabricate.build(:poll_vote, poll: poll, choice: -100) + expect(vote).to_not be_valid + end + + it 'marks vote invalid with choice in excess of options' do + poll = Fabricate.build(:poll, options: %w(a b c)) + + vote = Fabricate.build(:poll_vote, poll: poll, choice: 10) + expect(vote).to_not be_valid + end + end + + context 'with a poll where multiple is true' do + it 'does not allow a second vote on same choice from same account' do + poll = Fabricate(:poll, multiple: true, options: %w(a b c)) + first_vote = Fabricate(:poll_vote, poll: poll, choice: 1) + expect(first_vote).to be_valid + + second_vote = Fabricate.build(:poll_vote, account: first_vote.account, poll: poll, choice: 1) + expect(second_vote).to_not be_valid + end + end + + context 'with a poll where multiple is false' do + it 'does not allow a second vote from same account' do + poll = Fabricate(:poll, multiple: false, options: %w(a b c)) + first_vote = Fabricate(:poll_vote, poll: poll) + expect(first_vote).to be_valid + + second_vote = Fabricate.build(:poll_vote, account: first_vote.account, poll: poll) + expect(second_vote).to_not be_valid + end + end + end end -- cgit From af578e8ce0aabdbe9c0cd3d72d6fa2cc30b7fc66 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 2 Mar 2023 10:21:04 -0500 Subject: Fix deprecation warning about merging conditions (#23618) --- app/models/account_filter.rb | 24 +++++++++++++++++++++--- spec/models/account_filter_spec.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/models/account_filter.rb b/app/models/account_filter.rb index d27bb46fc..1666ea883 100644 --- a/app/models/account_filter.rb +++ b/app/models/account_filter.rb @@ -17,13 +17,13 @@ class AccountFilter attr_reader :params def initialize(params) - @params = params + @params = params.to_h.symbolize_keys end def results scope = Account.includes(:account_stat, user: [:ips, :invite_request]).without_instance_actor.reorder(nil) - params.each do |key, value| + relevant_params.each do |key, value| next if key.to_s == 'page' scope.merge!(scope_for(key, value)) if value.present? @@ -34,6 +34,16 @@ class AccountFilter private + def relevant_params + params.tap do |args| + args.delete(:origin) if origin_is_remote_and_domain_present? + end + end + + def origin_is_remote_and_domain_present? + params[:origin] == 'remote' && params[:by_domain].present? + end + def scope_for(key, value) case key.to_s when 'origin' @@ -94,7 +104,15 @@ class AccountFilter def order_scope(value) case value.to_s when 'active' - accounts_with_users.left_joins(:account_stat).order(Arel.sql('coalesce(users.current_sign_in_at, account_stats.last_status_at, to_timestamp(0)) desc, accounts.id desc')) + accounts_with_users + .left_joins(:account_stat) + .order( + Arel.sql( + <<~SQL.squish + COALESCE(users.current_sign_in_at, account_stats.last_status_at, to_timestamp(0)) DESC, accounts.id DESC + SQL + ) + ) when 'recent' Account.recent else diff --git a/spec/models/account_filter_spec.rb b/spec/models/account_filter_spec.rb index 853d20a0c..3032260fe 100644 --- a/spec/models/account_filter_spec.rb +++ b/spec/models/account_filter_spec.rb @@ -18,4 +18,30 @@ describe AccountFilter do expect { filter.results }.to raise_error(/wrong/) end end + + describe 'with origin and by_domain interacting' do + let!(:local_account) { Fabricate(:account, domain: nil) } + let!(:remote_account_one) { Fabricate(:account, domain: 'example.org') } + let(:remote_account_two) { Fabricate(:account, domain: 'other.domain') } + + it 'works with domain first and origin remote' do + filter = described_class.new(by_domain: 'example.org', origin: 'remote') + expect(filter.results).to match_array [remote_account_one] + end + + it 'works with domain last and origin remote' do + filter = described_class.new(origin: 'remote', by_domain: 'example.org') + expect(filter.results).to match_array [remote_account_one] + end + + it 'works with domain first and origin local' do + filter = described_class.new(by_domain: 'example.org', origin: 'local') + expect(filter.results).to match_array [local_account] + end + + it 'works with domain last and origin local' do + filter = described_class.new(origin: 'local', by_domain: 'example.org') + expect(filter.results).to match_array [remote_account_one] + end + end end -- cgit From c2a046ded1d47e2504df05568e34bc6a2a6dc810 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 3 Mar 2023 20:25:15 +0100 Subject: Fix “Remove all followers from the selected domains” being more destructive than it claims (#23805) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/relationships_controller.rb | 4 ++-- app/models/form/account_batch.rb | 10 ++++------ .../remove_domains_from_followers_service.rb | 23 ++++++++++++++++++++++ app/views/relationships/show.html.haml | 2 +- spec/controllers/relationships_controller_spec.rb | 11 ++++++++++- 5 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 app/services/remove_domains_from_followers_service.rb (limited to 'app/models') diff --git a/app/controllers/relationships_controller.rb b/app/controllers/relationships_controller.rb index 96cce55e9..baa34da22 100644 --- a/app/controllers/relationships_controller.rb +++ b/app/controllers/relationships_controller.rb @@ -60,8 +60,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/models/form/account_batch.rb b/app/models/form/account_batch.rb index 473622edf..5a7fc7ed1 100644 --- a/app/models/form/account_batch.rb +++ b/app/models/form/account_batch.rb @@ -17,8 +17,8 @@ class Form::AccountBatch unfollow! when 'remove_from_followers' remove_from_followers! - when 'block_domains' - block_domains! + when 'remove_domains_from_followers' + remove_domains_from_followers! when 'approve' approve! when 'reject' @@ -50,10 +50,8 @@ class Form::AccountBatch RemoveFromFollowersService.new.call(current_account, account_ids) end - def block_domains! - AfterAccountDomainBlockWorker.push_bulk(account_domains) do |domain| - [current_account.id, domain] - end + def remove_domains_from_followers! + RemoveDomainsFromFollowersService.new.call(current_account, account_domains) end def account_domains diff --git a/app/services/remove_domains_from_followers_service.rb b/app/services/remove_domains_from_followers_service.rb new file mode 100644 index 000000000..d76763409 --- /dev/null +++ b/app/services/remove_domains_from_followers_service.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class RemoveDomainsFromFollowersService < BaseService + include Payloadable + + def call(source_account, target_domains) + source_account.passive_relationships.where(account_id: Account.where(domain: target_domains)).find_each do |follow| + follow.destroy + + create_notification(follow) if source_account.local? && !follow.account.local? && follow.account.activitypub? + end + end + + private + + def create_notification(follow) + ActivityPub::DeliveryWorker.perform_async(build_json(follow), follow.target_account_id, follow.account.inbox_url) + end + + def build_json(follow) + Oj.dump(serialize_payload(follow, ActivityPub::RejectFollowSerializer)) + end +end diff --git a/app/views/relationships/show.html.haml b/app/views/relationships/show.html.haml index 2899cd514..f08e9c1df 100644 --- a/app/views/relationships/show.html.haml +++ b/app/views/relationships/show.html.haml @@ -48,7 +48,7 @@ = f.button safe_join([fa_icon('trash'), t('relationships.remove_selected_followers')]), name: :remove_from_followers, class: 'table-action-link', type: :submit, data: { confirm: t('relationships.confirm_remove_selected_followers') } unless following_relationship? - = f.button safe_join([fa_icon('trash'), t('relationships.remove_selected_domains')]), name: :block_domains, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } if followed_by_relationship? + = f.button safe_join([fa_icon('trash'), t('relationships.remove_selected_domains')]), name: :remove_domains_from_followers, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } if followed_by_relationship? .batch-table__body - if @accounts.empty? = nothing_here 'nothing-here--under-tabs' diff --git a/spec/controllers/relationships_controller_spec.rb b/spec/controllers/relationships_controller_spec.rb index 39f455e03..53a5daa51 100644 --- a/spec/controllers/relationships_controller_spec.rb +++ b/spec/controllers/relationships_controller_spec.rb @@ -58,7 +58,7 @@ describe RelationshipsController do end context 'when select parameter is provided' do - subject { patch :update, params: { form_account_batch: { account_ids: [poopfeast.id] }, block_domains: '' } } + subject { patch :update, params: { form_account_batch: { account_ids: [poopfeast.id] }, remove_domains_from_followers: '' } } it 'soft-blocks followers from selected domains' do poopfeast.follow!(user.account) @@ -69,6 +69,15 @@ describe RelationshipsController do expect(poopfeast.following?(user.account)).to be false end + it 'does not unfollow users from selected domains' do + user.account.follow!(poopfeast) + + sign_in user, scope: :user + subject + + expect(user.account.following?(poopfeast)).to be true + end + include_examples 'authenticate user' include_examples 'redirects back to followers page' end -- cgit From f8bb4d0d6b1050de481187e9f034b8bbb649d931 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 3 Mar 2023 20:36:18 +0100 Subject: Fix server error when failing to follow back followers from `/relationships` (#23787) --- app/controllers/relationships_controller.rb | 2 ++ app/models/form/account_batch.rb | 6 ++++++ config/locales/en.yml | 1 + 3 files changed, 9 insertions(+) (limited to 'app/models') diff --git a/app/controllers/relationships_controller.rb b/app/controllers/relationships_controller.rb index baa34da22..de5dc5879 100644 --- a/app/controllers/relationships_controller.rb +++ b/app/controllers/relationships_controller.rb @@ -19,6 +19,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 diff --git a/app/models/form/account_batch.rb b/app/models/form/account_batch.rb index 5a7fc7ed1..6a05f8163 100644 --- a/app/models/form/account_batch.rb +++ b/app/models/form/account_batch.rb @@ -35,9 +35,15 @@ class Form::AccountBatch private def follow! + error = nil + accounts.each do |target_account| FollowService.new.call(current_account, target_account) + rescue Mastodon::NotPermittedError, ActiveRecord::RecordNotFound => e + error ||= e end + + raise error if error.present? end def unfollow! diff --git a/config/locales/en.yml b/config/locales/en.yml index 9f8ba7ce7..d142962b5 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1408,6 +1408,7 @@ en: confirm_remove_selected_followers: Are you sure you want to remove selected followers? confirm_remove_selected_follows: Are you sure you want to remove selected follows? dormant: Dormant + follow_failure: Could not follow some of the selected accounts. follow_selected_followers: Follow selected followers followers: Followers following: Following -- cgit From 6b16b77ab0f347e688f009c5a04961142b8dd203 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 3 Mar 2023 20:45:55 +0100 Subject: Fix external authentication not running onboarding code for new users (#23458) --- app/models/concerns/omniauthable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/concerns/omniauthable.rb b/app/models/concerns/omniauthable.rb index b0aa5be6f..41eae215b 100644 --- a/app/models/concerns/omniauthable.rb +++ b/app/models/concerns/omniauthable.rb @@ -61,7 +61,7 @@ module Omniauthable user.account.avatar_remote_url = nil end - user.skip_confirmation! if email_is_verified + user.confirm! if email_is_verified user.save! user end -- cgit From 5a8c651e8f0252c7135042e79396f782361302d9 Mon Sep 17 00:00:00 2001 From: Christian Schmidt Date: Fri, 3 Mar 2023 21:06:31 +0100 Subject: Only offer translation for supported languages (#23879) --- .rubocop.yml | 4 + .../mastodon/components/status_content.jsx | 4 +- app/javascript/mastodon/initial_state.js | 2 - app/lib/translation_service.rb | 4 + app/lib/translation_service/deepl.rb | 46 +++++++--- app/lib/translation_service/libre_translate.rb | 38 +++++--- app/models/status.rb | 10 +++ app/serializers/initial_state_serializer.rb | 1 - app/serializers/rest/status_serializer.rb | 6 +- app/services/translate_status_service.rb | 2 +- spec/lib/translation_service/deepl_spec.rb | 100 +++++++++++++++++++++ .../translation_service/libre_translate_spec.rb | 71 +++++++++++++++ spec/models/status_spec.rb | 79 ++++++++++++++++ 13 files changed, 336 insertions(+), 31 deletions(-) create mode 100644 spec/lib/translation_service/deepl_spec.rb create mode 100644 spec/lib/translation_service/libre_translate_spec.rb (limited to 'app/models') diff --git a/.rubocop.yml b/.rubocop.yml index 27d778edf..0a41c54b9 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -97,6 +97,10 @@ Rails/Exit: - 'lib/mastodon/cli_helper.rb' - 'lib/cli.rb' +RSpec/FilePath: + CustomTransform: + DeepL: deepl + RSpec/NotToNot: EnforcedStyle: to_not diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx index a1c38171f..f9c9fe079 100644 --- a/app/javascript/mastodon/components/status_content.jsx +++ b/app/javascript/mastodon/components/status_content.jsx @@ -6,7 +6,7 @@ import { Link } from 'react-router-dom'; import classnames from 'classnames'; import PollContainer from 'mastodon/containers/poll_container'; import Icon from 'mastodon/components/icon'; -import { autoPlayGif, languages as preloadedLanguages, translationEnabled } from 'mastodon/initial_state'; +import { autoPlayGif, languages as preloadedLanguages } from 'mastodon/initial_state'; const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top) @@ -220,7 +220,7 @@ class StatusContent extends React.PureComponent { const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden; const renderReadMore = this.props.onClick && status.get('collapsed'); - const renderTranslate = translationEnabled && this.context.identity.signedIn && this.props.onTranslate && ['public', 'unlisted'].includes(status.get('visibility')) && status.get('contentHtml').length > 0 && status.get('language') !== null && intl.locale !== status.get('language'); + const renderTranslate = this.props.onTranslate && status.get('translatable'); const content = { __html: status.get('translation') ? status.getIn(['translation', 'content']) : status.get('contentHtml') }; const spoilerContent = { __html: status.get('spoilerHtml') }; diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js index d04c4a42d..919e0fc28 100644 --- a/app/javascript/mastodon/initial_state.js +++ b/app/javascript/mastodon/initial_state.js @@ -80,7 +80,6 @@ * @property {boolean} use_blurhash * @property {boolean=} use_pending_items * @property {string} version - * @property {boolean} translation_enabled */ /** @@ -132,7 +131,6 @@ export const unfollowModal = getMeta('unfollow_modal'); export const useBlurhash = getMeta('use_blurhash'); export const usePendingItems = getMeta('use_pending_items'); export const version = getMeta('version'); -export const translationEnabled = getMeta('translation_enabled'); export const languages = initialState?.languages; export const statusPageUrl = getMeta('status_page_url'); diff --git a/app/lib/translation_service.rb b/app/lib/translation_service.rb index 285f30939..5ff93674a 100644 --- a/app/lib/translation_service.rb +++ b/app/lib/translation_service.rb @@ -21,6 +21,10 @@ class TranslationService ENV['DEEPL_API_KEY'].present? || ENV['LIBRE_TRANSLATE_ENDPOINT'].present? end + def supported?(_source_language, _target_language) + false + end + def translate(_text, _source_language, _target_language) raise NotImplementedError end diff --git a/app/lib/translation_service/deepl.rb b/app/lib/translation_service/deepl.rb index 151d33d90..deff95a1d 100644 --- a/app/lib/translation_service/deepl.rb +++ b/app/lib/translation_service/deepl.rb @@ -11,33 +11,53 @@ class TranslationService::DeepL < TranslationService end def translate(text, source_language, target_language) - request(text, source_language, target_language).perform do |res| + form = { text: text, source_lang: source_language&.upcase, target_lang: target_language, tag_handling: 'html' } + request(:post, '/v2/translate', form: form) do |res| + transform_response(res.body_with_limit) + end + end + + def supported?(source_language, target_language) + source_language.in?(languages('source')) && target_language.in?(languages('target')) + end + + private + + def languages(type) + Rails.cache.fetch("translation_service/deepl/languages/#{type}", expires_in: 7.days, race_condition_ttl: 1.minute) do + request(:get, "/v2/languages?type=#{type}") do |res| + # In DeepL, EN and PT are deprecated in favor of EN-GB/EN-US and PT-BR/PT-PT, so + # they are supported but not returned by the API. + extra = type == 'source' ? [nil] : %w(en pt) + languages = Oj.load(res.body_with_limit).map { |language| language['language'].downcase } + + languages + extra + end + end + end + + def request(verb, path, **options) + req = Request.new(verb, "#{base_url}#{path}", **options) + req.add_headers(Authorization: "DeepL-Auth-Key #{@api_key}") + req.perform do |res| case res.code when 429 raise TooManyRequestsError when 456 raise QuotaExceededError when 200...300 - transform_response(res.body_with_limit) + yield res else raise UnexpectedResponseError end end end - private - - def request(text, source_language, target_language) - req = Request.new(:post, endpoint_url, form: { text: text, source_lang: source_language&.upcase, target_lang: target_language, tag_handling: 'html' }) - req.add_headers(Authorization: "DeepL-Auth-Key #{@api_key}") - req - end - - def endpoint_url + def base_url if @plan == 'free' - 'https://api-free.deepl.com/v2/translate' + 'https://api-free.deepl.com' else - 'https://api.deepl.com/v2/translate' + 'https://api.deepl.com' end end diff --git a/app/lib/translation_service/libre_translate.rb b/app/lib/translation_service/libre_translate.rb index 4ebe21e45..743e4d77f 100644 --- a/app/lib/translation_service/libre_translate.rb +++ b/app/lib/translation_service/libre_translate.rb @@ -9,29 +9,45 @@ class TranslationService::LibreTranslate < TranslationService end def translate(text, source_language, target_language) - request(text, source_language, target_language).perform do |res| + body = Oj.dump(q: text, source: source_language.presence || 'auto', target: target_language, format: 'html', api_key: @api_key) + request(:post, '/translate', body: body) do |res| + transform_response(res.body_with_limit, source_language) + end + end + + def supported?(source_language, target_language) + languages.key?(source_language) && languages[source_language].include?(target_language) + end + + private + + def languages + Rails.cache.fetch('translation_service/libre_translate/languages', expires_in: 7.days, race_condition_ttl: 1.minute) do + request(:get, '/languages') do |res| + languages = Oj.load(res.body_with_limit).to_h { |language| [language['code'], language['targets']] } + languages[nil] = languages.values.flatten.uniq + languages + end + end + end + + def request(verb, path, **options) + req = Request.new(verb, "#{@base_url}#{path}", allow_local: true, **options) + req.add_headers('Content-Type': 'application/json') + req.perform do |res| case res.code when 429 raise TooManyRequestsError when 403 raise QuotaExceededError when 200...300 - transform_response(res.body_with_limit, source_language) + yield res else raise UnexpectedResponseError end end end - private - - def request(text, source_language, target_language) - body = Oj.dump(q: text, source: source_language.presence || 'auto', target: target_language, format: 'html', api_key: @api_key) - req = Request.new(:post, "#{@base_url}/translate", body: body, allow_local: true) - req.add_headers('Content-Type': 'application/json') - req - end - def transform_response(str, source_language) json = Oj.load(str, mode: :strict) diff --git a/app/models/status.rb b/app/models/status.rb index e7ea191a8..dd7ac2edb 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -232,6 +232,16 @@ class Status < ApplicationRecord public_visibility? || unlisted_visibility? end + def translatable? + translate_target_locale = I18n.locale.to_s.split(/[_-]/).first + + distributable? && + content.present? && + language != translate_target_locale && + TranslationService.configured? && + TranslationService.configured.supported?(language, translate_target_locale) + end + alias sign? distributable? def with_media? diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 7905444e9..769ba653e 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -30,7 +30,6 @@ class InitialStateSerializer < ActiveModel::Serializer timeline_preview: Setting.timeline_preview, activity_api_enabled: Setting.activity_api_enabled, single_user_mode: Rails.configuration.x.single_user_mode, - translation_enabled: TranslationService.configured?, trends_as_landing_page: Setting.trends_as_landing_page, status_page_url: Setting.status_page_url, } diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index e0b8f32a6..a422f5b25 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -4,7 +4,7 @@ class REST::StatusSerializer < ActiveModel::Serializer include FormattingHelper attributes :id, :created_at, :in_reply_to_id, :in_reply_to_account_id, - :sensitive, :spoiler_text, :visibility, :language, + :sensitive, :spoiler_text, :visibility, :language, :translatable, :uri, :url, :replies_count, :reblogs_count, :favourites_count, :edited_at @@ -50,6 +50,10 @@ class REST::StatusSerializer < ActiveModel::Serializer object.account.user_shows_application? || (current_user? && current_user.account_id == object.account_id) end + def translatable + current_user? && object.translatable? + end + def visibility # This visibility is masked behind "private" # to avoid API changes because there are no diff --git a/app/services/translate_status_service.rb b/app/services/translate_status_service.rb index 539a0d9db..92d8b62a0 100644 --- a/app/services/translate_status_service.rb +++ b/app/services/translate_status_service.rb @@ -6,7 +6,7 @@ class TranslateStatusService < BaseService include FormattingHelper def call(status, target_language) - raise Mastodon::NotPermittedError unless status.public_visibility? || status.unlisted_visibility? + raise Mastodon::NotPermittedError unless status.translatable? @status = status @content = status_content_format(@status) diff --git a/spec/lib/translation_service/deepl_spec.rb b/spec/lib/translation_service/deepl_spec.rb new file mode 100644 index 000000000..aa2473186 --- /dev/null +++ b/spec/lib/translation_service/deepl_spec.rb @@ -0,0 +1,100 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe TranslationService::DeepL do + subject(:service) { described_class.new(plan, 'my-api-key') } + + let(:plan) { 'advanced' } + + before do + stub_request(:get, 'https://api.deepl.com/v2/languages?type=source').to_return( + body: '[{"language":"EN","name":"English"},{"language":"UK","name":"Ukrainian"}]' + ) + stub_request(:get, 'https://api.deepl.com/v2/languages?type=target').to_return( + body: '[{"language":"EN-GB","name":"English (British)"},{"language":"ZH","name":"Chinese"}]' + ) + end + + describe '#supported?' do + it 'supports included languages as source and target languages' do + expect(service.supported?('uk', 'en')).to be true + end + + it 'supports auto-detecting source language' do + expect(service.supported?(nil, 'en')).to be true + end + + it 'supports "en" and "pt" as target languages though not included in language list' do + expect(service.supported?('uk', 'en')).to be true + expect(service.supported?('uk', 'pt')).to be true + end + + it 'does not support non-included language as target language' do + expect(service.supported?('uk', 'nl')).to be false + end + + it 'does not support non-included language as source language' do + expect(service.supported?('da', 'en')).to be false + end + end + + describe '#translate' do + it 'returns translation with specified source language' do + stub_request(:post, 'https://api.deepl.com/v2/translate') + .with(body: 'text=Hasta+la+vista&source_lang=ES&target_lang=en&tag_handling=html') + .to_return(body: '{"translations":[{"detected_source_language":"ES","text":"See you soon"}]}') + + translation = service.translate('Hasta la vista', 'es', 'en') + expect(translation.detected_source_language).to eq 'es' + expect(translation.provider).to eq 'DeepL.com' + expect(translation.text).to eq 'See you soon' + end + + it 'returns translation with auto-detected source language' do + stub_request(:post, 'https://api.deepl.com/v2/translate') + .with(body: 'text=Guten+Tag&source_lang&target_lang=en&tag_handling=html') + .to_return(body: '{"translations":[{"detected_source_language":"DE","text":"Good Morning"}]}') + + translation = service.translate('Guten Tag', nil, 'en') + expect(translation.detected_source_language).to eq 'de' + expect(translation.provider).to eq 'DeepL.com' + expect(translation.text).to eq 'Good Morning' + end + end + + describe '#languages?' do + it 'returns source languages' do + expect(service.send(:languages, 'source')).to eq ['en', 'uk', nil] + end + + it 'returns target languages' do + expect(service.send(:languages, 'target')).to eq %w(en-gb zh en pt) + end + end + + describe '#request' do + before do + stub_request(:any, //) + # rubocop:disable Lint/EmptyBlock + service.send(:request, :get, '/v2/languages') { |res| } + # rubocop:enable Lint/EmptyBlock + end + + it 'uses paid plan base URL' do + expect(a_request(:get, 'https://api.deepl.com/v2/languages')).to have_been_made.once + end + + context 'with free plan' do + let(:plan) { 'free' } + + it 'uses free plan base URL' do + expect(a_request(:get, 'https://api-free.deepl.com/v2/languages')).to have_been_made.once + end + end + + it 'sends API key' do + expect(a_request(:get, 'https://api.deepl.com/v2/languages').with(headers: { Authorization: 'DeepL-Auth-Key my-api-key' })).to have_been_made.once + end + end +end diff --git a/spec/lib/translation_service/libre_translate_spec.rb b/spec/lib/translation_service/libre_translate_spec.rb new file mode 100644 index 000000000..a6cb01884 --- /dev/null +++ b/spec/lib/translation_service/libre_translate_spec.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe TranslationService::LibreTranslate do + subject(:service) { described_class.new('https://libretranslate.example.com', 'my-api-key') } + + before do + stub_request(:get, 'https://libretranslate.example.com/languages').to_return( + body: '[{"code": "en","name": "English","targets": ["de","es"]},{"code": "da","name": "Danish","targets": ["en","de"]}]' + ) + end + + describe '#supported?' do + it 'supports included language pair' do + expect(service.supported?('en', 'de')).to be true + end + + it 'does not support reversed language pair' do + expect(service.supported?('de', 'en')).to be false + end + + it 'supports auto-detecting source language' do + expect(service.supported?(nil, 'de')).to be true + end + + it 'does not support auto-detecting for unsupported target language' do + expect(service.supported?(nil, 'pt')).to be false + end + end + + describe '#languages' do + subject(:languages) { service.send(:languages) } + + it 'includes supported source languages' do + expect(languages.keys).to eq ['en', 'da', nil] + end + + it 'includes supported target languages for source language' do + expect(languages['en']).to eq %w(de es) + end + + it 'includes supported target languages for auto-detected language' do + expect(languages[nil]).to eq %w(de es en) + end + end + + describe '#translate' do + it 'returns translation with specified source language' do + stub_request(:post, 'https://libretranslate.example.com/translate') + .with(body: '{"q":"Hasta la vista","source":"es","target":"en","format":"html","api_key":"my-api-key"}') + .to_return(body: '{"translatedText": "See you"}') + + translation = service.translate('Hasta la vista', 'es', 'en') + expect(translation.detected_source_language).to eq 'es' + expect(translation.provider).to eq 'LibreTranslate' + expect(translation.text).to eq 'See you' + end + + it 'returns translation with auto-detected source language' do + stub_request(:post, 'https://libretranslate.example.com/translate') + .with(body: '{"q":"Guten Morgen","source":"auto","target":"en","format":"html","api_key":"my-api-key"}') + .to_return(body: '{"detectedLanguage":{"confidence":92,"language":"de"},"translatedText":"Good morning"}') + + translation = service.translate('Guten Morgen', nil, 'en') + expect(translation.detected_source_language).to be_nil + expect(translation.provider).to eq 'LibreTranslate' + expect(translation.text).to eq 'Good morning' + end + end +end diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb index 1e58c6d0d..1f6cfc796 100644 --- a/spec/models/status_spec.rb +++ b/spec/models/status_spec.rb @@ -114,6 +114,85 @@ RSpec.describe Status, type: :model do end end + describe '#translatable?' do + before do + allow(TranslationService).to receive(:configured?).and_return(true) + allow(TranslationService).to receive(:configured).and_return(TranslationService.new) + allow(TranslationService.configured).to receive(:supported?).with('es', 'en').and_return(true) + + subject.language = 'es' + subject.visibility = :public + end + + context 'all conditions are satisfied' do + it 'returns true' do + expect(subject.translatable?).to be true + end + end + + context 'translation service is not configured' do + it 'returns false' do + allow(TranslationService).to receive(:configured?).and_return(false) + allow(TranslationService).to receive(:configured).and_raise(TranslationService::NotConfiguredError) + expect(subject.translatable?).to be false + end + end + + context 'status language is nil' do + it 'returns true' do + subject.language = nil + allow(TranslationService.configured).to receive(:supported?).with(nil, 'en').and_return(true) + expect(subject.translatable?).to be true + end + end + + context 'status language is same as default locale' do + it 'returns false' do + subject.language = I18n.locale + expect(subject.translatable?).to be false + end + end + + context 'status language is unsupported' do + it 'returns false' do + subject.language = 'af' + allow(TranslationService.configured).to receive(:supported?).with('af', 'en').and_return(false) + expect(subject.translatable?).to be false + end + end + + context 'default locale is unsupported' do + it 'returns false' do + allow(TranslationService.configured).to receive(:supported?).with('es', 'af').and_return(false) + I18n.with_locale('af') do + expect(subject.translatable?).to be false + end + end + end + + context 'default locale has region' do + it 'returns true' do + I18n.with_locale('en-GB') do + expect(subject.translatable?).to be true + end + end + end + + context 'status text is blank' do + it 'returns false' do + subject.text = ' ' + expect(subject.translatable?).to be false + end + end + + context 'status visiblity is hidden' do + it 'returns false' do + subject.visibility = 'limited' + expect(subject.translatable?).to be false + end + end + end + describe '#content' do it 'returns the text of the status if it is not a reblog' do expect(subject.content).to eql subject.text -- cgit From 922837dc96154b0455a4cf660c3f8369c65aacb4 Mon Sep 17 00:00:00 2001 From: Jean byroot Boussier Date: Sat, 4 Mar 2023 16:38:28 +0100 Subject: Upgrade to latest redis-rb 4.x and fix deprecations (#23616) Co-authored-by: Jean Boussier --- Gemfile.lock | 2 +- app/lib/feed_manager.rb | 20 ++++++++++---------- app/models/follow_recommendation_suppression.rb | 4 ++-- app/services/batched_remove_status_service.rb | 18 +++++++++--------- .../scheduler/follow_recommendations_scheduler.rb | 13 +++++-------- config/environments/development.rb | 2 ++ config/environments/test.rb | 2 ++ config/initializers/redis.rb | 1 + db/migrate/20170920032311_fix_reblogs_in_feeds.rb | 2 +- .../20200407202420_migrate_unavailable_inboxes.rb | 5 +++-- lib/mastodon/feeds_cli.rb | 6 +----- 11 files changed, 37 insertions(+), 38 deletions(-) create mode 100644 config/initializers/redis.rb (limited to 'app/models') diff --git a/Gemfile.lock b/Gemfile.lock index 51cf8147b..b8b094325 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -558,7 +558,7 @@ GEM rdf-normalize (0.5.1) rdf (~> 3.2) redcarpet (3.6.0) - redis (4.5.1) + redis (4.8.1) redis-namespace (1.10.0) redis (>= 4) redlock (1.3.2) diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 8d7540e0f..7dda6b185 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -273,27 +273,27 @@ class FeedManager def clean_feeds!(type, ids) reblogged_id_sets = {} - redis.pipelined do + redis.pipelined do |pipeline| ids.each do |feed_id| - redis.del(key(type, feed_id)) reblog_key = key(type, feed_id, 'reblogs') # We collect a future for this: we don't block while getting # it, but we can iterate over it later. - reblogged_id_sets[feed_id] = redis.zrange(reblog_key, 0, -1) - redis.del(reblog_key) + reblogged_id_sets[feed_id] = pipeline.zrange(reblog_key, 0, -1) + pipeline.del(key(type, feed_id), reblog_key) end end # Remove all of the reblog tracking keys we just removed the # references to. - redis.pipelined do - reblogged_id_sets.each do |feed_id, future| - future.value.each do |reblogged_id| - reblog_set_key = key(type, feed_id, "reblogs:#{reblogged_id}") - redis.del(reblog_set_key) - end + keys_to_delete = reblogged_id_sets.flat_map do |feed_id, future| + future.value.map do |reblogged_id| + key(type, feed_id, "reblogs:#{reblogged_id}") end end + + redis.del(keys_to_delete) unless keys_to_delete.empty? + + nil end private diff --git a/app/models/follow_recommendation_suppression.rb b/app/models/follow_recommendation_suppression.rb index a9dbbfc18..e261a2fe3 100644 --- a/app/models/follow_recommendation_suppression.rb +++ b/app/models/follow_recommendation_suppression.rb @@ -20,9 +20,9 @@ class FollowRecommendationSuppression < ApplicationRecord private def remove_follow_recommendations - redis.pipelined do + redis.pipelined do |pipeline| I18n.available_locales.each do |locale| - redis.zrem("follow_recommendations:#{locale}", account_id) + pipeline.zrem("follow_recommendations:#{locale}", account_id) end end end diff --git a/app/services/batched_remove_status_service.rb b/app/services/batched_remove_status_service.rb index 54e5f10a4..7e9b67126 100644 --- a/app/services/batched_remove_status_service.rb +++ b/app/services/batched_remove_status_service.rb @@ -45,9 +45,9 @@ class BatchedRemoveStatusService < BaseService # Cannot be batched @status_id_cutoff = Mastodon::Snowflake.id_at(2.weeks.ago) - redis.pipelined do + redis.pipelined do |pipeline| statuses.each do |status| - unpush_from_public_timelines(status) + unpush_from_public_timelines(status, pipeline) end end end @@ -70,22 +70,22 @@ class BatchedRemoveStatusService < BaseService end end - def unpush_from_public_timelines(status) + def unpush_from_public_timelines(status, pipeline) return unless status.public_visibility? && status.id > @status_id_cutoff payload = Oj.dump(event: :delete, payload: status.id.to_s) - redis.publish('timeline:public', payload) - redis.publish(status.local? ? 'timeline:public:local' : 'timeline:public:remote', payload) + pipeline.publish('timeline:public', payload) + pipeline.publish(status.local? ? 'timeline:public:local' : 'timeline:public:remote', payload) if status.media_attachments.any? - redis.publish('timeline:public:media', payload) - redis.publish(status.local? ? 'timeline:public:local:media' : 'timeline:public:remote:media', payload) + pipeline.publish('timeline:public:media', payload) + pipeline.publish(status.local? ? 'timeline:public:local:media' : 'timeline:public:remote:media', payload) end status.tags.map { |tag| tag.name.mb_chars.downcase }.each do |hashtag| - redis.publish("timeline:hashtag:#{hashtag}", payload) - redis.publish("timeline:hashtag:#{hashtag}:local", payload) if status.local? + pipeline.publish("timeline:hashtag:#{hashtag}", payload) + pipeline.publish("timeline:hashtag:#{hashtag}:local", payload) if status.local? end end end diff --git a/app/workers/scheduler/follow_recommendations_scheduler.rb b/app/workers/scheduler/follow_recommendations_scheduler.rb index 04008a9d9..17cf3f2cc 100644 --- a/app/workers/scheduler/follow_recommendations_scheduler.rb +++ b/app/workers/scheduler/follow_recommendations_scheduler.rb @@ -20,7 +20,7 @@ class Scheduler::FollowRecommendationsScheduler Trends.available_locales.each do |locale| recommendations = if AccountSummary.safe.filtered.localized(locale).exists? # We can skip the work if no accounts with that language exist - FollowRecommendation.localized(locale).order(rank: :desc).limit(SET_SIZE).map { |recommendation| [recommendation.account_id, recommendation.rank] } + FollowRecommendation.localized(locale).order(rank: :desc).limit(SET_SIZE).map { |recommendation| [recommendation.rank, recommendation.account_id] } else [] end @@ -33,14 +33,14 @@ class Scheduler::FollowRecommendationsScheduler # Language-specific results should be above language-agnostic ones, # otherwise language-agnostic ones will always overshadow them - recommendations.map! { |(account_id, rank)| [account_id, rank + max_fallback_rank] } + recommendations.map! { |(rank, account_id)| [rank + max_fallback_rank, account_id] } added = 0 fallback_recommendations.each do |recommendation| - next if recommendations.any? { |(account_id, _)| account_id == recommendation.account_id } + next if recommendations.any? { |(_, account_id)| account_id == recommendation.account_id } - recommendations << [recommendation.account_id, recommendation.rank] + recommendations << [recommendation.rank, recommendation.account_id] added += 1 break if added >= missing @@ -49,10 +49,7 @@ class Scheduler::FollowRecommendationsScheduler redis.multi do |multi| multi.del(key(locale)) - - recommendations.each do |(account_id, rank)| - multi.zadd(key(locale), rank, account_id) - end + multi.zadd(key(locale), recommendations) end end end diff --git a/config/environments/development.rb b/config/environments/development.rb index de8762ff7..29b17a350 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -87,6 +87,8 @@ Rails.application.configure do config.x.otp_secret = ENV.fetch('OTP_SECRET', '1fc2b87989afa6351912abeebe31ffc5c476ead9bf8b3d74cbc4a302c7b69a45b40b1bbef3506ddad73e942e15ed5ca4b402bf9a66423626051104f4b5f05109') end +Redis.raise_deprecations = true + ActiveRecordQueryTrace.enabled = ENV['QUERY_TRACE_ENABLED'] == 'true' module PrivateAddressCheck diff --git a/config/environments/test.rb b/config/environments/test.rb index ef3cb2e48..9cbf31e8d 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -73,3 +73,5 @@ end # Catch serialization warnings early Sidekiq.strict_args! + +Redis.raise_deprecations = true diff --git a/config/initializers/redis.rb b/config/initializers/redis.rb new file mode 100644 index 000000000..f2bbd1e45 --- /dev/null +++ b/config/initializers/redis.rb @@ -0,0 +1 @@ +Redis.sadd_returns_boolean = false diff --git a/db/migrate/20170920032311_fix_reblogs_in_feeds.rb b/db/migrate/20170920032311_fix_reblogs_in_feeds.rb index 4ab68e8f3..7e2db0ff3 100644 --- a/db/migrate/20170920032311_fix_reblogs_in_feeds.rb +++ b/db/migrate/20170920032311_fix_reblogs_in_feeds.rb @@ -1,6 +1,6 @@ class FixReblogsInFeeds < ActiveRecord::Migration[5.1] def up - redis = Redis.current + redis = RedisConfiguration.pool.checkout fm = FeedManager.instance # Old scheme: diff --git a/db/migrate/20200407202420_migrate_unavailable_inboxes.rb b/db/migrate/20200407202420_migrate_unavailable_inboxes.rb index 92a3acb5d..8f9c68794 100644 --- a/db/migrate/20200407202420_migrate_unavailable_inboxes.rb +++ b/db/migrate/20200407202420_migrate_unavailable_inboxes.rb @@ -2,7 +2,8 @@ class MigrateUnavailableInboxes < ActiveRecord::Migration[5.2] disable_ddl_transaction! def up - urls = Redis.current.smembers('unavailable_inboxes') + redis = RedisConfiguration.pool.checkout + urls = redis.smembers('unavailable_inboxes') hosts = urls.map do |url| Addressable::URI.parse(url).normalized_host @@ -14,7 +15,7 @@ class MigrateUnavailableInboxes < ActiveRecord::Migration[5.2] UnavailableDomain.create(domain: host) end - Redis.current.del(*(['unavailable_inboxes'] + Redis.current.keys('exhausted_deliveries:*'))) + redis.del(*(['unavailable_inboxes'] + redis.keys('exhausted_deliveries:*'))) end def down; end diff --git a/lib/mastodon/feeds_cli.rb b/lib/mastodon/feeds_cli.rb index 428d63a44..fcfb48740 100644 --- a/lib/mastodon/feeds_cli.rb +++ b/lib/mastodon/feeds_cli.rb @@ -53,11 +53,7 @@ module Mastodon desc 'clear', 'Remove all home and list feeds from Redis' def clear keys = redis.keys('feed:*') - - redis.pipelined do - keys.each { |key| redis.del(key) } - end - + redis.del(keys) say('OK', :green) end end -- cgit From 86f8aa2db2bf4f19f482b5857c4e49b8791eb514 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 6 Mar 2023 16:00:08 +0100 Subject: Fix unconfirmed accounts being registered as active users (#23803) --- app/models/user.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app/models') diff --git a/app/models/user.rb b/app/models/user.rb index 5e106dee5..d56a9b9ca 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -507,11 +507,14 @@ class User < ApplicationRecord def prepare_new_user! BootstrapTimelineWorker.perform_async(account_id) ActivityTracker.increment('activity:accounts:local') + ActivityTracker.record('activity:logins', id) UserMailer.welcome(self).deliver_later TriggerWebhookWorker.perform_async('account.approved', 'Account', account_id) end def prepare_returning_user! + return unless confirmed? + ActivityTracker.record('activity:logins', id) regenerate_feed! if needs_feed_update? end -- cgit From bd047acc356671727c112336bb237f979bba517d Mon Sep 17 00:00:00 2001 From: Christian Schmidt Date: Thu, 16 Mar 2023 11:07:24 +0100 Subject: Replace `Status#translatable?` with language matrix in separate endpoint (#24037) --- .rubocop_todo.yml | 1 - .../instances/translation_languages_controller.rb | 23 +++++++ app/javascript/mastodon/actions/server.js | 27 ++++++++ .../mastodon/components/status_content.jsx | 13 +++- app/javascript/mastodon/features/ui/index.jsx | 3 +- app/javascript/mastodon/reducers/server.js | 9 +++ app/lib/translation_service.rb | 4 +- app/lib/translation_service/deepl.rb | 30 ++++---- app/lib/translation_service/libre_translate.rb | 18 ++--- app/models/status.rb | 10 --- app/serializers/rest/status_serializer.rb | 6 +- app/services/translate_status_service.rb | 16 ++++- config/routes.rb | 1 + .../translation_languages_controller_spec.rb | 31 +++++++++ .../v1/statuses/translations_controller_spec.rb | 3 +- spec/lib/translation_service/deepl_spec.rb | 36 +++------- .../translation_service/libre_translate_spec.rb | 31 ++------- spec/models/status_spec.rb | 79 ---------------------- spec/presenters/instance_presenter_spec.rb | 2 +- 19 files changed, 164 insertions(+), 179 deletions(-) create mode 100644 app/controllers/api/v1/instances/translation_languages_controller.rb create mode 100644 spec/controllers/api/v1/instances/translation_languages_controller_spec.rb (limited to 'app/models') diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index e79f4f8e9..85f078dcf 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -484,7 +484,6 @@ RSpec/DescribedClass: - 'spec/models/user_spec.rb' - 'spec/policies/account_moderation_note_policy_spec.rb' - 'spec/presenters/account_relationships_presenter_spec.rb' - - 'spec/presenters/instance_presenter_spec.rb' - 'spec/presenters/status_relationships_presenter_spec.rb' - 'spec/serializers/activitypub/note_serializer_spec.rb' - 'spec/serializers/activitypub/update_poll_serializer_spec.rb' 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/javascript/mastodon/actions/server.js b/app/javascript/mastodon/actions/server.js index 31d4aea10..091af0f0f 100644 --- a/app/javascript/mastodon/actions/server.js +++ b/app/javascript/mastodon/actions/server.js @@ -5,6 +5,10 @@ export const SERVER_FETCH_REQUEST = 'Server_FETCH_REQUEST'; export const SERVER_FETCH_SUCCESS = 'Server_FETCH_SUCCESS'; export const SERVER_FETCH_FAIL = 'Server_FETCH_FAIL'; +export const SERVER_TRANSLATION_LANGUAGES_FETCH_REQUEST = 'SERVER_TRANSLATION_LANGUAGES_FETCH_REQUEST'; +export const SERVER_TRANSLATION_LANGUAGES_FETCH_SUCCESS = 'SERVER_TRANSLATION_LANGUAGES_FETCH_SUCCESS'; +export const SERVER_TRANSLATION_LANGUAGES_FETCH_FAIL = 'SERVER_TRANSLATION_LANGUAGES_FETCH_FAIL'; + export const EXTENDED_DESCRIPTION_REQUEST = 'EXTENDED_DESCRIPTION_REQUEST'; export const EXTENDED_DESCRIPTION_SUCCESS = 'EXTENDED_DESCRIPTION_SUCCESS'; export const EXTENDED_DESCRIPTION_FAIL = 'EXTENDED_DESCRIPTION_FAIL'; @@ -37,6 +41,29 @@ const fetchServerFail = error => ({ error, }); +export const fetchServerTranslationLanguages = () => (dispatch, getState) => { + dispatch(fetchServerTranslationLanguagesRequest()); + + api(getState) + .get('/api/v1/instance/translation_languages').then(({ data }) => { + dispatch(fetchServerTranslationLanguagesSuccess(data)); + }).catch(err => dispatch(fetchServerTranslationLanguagesFail(err))); +}; + +const fetchServerTranslationLanguagesRequest = () => ({ + type: SERVER_TRANSLATION_LANGUAGES_FETCH_REQUEST, +}); + +const fetchServerTranslationLanguagesSuccess = translationLanguages => ({ + type: SERVER_TRANSLATION_LANGUAGES_FETCH_SUCCESS, + translationLanguages, +}); + +const fetchServerTranslationLanguagesFail = error => ({ + type: SERVER_TRANSLATION_LANGUAGES_FETCH_FAIL, + error, +}); + export const fetchExtendedDescription = () => (dispatch, getState) => { dispatch(fetchExtendedDescriptionRequest()); diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx index f9c9fe079..67a487b00 100644 --- a/app/javascript/mastodon/components/status_content.jsx +++ b/app/javascript/mastodon/components/status_content.jsx @@ -3,6 +3,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import { FormattedMessage, injectIntl } from 'react-intl'; import { Link } from 'react-router-dom'; +import { connect } from 'react-redux'; import classnames from 'classnames'; import PollContainer from 'mastodon/containers/poll_container'; import Icon from 'mastodon/components/icon'; @@ -47,7 +48,12 @@ class TranslateButton extends React.PureComponent { } -export default @injectIntl +const mapStateToProps = state => ({ + languages: state.getIn(['server', 'translationLanguages', 'items']), +}); + +export default @connect(mapStateToProps) +@injectIntl class StatusContent extends React.PureComponent { static contextTypes = { @@ -63,6 +69,7 @@ class StatusContent extends React.PureComponent { onClick: PropTypes.func, collapsable: PropTypes.bool, onCollapsedToggle: PropTypes.func, + languages: ImmutablePropTypes.map, intl: PropTypes.object, }; @@ -220,7 +227,9 @@ class StatusContent extends React.PureComponent { const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden; const renderReadMore = this.props.onClick && status.get('collapsed'); - const renderTranslate = this.props.onTranslate && status.get('translatable'); + const contentLocale = intl.locale.replace(/[_-].*/, ''); + const targetLanguages = this.props.languages?.get(status.get('language') || 'und'); + const renderTranslate = this.props.onTranslate && this.context.identity.signedIn && ['public', 'unlisted'].includes(status.get('visibility')) && status.get('contentHtml').length > 0 && targetLanguages?.includes(contentLocale); const content = { __html: status.get('translation') ? status.getIn(['translation', 'content']) : status.get('contentHtml') }; const spoilerContent = { __html: status.get('spoilerHtml') }; diff --git a/app/javascript/mastodon/features/ui/index.jsx b/app/javascript/mastodon/features/ui/index.jsx index 2dd59f95d..083707220 100644 --- a/app/javascript/mastodon/features/ui/index.jsx +++ b/app/javascript/mastodon/features/ui/index.jsx @@ -13,7 +13,7 @@ import { debounce } from 'lodash'; import { uploadCompose, resetCompose, changeComposeSpoilerness } from '../../actions/compose'; import { expandHomeTimeline } from '../../actions/timelines'; import { expandNotifications } from '../../actions/notifications'; -import { fetchServer } from '../../actions/server'; +import { fetchServer, fetchServerTranslationLanguages } from '../../actions/server'; import { clearHeight } from '../../actions/height_cache'; import { focusApp, unfocusApp, changeLayout } from 'mastodon/actions/app'; import { synchronouslySubmitMarkers, submitMarkers, fetchMarkers } from 'mastodon/actions/markers'; @@ -399,6 +399,7 @@ class UI extends React.PureComponent { this.props.dispatch(fetchMarkers()); this.props.dispatch(expandHomeTimeline()); this.props.dispatch(expandNotifications()); + this.props.dispatch(fetchServerTranslationLanguages()); setTimeout(() => this.props.dispatch(fetchServer()), 3000); } diff --git a/app/javascript/mastodon/reducers/server.js b/app/javascript/mastodon/reducers/server.js index db9f2b5e6..909ab2a66 100644 --- a/app/javascript/mastodon/reducers/server.js +++ b/app/javascript/mastodon/reducers/server.js @@ -2,6 +2,9 @@ import { SERVER_FETCH_REQUEST, SERVER_FETCH_SUCCESS, SERVER_FETCH_FAIL, + SERVER_TRANSLATION_LANGUAGES_FETCH_REQUEST, + SERVER_TRANSLATION_LANGUAGES_FETCH_SUCCESS, + SERVER_TRANSLATION_LANGUAGES_FETCH_FAIL, EXTENDED_DESCRIPTION_REQUEST, EXTENDED_DESCRIPTION_SUCCESS, EXTENDED_DESCRIPTION_FAIL, @@ -35,6 +38,12 @@ export default function server(state = initialState, action) { return state.set('server', fromJS(action.server)).setIn(['server', 'isLoading'], false); case SERVER_FETCH_FAIL: return state.setIn(['server', 'isLoading'], false); + case SERVER_TRANSLATION_LANGUAGES_FETCH_REQUEST: + return state.setIn(['translationLanguages', 'isLoading'], true); + case SERVER_TRANSLATION_LANGUAGES_FETCH_SUCCESS: + return state.setIn(['translationLanguages', 'items'], fromJS(action.translationLanguages)).setIn(['translationLanguages', 'isLoading'], false); + case SERVER_TRANSLATION_LANGUAGES_FETCH_FAIL: + return state.setIn(['translationLanguages', 'isLoading'], false); case EXTENDED_DESCRIPTION_REQUEST: return state.setIn(['extendedDescription', 'isLoading'], true); case EXTENDED_DESCRIPTION_SUCCESS: diff --git a/app/lib/translation_service.rb b/app/lib/translation_service.rb index 5ff93674a..bfe5de44f 100644 --- a/app/lib/translation_service.rb +++ b/app/lib/translation_service.rb @@ -21,8 +21,8 @@ class TranslationService ENV['DEEPL_API_KEY'].present? || ENV['LIBRE_TRANSLATE_ENDPOINT'].present? end - def supported?(_source_language, _target_language) - false + def languages + {} end def translate(_text, _source_language, _target_language) diff --git a/app/lib/translation_service/deepl.rb b/app/lib/translation_service/deepl.rb index deff95a1d..afcb7ecb2 100644 --- a/app/lib/translation_service/deepl.rb +++ b/app/lib/translation_service/deepl.rb @@ -17,25 +17,31 @@ class TranslationService::DeepL < TranslationService end end - def supported?(source_language, target_language) - source_language.in?(languages('source')) && target_language.in?(languages('target')) + def languages + source_languages = [nil] + fetch_languages('source') + + # In DeepL, EN and PT are deprecated in favor of EN-GB/EN-US and PT-BR/PT-PT, so + # they are supported but not returned by the API. + target_languages = %w(en pt) + fetch_languages('target') + + source_languages.index_with { |language| target_languages.without(nil, language) } end private - def languages(type) - Rails.cache.fetch("translation_service/deepl/languages/#{type}", expires_in: 7.days, race_condition_ttl: 1.minute) do - request(:get, "/v2/languages?type=#{type}") do |res| - # In DeepL, EN and PT are deprecated in favor of EN-GB/EN-US and PT-BR/PT-PT, so - # they are supported but not returned by the API. - extra = type == 'source' ? [nil] : %w(en pt) - languages = Oj.load(res.body_with_limit).map { |language| language['language'].downcase } - - languages + extra - end + def fetch_languages(type) + request(:get, "/v2/languages?type=#{type}") do |res| + Oj.load(res.body_with_limit).map { |language| normalize_language(language['language']) } end end + def normalize_language(language) + subtags = language.split(/[_-]/) + subtags[0].downcase! + subtags[1]&.upcase! + subtags.join('-') + end + def request(verb, path, **options) req = Request.new(verb, "#{base_url}#{path}", **options) req.add_headers(Authorization: "DeepL-Auth-Key #{@api_key}") diff --git a/app/lib/translation_service/libre_translate.rb b/app/lib/translation_service/libre_translate.rb index 743e4d77f..8bb194a9c 100644 --- a/app/lib/translation_service/libre_translate.rb +++ b/app/lib/translation_service/libre_translate.rb @@ -15,22 +15,18 @@ class TranslationService::LibreTranslate < TranslationService end end - def supported?(source_language, target_language) - languages.key?(source_language) && languages[source_language].include?(target_language) - end - - private - def languages - Rails.cache.fetch('translation_service/libre_translate/languages', expires_in: 7.days, race_condition_ttl: 1.minute) do - request(:get, '/languages') do |res| - languages = Oj.load(res.body_with_limit).to_h { |language| [language['code'], language['targets']] } - languages[nil] = languages.values.flatten.uniq - languages + request(:get, '/languages') do |res| + languages = Oj.load(res.body_with_limit).to_h do |language| + [language['code'], language['targets'].without(language['code'])] end + languages[nil] = languages.values.flatten.uniq.sort + languages end end + private + def request(verb, path, **options) req = Request.new(verb, "#{@base_url}#{path}", allow_local: true, **options) req.add_headers('Content-Type': 'application/json') diff --git a/app/models/status.rb b/app/models/status.rb index dd7ac2edb..e7ea191a8 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -232,16 +232,6 @@ class Status < ApplicationRecord public_visibility? || unlisted_visibility? end - def translatable? - translate_target_locale = I18n.locale.to_s.split(/[_-]/).first - - distributable? && - content.present? && - language != translate_target_locale && - TranslationService.configured? && - TranslationService.configured.supported?(language, translate_target_locale) - end - alias sign? distributable? def with_media? diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index a422f5b25..e0b8f32a6 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -4,7 +4,7 @@ class REST::StatusSerializer < ActiveModel::Serializer include FormattingHelper attributes :id, :created_at, :in_reply_to_id, :in_reply_to_account_id, - :sensitive, :spoiler_text, :visibility, :language, :translatable, + :sensitive, :spoiler_text, :visibility, :language, :uri, :url, :replies_count, :reblogs_count, :favourites_count, :edited_at @@ -50,10 +50,6 @@ class REST::StatusSerializer < ActiveModel::Serializer object.account.user_shows_application? || (current_user? && current_user.account_id == object.account_id) end - def translatable - current_user? && object.translatable? - end - def visibility # This visibility is masked behind "private" # to avoid API changes because there are no diff --git a/app/services/translate_status_service.rb b/app/services/translate_status_service.rb index 92d8b62a0..796f13a0d 100644 --- a/app/services/translate_status_service.rb +++ b/app/services/translate_status_service.rb @@ -6,19 +6,29 @@ class TranslateStatusService < BaseService include FormattingHelper def call(status, target_language) - raise Mastodon::NotPermittedError unless status.translatable? - @status = status @content = status_content_format(@status) @target_language = target_language + raise Mastodon::NotPermittedError unless permitted? + Rails.cache.fetch("translations/#{@status.language}/#{@target_language}/#{content_hash}", expires_in: CACHE_TTL) { translation_backend.translate(@content, @status.language, @target_language) } end private def translation_backend - TranslationService.configured + @translation_backend ||= TranslationService.configured + end + + def permitted? + return false unless @status.distributable? && @status.content.present? && TranslationService.configured? + + languages[@status.language]&.include?(@target_language) + end + + def languages + Rails.cache.fetch('translation_service/languages', expires_in: 7.days, race_condition_ttl: 1.hour) { TranslationService.configured.languages } end def content_hash diff --git a/config/routes.rb b/config/routes.rb index 530b46a5a..ea595e1e1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -546,6 +546,7 @@ Rails.application.routes.draw do resources :domain_blocks, only: [:index], controller: 'instances/domain_blocks' resource :privacy_policy, only: [:show], controller: 'instances/privacy_policies' resource :extended_description, only: [:show], controller: 'instances/extended_descriptions' + resource :translation_languages, only: [:show], controller: 'instances/translation_languages' resource :activity, only: [:show], controller: 'instances/activity' end diff --git a/spec/controllers/api/v1/instances/translation_languages_controller_spec.rb b/spec/controllers/api/v1/instances/translation_languages_controller_spec.rb new file mode 100644 index 000000000..5b7e4abb6 --- /dev/null +++ b/spec/controllers/api/v1/instances/translation_languages_controller_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe Api::V1::Instances::TranslationLanguagesController do + describe 'GET #show' do + context 'when no translation service is configured' do + it 'returns empty language matrix' do + get :show + + expect(response).to have_http_status(200) + expect(body_as_json).to eq({}) + end + end + + context 'when a translation service is configured' do + before do + service = instance_double(TranslationService::DeepL, languages: { nil => %w(en de), 'en' => ['de'] }) + allow(TranslationService).to receive(:configured?).and_return(true) + allow(TranslationService).to receive(:configured).and_return(service) + end + + it 'returns language matrix' do + get :show + + expect(response).to have_http_status(200) + expect(body_as_json).to eq({ und: %w(en de), en: ['de'] }) + end + end + end +end diff --git a/spec/controllers/api/v1/statuses/translations_controller_spec.rb b/spec/controllers/api/v1/statuses/translations_controller_spec.rb index 2deea9fc0..8495779bf 100644 --- a/spec/controllers/api/v1/statuses/translations_controller_spec.rb +++ b/spec/controllers/api/v1/statuses/translations_controller_spec.rb @@ -19,9 +19,10 @@ describe Api::V1::Statuses::TranslationsController do before do translation = TranslationService::Translation.new(text: 'Hello') - service = instance_double(TranslationService::DeepL, translate: translation, supported?: true) + service = instance_double(TranslationService::DeepL, translate: translation) allow(TranslationService).to receive(:configured?).and_return(true) allow(TranslationService).to receive(:configured).and_return(service) + Rails.cache.write('translation_service/languages', { 'es' => ['en'] }) post :create, params: { status_id: status.id } end diff --git a/spec/lib/translation_service/deepl_spec.rb b/spec/lib/translation_service/deepl_spec.rb index aa2473186..2363f8f13 100644 --- a/spec/lib/translation_service/deepl_spec.rb +++ b/spec/lib/translation_service/deepl_spec.rb @@ -16,29 +16,6 @@ RSpec.describe TranslationService::DeepL do ) end - describe '#supported?' do - it 'supports included languages as source and target languages' do - expect(service.supported?('uk', 'en')).to be true - end - - it 'supports auto-detecting source language' do - expect(service.supported?(nil, 'en')).to be true - end - - it 'supports "en" and "pt" as target languages though not included in language list' do - expect(service.supported?('uk', 'en')).to be true - expect(service.supported?('uk', 'pt')).to be true - end - - it 'does not support non-included language as target language' do - expect(service.supported?('uk', 'nl')).to be false - end - - it 'does not support non-included language as source language' do - expect(service.supported?('da', 'en')).to be false - end - end - describe '#translate' do it 'returns translation with specified source language' do stub_request(:post, 'https://api.deepl.com/v2/translate') @@ -63,13 +40,18 @@ RSpec.describe TranslationService::DeepL do end end - describe '#languages?' do + describe '#languages' do it 'returns source languages' do - expect(service.send(:languages, 'source')).to eq ['en', 'uk', nil] + expect(service.languages.keys).to eq [nil, 'en', 'uk'] + end + + it 'returns target languages for each source language' do + expect(service.languages['en']).to eq %w(pt en-GB zh) + expect(service.languages['uk']).to eq %w(en pt en-GB zh) end - it 'returns target languages' do - expect(service.send(:languages, 'target')).to eq %w(en-gb zh en pt) + it 'returns target languages for auto-detection' do + expect(service.languages[nil]).to eq %w(en pt en-GB zh) end end diff --git a/spec/lib/translation_service/libre_translate_spec.rb b/spec/lib/translation_service/libre_translate_spec.rb index a6cb01884..fbd726a7e 100644 --- a/spec/lib/translation_service/libre_translate_spec.rb +++ b/spec/lib/translation_service/libre_translate_spec.rb @@ -7,41 +7,24 @@ RSpec.describe TranslationService::LibreTranslate do before do stub_request(:get, 'https://libretranslate.example.com/languages').to_return( - body: '[{"code": "en","name": "English","targets": ["de","es"]},{"code": "da","name": "Danish","targets": ["en","de"]}]' + body: '[{"code": "en","name": "English","targets": ["de","en","es"]},{"code": "da","name": "Danish","targets": ["en","pt"]}]' ) end - describe '#supported?' do - it 'supports included language pair' do - expect(service.supported?('en', 'de')).to be true - end - - it 'does not support reversed language pair' do - expect(service.supported?('de', 'en')).to be false - end - - it 'supports auto-detecting source language' do - expect(service.supported?(nil, 'de')).to be true - end - - it 'does not support auto-detecting for unsupported target language' do - expect(service.supported?(nil, 'pt')).to be false - end - end - describe '#languages' do - subject(:languages) { service.send(:languages) } + subject(:languages) { service.languages } - it 'includes supported source languages' do + it 'returns source languages' do expect(languages.keys).to eq ['en', 'da', nil] end - it 'includes supported target languages for source language' do + it 'returns target languages for each source language' do expect(languages['en']).to eq %w(de es) + expect(languages['da']).to eq %w(en pt) end - it 'includes supported target languages for auto-detected language' do - expect(languages[nil]).to eq %w(de es en) + it 'returns target languages for auto-detected language' do + expect(languages[nil]).to eq %w(de en es pt) end end diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb index 1f6cfc796..1e58c6d0d 100644 --- a/spec/models/status_spec.rb +++ b/spec/models/status_spec.rb @@ -114,85 +114,6 @@ RSpec.describe Status, type: :model do end end - describe '#translatable?' do - before do - allow(TranslationService).to receive(:configured?).and_return(true) - allow(TranslationService).to receive(:configured).and_return(TranslationService.new) - allow(TranslationService.configured).to receive(:supported?).with('es', 'en').and_return(true) - - subject.language = 'es' - subject.visibility = :public - end - - context 'all conditions are satisfied' do - it 'returns true' do - expect(subject.translatable?).to be true - end - end - - context 'translation service is not configured' do - it 'returns false' do - allow(TranslationService).to receive(:configured?).and_return(false) - allow(TranslationService).to receive(:configured).and_raise(TranslationService::NotConfiguredError) - expect(subject.translatable?).to be false - end - end - - context 'status language is nil' do - it 'returns true' do - subject.language = nil - allow(TranslationService.configured).to receive(:supported?).with(nil, 'en').and_return(true) - expect(subject.translatable?).to be true - end - end - - context 'status language is same as default locale' do - it 'returns false' do - subject.language = I18n.locale - expect(subject.translatable?).to be false - end - end - - context 'status language is unsupported' do - it 'returns false' do - subject.language = 'af' - allow(TranslationService.configured).to receive(:supported?).with('af', 'en').and_return(false) - expect(subject.translatable?).to be false - end - end - - context 'default locale is unsupported' do - it 'returns false' do - allow(TranslationService.configured).to receive(:supported?).with('es', 'af').and_return(false) - I18n.with_locale('af') do - expect(subject.translatable?).to be false - end - end - end - - context 'default locale has region' do - it 'returns true' do - I18n.with_locale('en-GB') do - expect(subject.translatable?).to be true - end - end - end - - context 'status text is blank' do - it 'returns false' do - subject.text = ' ' - expect(subject.translatable?).to be false - end - end - - context 'status visiblity is hidden' do - it 'returns false' do - subject.visibility = 'limited' - expect(subject.translatable?).to be false - end - end - end - describe '#content' do it 'returns the text of the status if it is not a reblog' do expect(subject.content).to eql subject.text diff --git a/spec/presenters/instance_presenter_spec.rb b/spec/presenters/instance_presenter_spec.rb index 795abd8b4..2a1d668ce 100644 --- a/spec/presenters/instance_presenter_spec.rb +++ b/spec/presenters/instance_presenter_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe InstancePresenter do - let(:instance_presenter) { InstancePresenter.new } + let(:instance_presenter) { described_class.new } describe '#description' do around do |example| -- cgit From 75e5a6e43738c278390c03c96d5d3e8575a2783c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 16 Mar 2023 22:46:52 +0100 Subject: Change user backups to use expiring URLs for download when possible (#24136) --- app/controllers/backups_controller.rb | 27 +++++++++++++++++++++++++++ app/models/backup.rb | 2 +- app/views/settings/exports/show.html.haml | 2 +- app/views/user_mailer/backup_ready.html.haml | 2 +- app/views/user_mailer/backup_ready.text.erb | 2 +- config/routes.rb | 1 + 6 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 app/controllers/backups_controller.rb (limited to 'app/models') diff --git a/app/controllers/backups_controller.rb b/app/controllers/backups_controller.rb new file mode 100644 index 000000000..2f4b400b8 --- /dev/null +++ b/app/controllers/backups_controller.rb @@ -0,0 +1,27 @@ +# 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 + redirect_to @backup.dump.expiring_url(Time.now.utc + 10) + 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/models/backup.rb b/app/models/backup.rb index bec3cbfe5..dca06eb58 100644 --- a/app/models/backup.rb +++ b/app/models/backup.rb @@ -18,6 +18,6 @@ class Backup < ApplicationRecord belongs_to :user, inverse_of: :backups - has_attached_file :dump + has_attached_file :dump, s3_permissions: 'private' validates_attachment_content_type :dump, content_type: /\Aapplication/ end diff --git a/app/views/settings/exports/show.html.haml b/app/views/settings/exports/show.html.haml index c49613fdc..d7b59af27 100644 --- a/app/views/settings/exports/show.html.haml +++ b/app/views/settings/exports/show.html.haml @@ -64,6 +64,6 @@ %td= l backup.created_at - if backup.processed? %td= number_to_human_size backup.dump_file_size - %td= table_link_to 'download', t('exports.archive_takeout.download'), backup.dump.url + %td= table_link_to 'download', t('exports.archive_takeout.download'), download_backup_url(backup) - else %td{ colspan: 2 }= t('exports.archive_takeout.in_progress') diff --git a/app/views/user_mailer/backup_ready.html.haml b/app/views/user_mailer/backup_ready.html.haml index 85140b08b..465ead2c8 100644 --- a/app/views/user_mailer/backup_ready.html.haml +++ b/app/views/user_mailer/backup_ready.html.haml @@ -55,5 +55,5 @@ %tbody %tr %td.button-primary - = link_to full_asset_url(@backup.dump.url) do + = link_to download_backup_url(@backup) do %span= t 'exports.archive_takeout.download' diff --git a/app/views/user_mailer/backup_ready.text.erb b/app/views/user_mailer/backup_ready.text.erb index eb89e7d74..8ebbaae85 100644 --- a/app/views/user_mailer/backup_ready.text.erb +++ b/app/views/user_mailer/backup_ready.text.erb @@ -4,4 +4,4 @@ <%= t 'user_mailer.backup_ready.explanation' %> -=> <%= full_asset_url(@backup.dump.url) %> +=> <%= download_backup_url(@backup) %> diff --git a/config/routes.rb b/config/routes.rb index ea595e1e1..8850545ca 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -220,6 +220,7 @@ Rails.application.routes.draw do resource :statuses_cleanup, controller: :statuses_cleanup, only: [:show, :update] get '/media_proxy/:id/(*any)', to: 'media_proxy#show', as: :media_proxy, format: false + get '/backups/:id/download', to: 'backups#download', as: :download_backup, format: false resource :authorize_interaction, only: [:show, :create] resource :share, only: [:show, :create] -- cgit From 94cbd808b5b3e7999c7e77dc724b7e8c9dd2bdec Mon Sep 17 00:00:00 2001 From: Vyr Cossont Date: Sat, 18 Mar 2023 23:47:54 -0700 Subject: Webhooks for local status.create, status.update, account.update (#24133) --- .rubocop_todo.yml | 2 +- app/models/account.rb | 7 +++++++ app/models/status.rb | 11 +++++++++++ app/models/webhook.rb | 3 +++ app/workers/webhooks/delivery_worker.rb | 2 +- 5 files changed, 23 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index a3536e202..b2f8bf52c 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -245,7 +245,7 @@ Metrics/BlockNesting: # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 368 + Max: 375 # Configuration parameters: AllowedMethods, AllowedPatterns. Metrics/CyclomaticComplexity: diff --git a/app/models/account.rb b/app/models/account.rb index 1ff083e54..c4df48878 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -122,6 +122,8 @@ class Account < ApplicationRecord scope :not_excluded_by_account, ->(account) { where.not(id: account.excluded_from_timeline_account_ids) } scope :not_domain_blocked_by_account, ->(account) { where(arel_table[:domain].eq(nil).or(arel_table[:domain].not_in(account.excluded_from_timeline_domains))) } + after_update_commit :trigger_update_webhooks + delegate :email, :unconfirmed_email, :current_sign_in_at, @@ -593,4 +595,9 @@ class Account < ApplicationRecord CanonicalEmailBlock.where(reference_account: self).delete_all end + + # NOTE: the `account.created` webhook is triggered by the `User` model, not `Account`. + def trigger_update_webhooks + TriggerWebhookWorker.perform_async('account.updated', 'Account', id) if local? + end end diff --git a/app/models/status.rb b/app/models/status.rb index e7ea191a8..2e32c3f16 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -111,6 +111,9 @@ class Status < ApplicationRecord where('NOT EXISTS (SELECT * FROM statuses_tags forbidden WHERE forbidden.status_id = statuses.id AND forbidden.tag_id IN (?))', tag_ids) } + after_create_commit :trigger_create_webhooks + after_update_commit :trigger_update_webhooks + cache_associated :application, :media_attachments, :conversation, @@ -535,4 +538,12 @@ class Status < ApplicationRecord reblog&.decrement_count!(:reblogs_count) if reblog? thread&.decrement_count!(:replies_count) if in_reply_to_id.present? && distributable? end + + def trigger_create_webhooks + TriggerWebhookWorker.perform_async('status.created', 'Status', id) if local? + end + + def trigger_update_webhooks + TriggerWebhookWorker.perform_async('status.updated', 'Status', id) if local? + end end diff --git a/app/models/webhook.rb b/app/models/webhook.rb index 4aafb1257..9a056a386 100644 --- a/app/models/webhook.rb +++ b/app/models/webhook.rb @@ -17,7 +17,10 @@ class Webhook < ApplicationRecord EVENTS = %w( account.approved account.created + account.updated report.created + status.created + status.updated ).freeze scope :enabled, -> { where(enabled: true) } diff --git a/app/workers/webhooks/delivery_worker.rb b/app/workers/webhooks/delivery_worker.rb index b1e345c5e..f8ed669fb 100644 --- a/app/workers/webhooks/delivery_worker.rb +++ b/app/workers/webhooks/delivery_worker.rb @@ -19,7 +19,7 @@ class Webhooks::DeliveryWorker private def perform_request - request = Request.new(:post, @webhook.url, body: @body) + request = Request.new(:post, @webhook.url, body: @body, allow_local: true) request.add_headers( 'Content-Type' => 'application/json', -- cgit From 38c84f57b6d2de1683974f91d726c30ba7f1491b Mon Sep 17 00:00:00 2001 From: Takeshi Umeda Date: Tue, 21 Mar 2023 18:32:58 +0900 Subject: Refactoring relations_map (#24195) --- app/models/concerns/account_interactions.rb | 15 +++++++++++++++ app/models/concerns/status_threading_concern.rb | 14 +------------- app/services/import_service.rb | 12 +----------- app/services/search_service.rb | 12 +----------- 4 files changed, 18 insertions(+), 35 deletions(-) (limited to 'app/models') diff --git a/app/models/concerns/account_interactions.rb b/app/models/concerns/account_interactions.rb index 1898516b0..48ab1349d 100644 --- a/app/models/concerns/account_interactions.rb +++ b/app/models/concerns/account_interactions.rb @@ -292,6 +292,21 @@ module AccountInteractions end end + def relations_map(account_ids, domains = nil, **options) + relations = { + blocked_by: Account.blocked_by_map(account_ids, id), + following: Account.following_map(account_ids, id), + } + + return relations if options[:skip_blocking_and_muting] + + relations.merge!({ + blocking: Account.blocking_map(account_ids, id), + muting: Account.muting_map(account_ids, id), + domain_blocking_by_domain: Account.domain_blocking_map_by_domain(domains, id), + }) + end + private def remove_potential_friendship(other_account) diff --git a/app/models/concerns/status_threading_concern.rb b/app/models/concerns/status_threading_concern.rb index 8b628beea..2ca3b66c2 100644 --- a/app/models/concerns/status_threading_concern.rb +++ b/app/models/concerns/status_threading_concern.rb @@ -79,7 +79,7 @@ module StatusThreadingConcern statuses = Status.with_accounts(ids).to_a account_ids = statuses.map(&:account_id).uniq domains = statuses.filter_map(&:account_domain).uniq - relations = relations_map_for_account(account, account_ids, domains) + relations = account&.relations_map(account_ids, domains) || {} statuses.reject! { |status| StatusFilter.new(status, account, relations).filtered? } @@ -108,16 +108,4 @@ module StatusThreadingConcern arr end - - def relations_map_for_account(account, account_ids, domains) - return {} if account.nil? - - { - blocking: Account.blocking_map(account_ids, account.id), - blocked_by: Account.blocked_by_map(account_ids, account.id), - muting: Account.muting_map(account_ids, account.id), - following: Account.following_map(account_ids, account.id), - domain_blocking_by_domain: Account.domain_blocking_map_by_domain(domains, account.id), - } - end end diff --git a/app/services/import_service.rb b/app/services/import_service.rb index 940c236d4..56f191c1f 100644 --- a/app/services/import_service.rb +++ b/app/services/import_service.rb @@ -120,7 +120,7 @@ class ImportService < BaseService end account_ids = statuses.map(&:account_id) - preloaded_relations = relations_map_for_account(@account, account_ids) + preloaded_relations = @account.relations_map(account_ids, skip_blocking_and_muting: true) statuses.keep_if { |status| StatusPolicy.new(@account, status, preloaded_relations).show? } @@ -138,14 +138,4 @@ class ImportService < BaseService def import_data Paperclip.io_adapters.for(@import.data).read.force_encoding(Encoding::UTF_8) end - - def relations_map_for_account(account, account_ids) - { - blocking: {}, - blocked_by: Account.blocked_by_map(account_ids, account.id), - muting: {}, - following: Account.following_map(account_ids, account.id), - domain_blocking_by_domain: {}, - } - end end diff --git a/app/services/search_service.rb b/app/services/search_service.rb index 93b72fa0c..b1ce5453f 100644 --- a/app/services/search_service.rb +++ b/app/services/search_service.rb @@ -49,7 +49,7 @@ class SearchService < BaseService results = definition.limit(@limit).offset(@offset).objects.compact account_ids = results.map(&:account_id) account_domains = results.map(&:account_domain) - preloaded_relations = relations_map_for_account(@account, account_ids, account_domains) + preloaded_relations = @account.relations_map(account_ids, account_domains) results.reject { |status| StatusFilter.new(status, @account, preloaded_relations).filtered? } rescue Faraday::ConnectionFailed, Parslet::ParseFailed @@ -111,16 +111,6 @@ class SearchService < BaseService @options[:type].blank? || @options[:type] == 'statuses' end - def relations_map_for_account(account, account_ids, domains) - { - blocking: Account.blocking_map(account_ids, account.id), - blocked_by: Account.blocked_by_map(account_ids, account.id), - muting: Account.muting_map(account_ids, account.id), - following: Account.following_map(account_ids, account.id), - domain_blocking_by_domain: Account.domain_blocking_map_by_domain(domains, account.id), - } - end - def parsed_query SearchQueryTransformer.new.apply(SearchQueryParser.new.parse(@query)) end -- cgit From 2626097869c9520c21aaba73c9bcfe72c0f25f28 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 22 Mar 2023 15:47:44 +0100 Subject: Fix Rails cache namespace being overriden with `v2` for cached statuses (#24202) --- app/controllers/concerns/cache_concern.rb | 4 ++-- app/models/status.rb | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/controllers/concerns/cache_concern.rb b/app/controllers/concerns/cache_concern.rb index e606218ac..a5a9ba3e1 100644 --- a/app/controllers/concerns/cache_concern.rb +++ b/app/controllers/concerns/cache_concern.rb @@ -187,7 +187,7 @@ module CacheConcern return [] if raw.empty? cached_keys_with_value = begin - Rails.cache.read_multi(*raw, namespace: 'v2').transform_keys(&:id).transform_values { |r| ActiveRecordCoder.load(r) } + 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 @@ -200,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, ActiveRecordCoder.dump(item), namespace: 'v2') + Rails.cache.write(item, ActiveRecordCoder.dump(item)) end end diff --git a/app/models/status.rb b/app/models/status.rb index 2e32c3f16..2757497db 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -140,6 +140,10 @@ class Status < ApplicationRecord REAL_TIME_WINDOW = 6.hours + def cache_key + "v2:#{super}" + end + def searchable_by(preloaded = nil) ids = [] -- cgit From 9bda93374093c738f1007922b2e8df58043c718f Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 25 Mar 2023 10:00:03 +0100 Subject: Change media upload limits and remove client-side resizing (#23726) --- app/javascript/mastodon/actions/compose.js | 73 ++++---- app/javascript/mastodon/utils/resize_image.js | 189 --------------------- app/models/concerns/attachmentable.rb | 2 +- app/models/media_attachment.rb | 10 +- app/models/preview_card.rb | 4 +- dist/nginx.conf | 2 +- package.json | 1 - .../settings/profiles_controller_spec.rb | 8 - yarn.lock | 5 - 9 files changed, 43 insertions(+), 251 deletions(-) delete mode 100644 app/javascript/mastodon/utils/resize_image.js (limited to 'app/models') diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index 3756a975b..961503287 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -4,7 +4,6 @@ import { defineMessages } from 'react-intl'; import api from 'mastodon/api'; import { search as emojiSearch } from 'mastodon/features/emoji/emoji_mart_search_light'; import { tagHistory } from 'mastodon/settings'; -import resizeImage from 'mastodon/utils/resize_image'; import { showAlert, showAlertForError } from './alerts'; import { useEmoji } from './emojis'; import { importFetchedAccounts, importFetchedStatus } from './importer'; @@ -274,46 +273,42 @@ export function uploadCompose(files) { dispatch(uploadComposeRequest()); - for (const [i, f] of Array.from(files).entries()) { + for (const [i, file] of Array.from(files).entries()) { if (media.size + i > 3) break; - resizeImage(f).then(file => { - const data = new FormData(); - data.append('file', file); - // Account for disparity in size of original image and resized data - total += file.size - f.size; - - return api(getState).post('/api/v2/media', data, { - onUploadProgress: function({ loaded }){ - progress[i] = loaded; - dispatch(uploadComposeProgress(progress.reduce((a, v) => a + v, 0), total)); - }, - }).then(({ status, data }) => { - // If server-side processing of the media attachment has not completed yet, - // poll the server until it is, before showing the media attachment as uploaded - - if (status === 200) { - dispatch(uploadComposeSuccess(data, f)); - } else if (status === 202) { - dispatch(uploadComposeProcessing()); - - let tryCount = 1; - - const poll = () => { - api(getState).get(`/api/v1/media/${data.id}`).then(response => { - if (response.status === 200) { - dispatch(uploadComposeSuccess(response.data, f)); - } else if (response.status === 206) { - const retryAfter = (Math.log2(tryCount) || 1) * 1000; - tryCount += 1; - setTimeout(() => poll(), retryAfter); - } - }).catch(error => dispatch(uploadComposeFail(error))); - }; - - poll(); - } - }); + const data = new FormData(); + data.append('file', file); + + api(getState).post('/api/v2/media', data, { + onUploadProgress: function({ loaded }){ + progress[i] = loaded; + dispatch(uploadComposeProgress(progress.reduce((a, v) => a + v, 0), total)); + }, + }).then(({ status, data }) => { + // If server-side processing of the media attachment has not completed yet, + // poll the server until it is, before showing the media attachment as uploaded + + if (status === 200) { + dispatch(uploadComposeSuccess(data, file)); + } else if (status === 202) { + dispatch(uploadComposeProcessing()); + + let tryCount = 1; + + const poll = () => { + api(getState).get(`/api/v1/media/${data.id}`).then(response => { + if (response.status === 200) { + dispatch(uploadComposeSuccess(response.data, file)); + } else if (response.status === 206) { + const retryAfter = (Math.log2(tryCount) || 1) * 1000; + tryCount += 1; + setTimeout(() => poll(), retryAfter); + } + }).catch(error => dispatch(uploadComposeFail(error))); + }; + + poll(); + } }).catch(error => dispatch(uploadComposeFail(error))); } }; diff --git a/app/javascript/mastodon/utils/resize_image.js b/app/javascript/mastodon/utils/resize_image.js deleted file mode 100644 index fb8c3c11e..000000000 --- a/app/javascript/mastodon/utils/resize_image.js +++ /dev/null @@ -1,189 +0,0 @@ -import EXIF from 'exif-js'; - -const MAX_IMAGE_PIXELS = 2073600; // 1920x1080px - -const _browser_quirks = {}; - -// Some browsers will automatically draw images respecting their EXIF orientation -// while others won't, and the safest way to detect that is to examine how it -// is done on a known image. -// See https://github.com/w3c/csswg-drafts/issues/4666 -// and https://github.com/blueimp/JavaScript-Load-Image/commit/1e4df707821a0afcc11ea0720ee403b8759f3881 -const dropOrientationIfNeeded = (orientation) => new Promise(resolve => { - switch (_browser_quirks['image-orientation-automatic']) { - case true: - resolve(1); - break; - case false: - resolve(orientation); - break; - default: - // black 2x1 JPEG, with the following meta information set: - // - EXIF Orientation: 6 (Rotated 90° CCW) - const testImageURL = - 'data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAA' + - 'AAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA' + - 'QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE' + - 'BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/x' + - 'ABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAA' + - 'AAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q=='; - const img = new Image(); - img.onload = () => { - const automatic = (img.width === 1 && img.height === 2); - _browser_quirks['image-orientation-automatic'] = automatic; - resolve(automatic ? 1 : orientation); - }; - img.onerror = () => { - _browser_quirks['image-orientation-automatic'] = false; - resolve(orientation); - }; - img.src = testImageURL; - } -}); - -// Some browsers don't allow reading from a canvas and instead return all-white -// or randomized data. Use a pre-defined image to check if reading the canvas -// works. -const checkCanvasReliability = () => new Promise((resolve, reject) => { - switch(_browser_quirks['canvas-read-unreliable']) { - case true: - reject('Canvas reading unreliable'); - break; - case false: - resolve(); - break; - default: - // 2×2 GIF with white, red, green and blue pixels - const testImageURL = - 'data:image/gif;base64,R0lGODdhAgACAKEDAAAA//8AAAD/AP///ywAAAAAAgACAAACA1wEBQA7'; - const refData = - [255, 255, 255, 255, 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255]; - const img = new Image(); - img.onload = () => { - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - context.drawImage(img, 0, 0, 2, 2); - const imageData = context.getImageData(0, 0, 2, 2); - if (imageData.data.every((x, i) => refData[i] === x)) { - _browser_quirks['canvas-read-unreliable'] = false; - resolve(); - } else { - _browser_quirks['canvas-read-unreliable'] = true; - reject('Canvas reading unreliable'); - } - }; - img.onerror = () => { - _browser_quirks['canvas-read-unreliable'] = true; - reject('Failed to load test image'); - }; - img.src = testImageURL; - } -}); - -const getImageUrl = inputFile => new Promise((resolve, reject) => { - if (window.URL && URL.createObjectURL) { - try { - resolve(URL.createObjectURL(inputFile)); - } catch (error) { - reject(error); - } - return; - } - - const reader = new FileReader(); - reader.onerror = (...args) => reject(...args); - reader.onload = ({ target }) => resolve(target.result); - - reader.readAsDataURL(inputFile); -}); - -const loadImage = inputFile => new Promise((resolve, reject) => { - getImageUrl(inputFile).then(url => { - const img = new Image(); - - img.onerror = (...args) => reject(...args); - img.onload = () => resolve(img); - - img.src = url; - }).catch(reject); -}); - -const getOrientation = (img, type = 'image/png') => new Promise(resolve => { - if (!['image/jpeg', 'image/webp'].includes(type)) { - resolve(1); - return; - } - - EXIF.getData(img, () => { - const orientation = EXIF.getTag(img, 'Orientation'); - if (orientation !== 1) { - dropOrientationIfNeeded(orientation).then(resolve).catch(() => resolve(orientation)); - } else { - resolve(orientation); - } - }); -}); - -const processImage = (img, { width, height, orientation, type = 'image/png' }) => new Promise(resolve => { - const canvas = document.createElement('canvas'); - - if (4 < orientation && orientation < 9) { - canvas.width = height; - canvas.height = width; - } else { - canvas.width = width; - canvas.height = height; - } - - const context = canvas.getContext('2d'); - - switch (orientation) { - case 2: context.transform(-1, 0, 0, 1, width, 0); break; - case 3: context.transform(-1, 0, 0, -1, width, height); break; - case 4: context.transform(1, 0, 0, -1, 0, height); break; - case 5: context.transform(0, 1, 1, 0, 0, 0); break; - case 6: context.transform(0, 1, -1, 0, height, 0); break; - case 7: context.transform(0, -1, -1, 0, height, width); break; - case 8: context.transform(0, -1, 1, 0, 0, width); break; - } - - context.drawImage(img, 0, 0, width, height); - - canvas.toBlob(resolve, type); -}); - -const resizeImage = (img, type = 'image/png') => new Promise((resolve, reject) => { - const { width, height } = img; - - const newWidth = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (width / height))); - const newHeight = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (height / width))); - - checkCanvasReliability() - .then(getOrientation(img, type)) - .then(orientation => processImage(img, { - width: newWidth, - height: newHeight, - orientation, - type, - })) - .then(resolve) - .catch(reject); -}); - -export default inputFile => new Promise((resolve) => { - if (!inputFile.type.match(/image.*/) || inputFile.type === 'image/gif') { - resolve(inputFile); - return; - } - - loadImage(inputFile).then(img => { - if (img.width * img.height < MAX_IMAGE_PIXELS) { - resolve(inputFile); - return; - } - - resizeImage(img, inputFile.type) - .then(resolve) - .catch(() => resolve(inputFile)); - }).catch(() => resolve(inputFile)); -}); diff --git a/app/models/concerns/attachmentable.rb b/app/models/concerns/attachmentable.rb index 01fae4236..d44c22438 100644 --- a/app/models/concerns/attachmentable.rb +++ b/app/models/concerns/attachmentable.rb @@ -5,7 +5,7 @@ require 'mime/types/columnar' module Attachmentable extend ActiveSupport::Concern - MAX_MATRIX_LIMIT = 16_777_216 # 4096x4096px or approx. 16MB + MAX_MATRIX_LIMIT = 33_177_600 # 7680x4320px or approx. 847MB in RAM GIF_MATRIX_LIMIT = 921_600 # 1280x720px # For some file extensions, there exist different content diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index 08abd4e43..e51e13b95 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -39,11 +39,11 @@ class MediaAttachment < ApplicationRecord MAX_DESCRIPTION_LENGTH = 1_500 - IMAGE_LIMIT = 10.megabytes - VIDEO_LIMIT = 40.megabytes + IMAGE_LIMIT = 16.megabytes + VIDEO_LIMIT = 99.megabytes - MAX_VIDEO_MATRIX_LIMIT = 2_304_000 # 1920x1200px - MAX_VIDEO_FRAME_RATE = 60 + MAX_VIDEO_MATRIX_LIMIT = 8_294_400 # 3840x2160px + MAX_VIDEO_FRAME_RATE = 120 IMAGE_FILE_EXTENSIONS = %w(.jpg .jpeg .png .gif .webp .heic .heif .avif).freeze VIDEO_FILE_EXTENSIONS = %w(.webm .mp4 .m4v .mov).freeze @@ -69,7 +69,7 @@ class MediaAttachment < ApplicationRecord IMAGE_STYLES = { original: { - pixels: 2_073_600, # 1920x1080px + pixels: 8_294_400, # 3840x2160px file_geometry_parser: FastGeometryParser, }.freeze, diff --git a/app/models/preview_card.rb b/app/models/preview_card.rb index 6bce16562..a738940be 100644 --- a/app/models/preview_card.rb +++ b/app/models/preview_card.rb @@ -36,7 +36,7 @@ class PreviewCard < ApplicationRecord include Attachmentable IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze - LIMIT = 1.megabytes + LIMIT = 2.megabytes BLURHASH_OPTIONS = { x_comp: 4, @@ -121,7 +121,7 @@ class PreviewCard < ApplicationRecord def image_styles(file) styles = { original: { - geometry: '400x400>', + pixels: 230_400, # 640x360px file_geometry_parser: FastGeometryParser, convert_options: '-coalesce', blurhash: BLURHASH_OPTIONS, diff --git a/dist/nginx.conf b/dist/nginx.conf index 5bc960e25..bed4bd3db 100644 --- a/dist/nginx.conf +++ b/dist/nginx.conf @@ -39,7 +39,7 @@ server { keepalive_timeout 70; sendfile on; - client_max_body_size 80m; + client_max_body_size 99m; root /home/mastodon/live/public; diff --git a/package.json b/package.json index 045db8d14..90d76001b 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,6 @@ "emoji-mart": "npm:emoji-mart-lazyload@latest", "es6-symbol": "^3.1.3", "escape-html": "^1.0.3", - "exif-js": "^2.3.0", "express": "^4.18.2", "file-loader": "^6.2.0", "font-awesome": "^4.7.0", diff --git a/spec/controllers/settings/profiles_controller_spec.rb b/spec/controllers/settings/profiles_controller_spec.rb index e45596b1a..563e60271 100644 --- a/spec/controllers/settings/profiles_controller_spec.rb +++ b/spec/controllers/settings/profiles_controller_spec.rb @@ -44,12 +44,4 @@ RSpec.describe Settings::ProfilesController, type: :controller do expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id) end end - - describe 'PUT #update with oversized image' do - it 'gives the user an error message' do - allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async) - put :update, params: { account: { avatar: fixture_file_upload('4096x4097.png', 'image/png') } } - expect(response.body).to include('images are not supported') - end - end end diff --git a/yarn.lock b/yarn.lock index d2be342c9..0dc40b469 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4821,11 +4821,6 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -exif-js@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/exif-js/-/exif-js-2.3.0.tgz#9d10819bf571f873813e7640241255ab9ce1a814" - integrity sha1-nRCBm/Vx+HOBPnZAJBJVq5zhqBQ= - exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" -- cgit From e084b5b82da703dac3ade7480286e847c5c1c2cd Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 27 Mar 2023 17:07:37 +0200 Subject: Fix user archive takeout when using OpenStack Swift or S3 providers with no ACL support (#24200) --- app/controllers/backups_controller.rb | 6 +++++- app/models/backup.rb | 2 +- config/initializers/paperclip.rb | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/controllers/backups_controller.rb b/app/controllers/backups_controller.rb index 2f4b400b8..0687b62c5 100644 --- a/app/controllers/backups_controller.rb +++ b/app/controllers/backups_controller.rb @@ -13,7 +13,11 @@ class BackupsController < ApplicationController when :s3 redirect_to @backup.dump.expiring_url(10) when :fog - redirect_to @backup.dump.expiring_url(Time.now.utc + 10) + if Paperclip::Attachment.default_options.dig(:storage, :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 diff --git a/app/models/backup.rb b/app/models/backup.rb index dca06eb58..5feb31d7d 100644 --- a/app/models/backup.rb +++ b/app/models/backup.rb @@ -18,6 +18,6 @@ class Backup < ApplicationRecord belongs_to :user, inverse_of: :backups - has_attached_file :dump, s3_permissions: 'private' + has_attached_file :dump, s3_permissions: ->(*) { ENV['S3_PERMISSION'] == '' ? nil : 'private' } validates_attachment_content_type :dump, content_type: /\Aapplication/ end diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb index 9282c941d..bd37f6709 100644 --- a/config/initializers/paperclip.rb +++ b/config/initializers/paperclip.rb @@ -130,6 +130,7 @@ elsif ENV['SWIFT_ENABLED'] == 'true' openstack_domain_name: ENV.fetch('SWIFT_DOMAIN_NAME') { 'default' }, openstack_region: ENV['SWIFT_REGION'], openstack_cache_ttl: ENV.fetch('SWIFT_CACHE_TTL') { 60 }, + openstack_temp_url_key: ENV['SWIFT_TEMP_URL_KEY'], }, fog_file: { 'Cache-Control' => 'public, max-age=315576000, immutable' }, -- cgit From a9b5598c97fc4d3302b61b260097ef41c2ebe377 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 30 Mar 2023 14:44:00 +0200 Subject: Change user settings to be stored in a more optimal way (#23630) Co-authored-by: Claire --- .rubocop.yml | 8 ++ .rubocop_todo.yml | 1 + .../api/v1/accounts/credentials_controller.rb | 12 +- app/controllers/settings/preferences_controller.rb | 40 +----- app/lib/user_settings_decorator.rb | 155 --------------------- app/lib/user_settings_serializer.rb | 19 +++ app/models/concerns/has_user_settings.rb | 141 +++++++++++++++++++ app/models/user.rb | 59 +------- app/models/user_settings.rb | 99 +++++++++++++ app/models/user_settings/dsl.rb | 37 +++++ app/models/user_settings/glue.rb | 23 +++ app/models/user_settings/namespace.rb | 21 +++ app/models/user_settings/setting.rb | 48 +++++++ app/services/notify_service.rb | 13 +- .../settings/preferences/appearance/show.html.haml | 65 ++++----- .../preferences/notifications/show.html.haml | 36 ++--- .../settings/preferences/other/show.html.haml | 29 ++-- config/initializers/inflections.rb | 1 + config/settings.yml | 34 ----- db/migrate/20230215074327_add_settings_to_users.rb | 7 + db/migrate/20230215074423_move_user_settings.rb | 84 +++++++++++ db/schema.rb | 3 +- lib/tasks/tests.rake | 2 +- .../api/v1/accounts/credentials_controller_spec.rb | 1 + spec/controllers/application_controller_spec.rb | 10 +- .../preferences/notifications_controller_spec.rb | 14 +- .../settings/preferences/other_controller_spec.rb | 14 +- spec/lib/settings/extend_spec.rb | 16 --- spec/lib/settings/scoped_settings_spec.rb | 35 ----- spec/lib/user_settings_decorator_spec.rb | 84 ----------- spec/models/user_settings/namespace_spec.rb | 25 ++++ spec/models/user_settings/setting_spec.rb | 74 ++++++++++ spec/models/user_settings_spec.rb | 110 +++++++++++++++ spec/models/user_spec.rb | 14 +- spec/services/notify_service_spec.rb | 7 +- spec/services/report_service_spec.rb | 3 +- 36 files changed, 818 insertions(+), 526 deletions(-) delete mode 100644 app/lib/user_settings_decorator.rb create mode 100644 app/lib/user_settings_serializer.rb create mode 100644 app/models/concerns/has_user_settings.rb create mode 100644 app/models/user_settings.rb create mode 100644 app/models/user_settings/dsl.rb create mode 100644 app/models/user_settings/glue.rb create mode 100644 app/models/user_settings/namespace.rb create mode 100644 app/models/user_settings/setting.rb create mode 100644 db/migrate/20230215074327_add_settings_to_users.rb create mode 100644 db/migrate/20230215074423_move_user_settings.rb delete mode 100644 spec/lib/settings/extend_spec.rb delete mode 100644 spec/lib/settings/scoped_settings_spec.rb delete mode 100644 spec/lib/user_settings_decorator_spec.rb create mode 100644 spec/models/user_settings/namespace_spec.rb create mode 100644 spec/models/user_settings/setting_spec.rb create mode 100644 spec/models/user_settings_spec.rb (limited to 'app/models') diff --git a/.rubocop.yml b/.rubocop.yml index 1033db92d..b5598b65a 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -185,3 +185,11 @@ Style/TrailingCommaInHashLiteral: Style/SymbolArray: Enabled: false + +# Reason: Prefer less intendation in conditional assignments +# https://docs.rubocop.org/rubocop/cops_style.html#styleredundantbegin +Style/RedundantBegin: + Enabled: false + +RSpec/NamedSubject: + EnforcedStyle: named_only diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 64a6b6b33..4ad266c8c 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -259,6 +259,7 @@ Metrics/ModuleLength: - 'app/helpers/jsonld_helper.rb' - 'app/helpers/statuses_helper.rb' - 'app/models/concerns/account_interactions.rb' + - 'app/models/concerns/has_user_settings.rb' # Configuration parameters: Max, CountKeywordArgs, MaxOptionalParameters. Metrics/ParameterLists: 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/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb index f5d5c1244..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,43 +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_delete_modal, - :setting_auto_play_gif, - :setting_display_media, - :setting_expand_spoilers, - :setting_reduce_motion, - :setting_disable_swiping, - :setting_system_font_ui, - :setting_noindex, - :setting_theme, - :setting_aggregate_reblogs, - :setting_show_application, - :setting_advanced_layout, - :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 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/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb deleted file mode 100644 index 5fb7655a9..000000000 --- a/app/lib/user_settings_decorator.rb +++ /dev/null @@ -1,155 +0,0 @@ -# frozen_string_literal: true - -class UserSettingsDecorator - attr_reader :user, :settings - - def initialize(user) - @user = user - end - - def update(settings) - @settings = settings - process_update - end - - private - - def process_update - user.settings['notification_emails'] = merged_notification_emails if change?('notification_emails') - user.settings['interactions'] = merged_interactions if change?('interactions') - user.settings['default_privacy'] = default_privacy_preference if change?('setting_default_privacy') - user.settings['default_sensitive'] = default_sensitive_preference if change?('setting_default_sensitive') - user.settings['default_language'] = default_language_preference if change?('setting_default_language') - user.settings['unfollow_modal'] = unfollow_modal_preference if change?('setting_unfollow_modal') - user.settings['boost_modal'] = boost_modal_preference if change?('setting_boost_modal') - user.settings['delete_modal'] = delete_modal_preference if change?('setting_delete_modal') - user.settings['auto_play_gif'] = auto_play_gif_preference if change?('setting_auto_play_gif') - user.settings['display_media'] = display_media_preference if change?('setting_display_media') - user.settings['expand_spoilers'] = expand_spoilers_preference if change?('setting_expand_spoilers') - user.settings['reduce_motion'] = reduce_motion_preference if change?('setting_reduce_motion') - user.settings['disable_swiping'] = disable_swiping_preference if change?('setting_disable_swiping') - user.settings['system_font_ui'] = system_font_ui_preference if change?('setting_system_font_ui') - user.settings['noindex'] = noindex_preference if change?('setting_noindex') - user.settings['theme'] = theme_preference if change?('setting_theme') - user.settings['aggregate_reblogs'] = aggregate_reblogs_preference if change?('setting_aggregate_reblogs') - user.settings['show_application'] = show_application_preference if change?('setting_show_application') - user.settings['advanced_layout'] = advanced_layout_preference if change?('setting_advanced_layout') - user.settings['use_blurhash'] = use_blurhash_preference if change?('setting_use_blurhash') - user.settings['use_pending_items'] = use_pending_items_preference if change?('setting_use_pending_items') - user.settings['trends'] = trends_preference if change?('setting_trends') - user.settings['crop_images'] = crop_images_preference if change?('setting_crop_images') - user.settings['always_send_emails'] = always_send_emails_preference if change?('setting_always_send_emails') - end - - def merged_notification_emails - user.settings['notification_emails'].merge coerced_settings('notification_emails').to_h - end - - def merged_interactions - user.settings['interactions'].merge coerced_settings('interactions').to_h - end - - def default_privacy_preference - settings['setting_default_privacy'] - end - - def default_sensitive_preference - boolean_cast_setting 'setting_default_sensitive' - end - - def unfollow_modal_preference - boolean_cast_setting 'setting_unfollow_modal' - end - - def boost_modal_preference - boolean_cast_setting 'setting_boost_modal' - end - - def delete_modal_preference - boolean_cast_setting 'setting_delete_modal' - end - - def system_font_ui_preference - boolean_cast_setting 'setting_system_font_ui' - end - - def auto_play_gif_preference - boolean_cast_setting 'setting_auto_play_gif' - end - - def display_media_preference - settings['setting_display_media'] - end - - def expand_spoilers_preference - boolean_cast_setting 'setting_expand_spoilers' - end - - def reduce_motion_preference - boolean_cast_setting 'setting_reduce_motion' - end - - def disable_swiping_preference - boolean_cast_setting 'setting_disable_swiping' - end - - def noindex_preference - boolean_cast_setting 'setting_noindex' - end - - def show_application_preference - boolean_cast_setting 'setting_show_application' - end - - def theme_preference - settings['setting_theme'] - end - - def default_language_preference - settings['setting_default_language'] - end - - def aggregate_reblogs_preference - boolean_cast_setting 'setting_aggregate_reblogs' - end - - def advanced_layout_preference - boolean_cast_setting 'setting_advanced_layout' - end - - def use_blurhash_preference - boolean_cast_setting 'setting_use_blurhash' - end - - def use_pending_items_preference - boolean_cast_setting 'setting_use_pending_items' - end - - def trends_preference - boolean_cast_setting 'setting_trends' - end - - def crop_images_preference - boolean_cast_setting 'setting_crop_images' - end - - def always_send_emails_preference - boolean_cast_setting 'setting_always_send_emails' - end - - def boolean_cast_setting(key) - ActiveModel::Type::Boolean.new.cast(settings[key]) - end - - def coerced_settings(key) - coerce_values settings.fetch(key, {}) - end - - def coerce_values(params_hash) - params_hash.transform_values { |x| ActiveModel::Type::Boolean.new.cast(x) } - end - - def change?(key) - !settings[key].nil? - end -end diff --git a/app/lib/user_settings_serializer.rb b/app/lib/user_settings_serializer.rb new file mode 100644 index 000000000..10d1be04d --- /dev/null +++ b/app/lib/user_settings_serializer.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class UserSettingsSerializer + def self.load(value) + json = begin + if value.blank? + {} + else + Oj.load(value, symbol_keys: true) + end + end + + UserSettings.new(json) + end + + def self.dump(value) + Oj.dump(value.as_json) + end +end diff --git a/app/models/concerns/has_user_settings.rb b/app/models/concerns/has_user_settings.rb new file mode 100644 index 000000000..b3fa1f683 --- /dev/null +++ b/app/models/concerns/has_user_settings.rb @@ -0,0 +1,141 @@ +# frozen_string_literal: true + +module HasUserSettings + extend ActiveSupport::Concern + + included do + serialize :settings, UserSettingsSerializer + end + + def settings_attributes=(attributes) + settings.update(attributes) + end + + def prefers_noindex? + settings['noindex'] + end + + def preferred_posting_language + valid_locale_cascade(settings['default_language'], locale, I18n.locale) + end + + def setting_auto_play_gif + settings['web.auto_play'] + end + + def setting_default_sensitive + settings['default_sensitive'] + end + + def setting_unfollow_modal + settings['web.unfollow_modal'] + end + + def setting_boost_modal + settings['web.reblog_modal'] + end + + def setting_delete_modal + settings['web.delete_modal'] + end + + def setting_reduce_motion + settings['web.reduce_motion'] + end + + def setting_system_font_ui + settings['web.use_system_font'] + end + + def setting_noindex + settings['noindex'] + end + + def setting_theme + settings['theme'] + end + + def setting_display_media + settings['web.display_media'] + end + + def setting_expand_spoilers + settings['web.expand_content_warnings'] + end + + def setting_default_language + settings['default_language'] + end + + def setting_aggregate_reblogs + settings['aggregate_reblogs'] + end + + def setting_show_application + settings['show_application'] + end + + def setting_advanced_layout + settings['web.advanced_layout'] + end + + def setting_use_blurhash + settings['web.use_blurhash'] + end + + def setting_use_pending_items + settings['web.use_pending_items'] + end + + def setting_trends + settings['web.trends'] + end + + def setting_crop_images + settings['web.crop_images'] + end + + def setting_disable_swiping + settings['web.disable_swiping'] + end + + def setting_always_send_emails + settings['always_send_emails'] + end + + def setting_default_privacy + settings['default_privacy'] || (account.locked? ? 'private' : 'public') + end + + def allows_report_emails? + settings['notification_emails.report'] + end + + def allows_pending_account_emails? + settings['notification_emails.pending_account'] + end + + def allows_appeal_emails? + settings['notification_emails.appeal'] + end + + def allows_trends_review_emails? + settings['notification_emails.trends'] + end + + def aggregates_reblogs? + settings['aggregate_reblogs'] + end + + def shows_application? + settings['show_application'] + end + + def show_all_media? + settings['web.display_media'] == 'show_all' + end + + def hide_all_media? + settings['web.display_media'] == 'hide_all' + end +end diff --git a/app/models/user.rb b/app/models/user.rb index d56a9b9ca..9b225d75f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -39,10 +39,11 @@ # webauthn_id :string # sign_up_ip :inet # role_id :bigint(8) +# settings :text # class User < ApplicationRecord - self.ignored_columns = %w( + self.ignored_columns += %w( remember_created_at remember_token current_sign_in_ip @@ -51,9 +52,9 @@ class User < ApplicationRecord filtered_languages ) - include Settings::Extend include Redisable include LanguagesHelper + include HasUserSettings # The home and list feeds will be stored in Redis for this amount # of time, and status fan-out to followers will include only people @@ -132,13 +133,6 @@ class User < ApplicationRecord has_many :session_activations, dependent: :destroy - delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :delete_modal, - :reduce_motion, :system_font_ui, :noindex, :theme, :display_media, - :expand_spoilers, :default_language, :aggregate_reblogs, :show_application, - :advanced_layout, :use_blurhash, :use_pending_items, :trends, :crop_images, - :disable_swiping, :always_send_emails, - to: :settings, prefix: :setting, allow_nil: false - delegate :can?, to: :role attr_reader :invite_code @@ -302,42 +296,6 @@ class User < ApplicationRecord save! end - def prefers_noindex? - setting_noindex - end - - def preferred_posting_language - valid_locale_cascade(settings.default_language, locale, I18n.locale) - end - - def setting_default_privacy - settings.default_privacy || (account.locked? ? 'private' : 'public') - end - - def allows_report_emails? - settings.notification_emails['report'] - end - - def allows_pending_account_emails? - settings.notification_emails['pending_account'] - end - - def allows_appeal_emails? - settings.notification_emails['appeal'] - end - - def allows_trends_review_emails? - settings.notification_emails['trending_tag'] - end - - def aggregates_reblogs? - @aggregates_reblogs ||= settings.aggregate_reblogs - end - - def shows_application? - @shows_application ||= settings.show_application - end - def token_for_app(app) return nil if app.nil? || app.owner != self @@ -417,14 +375,6 @@ class User < ApplicationRecord send_reset_password_instructions end - def show_all_media? - setting_display_media == 'show_all' - end - - def hide_all_media? - setting_display_media == 'hide_all' - end - protected def send_devise_notification(notification, *args, **kwargs) @@ -494,7 +444,8 @@ class User < ApplicationRecord def sanitize_languages return if chosen_languages.nil? - chosen_languages.reject!(&:blank?) + chosen_languages.compact_blank! + self.chosen_languages = nil if chosen_languages.empty? end diff --git a/app/models/user_settings.rb b/app/models/user_settings.rb new file mode 100644 index 000000000..2c025d6c5 --- /dev/null +++ b/app/models/user_settings.rb @@ -0,0 +1,99 @@ +# frozen_string_literal: true + +class UserSettings + class Error < StandardError; end + class KeyError < Error; end + + include UserSettings::DSL + include UserSettings::Glue + + setting :always_send_emails, default: false + setting :aggregate_reblogs, default: true + setting :theme, default: -> { ::Setting.theme } + setting :noindex, default: -> { ::Setting.noindex } + setting :show_application, default: true + setting :default_language, default: nil + setting :default_sensitive, default: false + setting :default_privacy, default: nil + + namespace :web do + setting :crop_images, default: true + setting :advanced_layout, default: false + setting :trends, default: true + setting :use_blurhash, default: true + setting :use_pending_items, default: false + setting :use_system_font, default: false + setting :disable_swiping, default: false + setting :delete_modal, default: true + setting :reblog_modal, default: false + setting :unfollow_modal, default: true + setting :reduce_motion, default: false + setting :expand_content_warnings, default: false + setting :display_media, default: 'default', in: %w(default show_all hide_all) + setting :auto_play, default: false + end + + namespace :notification_emails do + setting :follow, default: true + setting :reblog, default: false + setting :favourite, default: false + setting :mention, default: true + setting :follow_request, default: true + setting :report, default: true + setting :pending_account, default: true + setting :trends, default: true + setting :appeal, default: true + end + + namespace :interactions do + setting :must_be_follower, default: false + setting :must_be_following, default: false + setting :must_be_following_dm, default: false + end + + def initialize(original_hash) + @original_hash = original_hash || {} + end + + def [](key) + key = key.to_sym + + raise KeyError, "Undefined setting: #{key}" unless self.class.definition_for?(key) + + if @original_hash.key?(key) + @original_hash[key] + else + self.class.definition_for(key).default_value + end + end + + def []=(key, value) + key = key.to_sym + + raise KeyError, "Undefined setting: #{key}" unless self.class.definition_for?(key) + + typecast_value = self.class.definition_for(key).type_cast(value) + + if typecast_value.nil? + @original_hash.delete(key) + else + @original_hash[key] = typecast_value + end + end + + def update(params) + params.each do |k, v| + self[k] = v unless v.nil? + end + end + + keys.each do |key| + define_method(key) do + self[key] + end + end + + def as_json + @original_hash + end +end diff --git a/app/models/user_settings/dsl.rb b/app/models/user_settings/dsl.rb new file mode 100644 index 000000000..26238bbbe --- /dev/null +++ b/app/models/user_settings/dsl.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +module UserSettings::DSL + module ClassMethods + def setting(key, options = {}) + @definitions ||= {} + + UserSettings::Setting.new(key, options).tap do |s| + @definitions[s.key] = s + end + end + + def namespace(key, &block) + @definitions ||= {} + + UserSettings::Namespace.new(key).configure(&block).tap do |n| + @definitions.merge!(n.definitions) + end + end + + def keys + @definitions.keys + end + + def definition_for(key) + @definitions[key.to_sym] + end + + def definition_for?(key) + @definitions.key?(key.to_sym) + end + end + + def self.included(base) + base.extend ClassMethods + end +end diff --git a/app/models/user_settings/glue.rb b/app/models/user_settings/glue.rb new file mode 100644 index 000000000..02066a411 --- /dev/null +++ b/app/models/user_settings/glue.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module UserSettings::Glue + def to_model + self + end + + def to_key + '' + end + + def persisted? + false + end + + def type_for_attribute(key) + self.class.definition_for(key)&.type + end + + def has_attribute?(key) # rubocop:disable Naming/PredicateName + self.class.definition_for?(key) + end +end diff --git a/app/models/user_settings/namespace.rb b/app/models/user_settings/namespace.rb new file mode 100644 index 000000000..b8f7e092e --- /dev/null +++ b/app/models/user_settings/namespace.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class UserSettings::Namespace + attr_reader :name, :definitions + + def initialize(name) + @name = name.to_sym + @definitions = {} + end + + def configure(&block) + instance_eval(&block) + self + end + + def setting(key, options = {}) + UserSettings::Setting.new(key, options.merge(namespace: name)).tap do |s| + @definitions[s.key] = s + end + end +end diff --git a/app/models/user_settings/setting.rb b/app/models/user_settings/setting.rb new file mode 100644 index 000000000..c359c593b --- /dev/null +++ b/app/models/user_settings/setting.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +class UserSettings::Setting + attr_reader :name, :namespace, :in + + def initialize(name, options = {}) + @name = name.to_sym + @default_value = options[:default] + @namespace = options[:namespace] + @in = options[:in] + end + + def default_value + if @default_value.respond_to?(:call) + @default_value.call + else + @default_value + end + end + + def type + if @default_value.is_a?(TrueClass) || @default_value.is_a?(FalseClass) + ActiveModel::Type::Boolean.new + else + ActiveModel::Type::String.new + end + end + + def type_cast(value) + if type.respond_to?(:cast) + type.cast(value) + else + value + end + end + + def to_a + [key, default_value] + end + + def key + if namespace + "#{namespace}.#{name}".to_sym + else + name + end + end +end diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index 4c7acbcac..994ca588a 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -3,6 +3,11 @@ class NotifyService < BaseService include Redisable + NON_EMAIL_TYPES = %i( + admin.report + admin.sign_up + ).freeze + def call(recipient, type, activity) @recipient = recipient @activity = activity @@ -36,11 +41,11 @@ class NotifyService < BaseService end def optional_non_follower? - @recipient.user.settings.interactions['must_be_follower'] && !@notification.from_account.following?(@recipient) + @recipient.user.settings['interactions.must_be_follower'] && !@notification.from_account.following?(@recipient) end def optional_non_following? - @recipient.user.settings.interactions['must_be_following'] && !following_sender? + @recipient.user.settings['interactions.must_be_following'] && !following_sender? end def message? @@ -82,7 +87,7 @@ class NotifyService < BaseService def optional_non_following_and_direct? direct_message? && - @recipient.user.settings.interactions['must_be_following_dm'] && + @recipient.user.settings['interactions.must_be_following_dm'] && !following_sender? && !response_to_recipient? end @@ -171,6 +176,6 @@ class NotifyService < BaseService end def send_email_for_notification_type? - @recipient.user.settings.notification_emails[@notification.type.to_s] + NON_EMAIL_TYPES.exclude?(@notification.type) && @recipient.user.settings["notification_emails.#{@notification.type}"] end end diff --git a/app/views/settings/preferences/appearance/show.html.haml b/app/views/settings/preferences/appearance/show.html.haml index bc23df647..5358310e5 100644 --- a/app/views/settings/preferences/appearance/show.html.haml +++ b/app/views/settings/preferences/appearance/show.html.haml @@ -9,57 +9,58 @@ .fields-group.fields-row__column.fields-row__column-6 = f.input :locale, collection: I18n.available_locales, wrapper: :with_label, include_blank: false, label_method: lambda { |locale| native_locale_name(locale) }, selected: I18n.locale, hint: false .fields-group.fields-row__column.fields-row__column-6 - = f.input :setting_theme, collection: Themes.instance.names, label_method: lambda { |theme| I18n.t("themes.#{theme}", default: theme) }, wrapper: :with_label, include_blank: false, hint: false + = f.simple_fields_for :settings, current_user.settings do |ff| + = ff.input :theme, collection: Themes.instance.names, label_method: lambda { |theme| I18n.t("themes.#{theme}", default: theme) }, wrapper: :with_label, include_blank: false, hint: false - unless I18n.locale == :en .flash-message.translation-prompt #{t 'appearance.localization.body'} #{content_tag(:a, t('appearance.localization.guide_link_text'), href: t('appearance.localization.guide_link'), target: '_blank', rel: 'noopener')} - %h4= t 'appearance.advanced_web_interface' + = f.simple_fields_for :settings, current_user.settings do |ff| + %h4= t 'appearance.advanced_web_interface' - %p.hint= t 'appearance.advanced_web_interface_hint' + %p.hint= t 'appearance.advanced_web_interface_hint' - .fields-group - = f.input :setting_advanced_layout, as: :boolean, wrapper: :with_label, hint: false + .fields-group + = ff.input :'web.advanced_layout', wrapper: :with_label, hint: false, label: I18n.t('simple_form.labels.defaults.setting_advanced_layout') + %h4= t 'appearance.animations_and_accessibility' - %h4= t 'appearance.animations_and_accessibility' + .fields-group + = ff.input :'web.use_pending_items', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_use_pending_items'), hint: I18n.t('simple_form.hints.defaults.setting_use_pending_items') - .fields-group - = f.input :setting_use_pending_items, as: :boolean, wrapper: :with_label + .fields-group + = ff.input :'web.auto_play', wrapper: :with_label, recommended: true, label: I18n.t('simple_form.labels.defaults.setting_auto_play_gif') + = ff.input :'web.reduce_motion', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_reduce_motion') + = ff.input :'web.disable_swiping', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_disable_swiping') + = ff.input :'web.use_system_font', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_system_font_ui') - .fields-group - = f.input :setting_auto_play_gif, as: :boolean, wrapper: :with_label, recommended: true - = f.input :setting_reduce_motion, as: :boolean, wrapper: :with_label - = f.input :setting_disable_swiping, as: :boolean, wrapper: :with_label - = f.input :setting_system_font_ui, as: :boolean, wrapper: :with_label + %h4= t 'appearance.toot_layout' - %h4= t 'appearance.toot_layout' + .fields-group + = ff.input :'web.crop_images', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_crop_images') - .fields-group - = f.input :setting_crop_images, as: :boolean, wrapper: :with_label + %h4= t 'appearance.discovery' - %h4= t 'appearance.discovery' + .fields-group + = ff.input :'web.trends', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_trends') - .fields-group - = f.input :setting_trends, as: :boolean, wrapper: :with_label + %h4= t 'appearance.confirmation_dialogs' - %h4= t 'appearance.confirmation_dialogs' + .fields-group + = ff.input :'web.unfollow_modal', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_unfollow_modal') + = ff.input :'web.reblog_modal', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_boost_modal') + = ff.input :'web.delete_modal', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_delete_modal') - .fields-group - = f.input :setting_unfollow_modal, as: :boolean, wrapper: :with_label - = f.input :setting_boost_modal, as: :boolean, wrapper: :with_label - = f.input :setting_delete_modal, as: :boolean, wrapper: :with_label + %h4= t 'appearance.sensitive_content' - %h4= t 'appearance.sensitive_content' + .fields-group + = ff.input :'web.display_media', collection: ['default', 'show_all', 'hide_all'],label_method: lambda { |item| t("simple_form.hints.defaults.setting_display_media_#{item}") }, hint: false, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', wrapper: :with_floating_label, label: I18n.t('simple_form.labels.defaults.setting_display_media') - .fields-group - = f.input :setting_display_media, collection: ['default', 'show_all', 'hide_all'], label_method: lambda { |item| t("simple_form.hints.defaults.setting_display_media_#{item}") }, hint: false, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', wrapper: :with_floating_label + .fields-group + = ff.input :'web.use_blurhash', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_use_blurhash'), hint: I18n.t('simple_form.hints.defaults.setting_use_blurhash') - .fields-group - = f.input :setting_use_blurhash, as: :boolean, wrapper: :with_label - - .fields-group - = f.input :setting_expand_spoilers, as: :boolean, wrapper: :with_label + .fields-group + = ff.input :'web.expand_content_warnings', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_expand_spoilers') .actions = f.button :button, t('generic.save_changes'), type: :submit diff --git a/app/views/settings/preferences/notifications/show.html.haml b/app/views/settings/preferences/notifications/show.html.haml index f00dbadd4..cb1ad0886 100644 --- a/app/views/settings/preferences/notifications/show.html.haml +++ b/app/views/settings/preferences/notifications/show.html.haml @@ -11,25 +11,25 @@ %p.hint= t 'notifications.email_events_hint' - .fields-group - = f.simple_fields_for :notification_emails, hash_to_object(current_user.settings.notification_emails) do |ff| - = ff.input :follow, as: :boolean, wrapper: :with_label - = ff.input :follow_request, as: :boolean, wrapper: :with_label - = ff.input :reblog, as: :boolean, wrapper: :with_label - = ff.input :favourite, as: :boolean, wrapper: :with_label - = ff.input :mention, as: :boolean, wrapper: :with_label - = ff.input :report, as: :boolean, wrapper: :with_label if current_user.can?(:manage_reports) - = ff.input :appeal, as: :boolean, wrapper: :with_label if current_user.can?(:manage_appeals) - = ff.input :pending_account, as: :boolean, wrapper: :with_label if current_user.can?(:manage_users) - = ff.input :trending_tag, as: :boolean, wrapper: :with_label if current_user.can?(:manage_taxonomies) - - .fields-group - = f.input :setting_always_send_emails, as: :boolean, wrapper: :with_label + = f.simple_fields_for :settings, current_user.settings do |ff| + .fields-group + = ff.input :'notification_emails.follow', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.follow') + = ff.input :'notification_emails.follow_request', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.follow_request') + = ff.input :'notification_emails.reblog', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.reblog') + = ff.input :'notification_emails.favourite', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.favourite') + = ff.input :'notification_emails.mention', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.mention') + = ff.input :'notification_emails.report', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.report') if current_user.can?(:manage_reports) + = ff.input :'notification_emails.appeal', as: :boolean, wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.appeal') if current_user.can?(:manage_appeals) + = ff.input :'notification_emails.pending_account', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.pending_account') if current_user.can?(:manage_users) + = ff.input :'notification_emails.trends', wrapper: :with_label, label: I18n.t('simple_form.labels.notification_emails.trending_tag') if current_user.can?(:manage_taxonomies) + + .fields-group + = ff.input :always_send_emails, wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_always_send_emails'), hint: I18n.t('simple_form.hints.defaults.setting_always_send_emails') %h4= t 'notifications.other_settings' .fields-group - = f.simple_fields_for :interactions, hash_to_object(current_user.settings.interactions) do |ff| - = ff.input :must_be_follower, as: :boolean, wrapper: :with_label - = ff.input :must_be_following, as: :boolean, wrapper: :with_label - = ff.input :must_be_following_dm, as: :boolean, wrapper: :with_label + = f.simple_fields_for :settings, current_user.settings do |ff| + = ff.input :'interactions.must_be_follower', wrapper: :with_label, label: I18n.t('simple_form.labels.interactions.must_be_follower') + = ff.input :'interactions.must_be_following', wrapper: :with_label, label: I18n.t('simple_form.labels.interactions.must_be_following') + = ff.input :'interactions.must_be_following_dm', wrapper: :with_label, label: I18n.t('simple_form.labels.interactions.must_be_following_dm') diff --git a/app/views/settings/preferences/other/show.html.haml b/app/views/settings/preferences/other/show.html.haml index 44f4af2eb..6590ec7c2 100644 --- a/app/views/settings/preferences/other/show.html.haml +++ b/app/views/settings/preferences/other/show.html.haml @@ -7,26 +7,27 @@ = simple_form_for current_user, url: settings_preferences_other_path, html: { method: :put, id: 'edit_preferences' } do |f| = render 'shared/error_messages', object: current_user - .fields-group - = f.input :setting_noindex, as: :boolean, wrapper: :with_label + = f.simple_fields_for :settings, current_user.settings do |ff| + .fields-group + = ff.input :noindex, wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_noindex'), hint: I18n.t('simple_form.hints.defaults.setting_noindex') - .fields-group - = f.input :setting_aggregate_reblogs, as: :boolean, wrapper: :with_label, recommended: true + .fields-group + = ff.input :aggregate_reblogs, wrapper: :with_label, recommended: true, label: I18n.t('simple_form.labels.defaults.setting_aggregate_reblogs'), hint: I18n.t('simple_form.hints.defaults.setting_aggregate_reblogs') - %h4= t 'preferences.posting_defaults' + %h4= t 'preferences.posting_defaults' - .fields-row - .fields-group.fields-row__column.fields-row__column-6 - = f.input :setting_default_privacy, collection: Status.selectable_visibilities, wrapper: :with_label, include_blank: false, label_method: lambda { |visibility| safe_join([I18n.t("statuses.visibilities.#{visibility}"), I18n.t("statuses.visibilities.#{visibility}_long")], ' - ') }, required: false, hint: false + .fields-row + .fields-group.fields-row__column.fields-row__column-6 + = ff.input :default_privacy, collection: Status.selectable_visibilities, wrapper: :with_label, include_blank: false, label_method: lambda { |visibility| safe_join([I18n.t("statuses.visibilities.#{visibility}"), I18n.t("statuses.visibilities.#{visibility}_long")], ' - ') }, required: false, hint: false, label: I18n.t('simple_form.labels.defaults.setting_default_privacy') - .fields-group.fields-row__column.fields-row__column-6 - = f.input :setting_default_language, collection: [nil] + filterable_languages, wrapper: :with_label, label_method: lambda { |locale| locale.nil? ? I18n.t('statuses.default_language') : native_locale_name(locale) }, required: false, include_blank: false, hint: false + .fields-group.fields-row__column.fields-row__column-6 + = ff.input :default_language, collection: [nil] + filterable_languages, wrapper: :with_label, label_method: lambda { |locale| locale.nil? ? I18n.t('statuses.default_language') : native_locale_name(locale) }, required: false, include_blank: false, hint: false, label: I18n.t('simple_form.labels.defaults.setting_default_language') - .fields-group - = f.input :setting_default_sensitive, as: :boolean, wrapper: :with_label + .fields-group + = ff.input :default_sensitive, wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_default_sensitive'), hint: I18n.t('simple_form.hints.defaults.setting_default_sensitive') - .fields-group - = f.input :setting_show_application, as: :boolean, wrapper: :with_label, recommended: true + .fields-group + = ff.input :show_application, wrapper: :with_label, recommended: true, label: I18n.t('simple_form.labels.defaults.setting_show_application'), hint: I18n.t('simple_form.hints.defaults.setting_show_application') %h4= t 'preferences.public_timelines' diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index a361cb0ec..95f0b5788 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -26,6 +26,7 @@ ActiveSupport::Inflector.inflections(:en) do |inflect| inflect.acronym 'URL' inflect.acronym 'ASCII' inflect.acronym 'DeepL' + inflect.acronym 'DSL' inflect.singular 'data', 'data' end diff --git a/config/settings.yml b/config/settings.yml index f0b09dd5c..4ac521a4b 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -12,48 +12,14 @@ defaults: &defaults registrations_mode: 'open' profile_directory: true closed_registrations_message: '' - open_deletion: true - min_invite_role: 'admin' timeline_preview: true show_staff_badge: true - default_sensitive: false - unfollow_modal: false - boost_modal: false - delete_modal: true - auto_play_gif: false - display_media: 'default' - expand_spoilers: false preview_sensitive_media: false - reduce_motion: false - disable_swiping: false - show_application: true - system_font_ui: false noindex: false theme: 'default' - aggregate_reblogs: true - advanced_layout: false - use_blurhash: true - use_pending_items: false trends: true trends_as_landing_page: true trendable_by_default: false - crop_images: true - notification_emails: - follow: true - reblog: false - favourite: false - mention: true - follow_request: true - digest: true - report: true - pending_account: true - trending_tag: true - appeal: true - always_send_emails: false - interactions: - must_be_follower: false - must_be_following: false - must_be_following_dm: false reserved_usernames: - admin - support diff --git a/db/migrate/20230215074327_add_settings_to_users.rb b/db/migrate/20230215074327_add_settings_to_users.rb new file mode 100644 index 000000000..ff5308f42 --- /dev/null +++ b/db/migrate/20230215074327_add_settings_to_users.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddSettingsToUsers < ActiveRecord::Migration[6.1] + def change + add_column :users, :settings, :text + end +end diff --git a/db/migrate/20230215074423_move_user_settings.rb b/db/migrate/20230215074423_move_user_settings.rb new file mode 100644 index 000000000..351a8b61d --- /dev/null +++ b/db/migrate/20230215074423_move_user_settings.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +class MoveUserSettings < ActiveRecord::Migration[6.1] + class User < ApplicationRecord; end + + MAPPING = { + default_privacy: 'default_privacy', + default_sensitive: 'web.default_sensitive', + default_language: 'default_language', + noindex: 'noindex', + theme: 'theme', + trends: 'web.trends', + unfollow_modal: 'web.unfollow_modal', + boost_modal: 'web.reblog_modal', + delete_modal: 'web.delete_modal', + auto_play_gif: 'web.auto_play', + display_media: 'web.display_media', + expand_spoilers: 'web.expand_content_warnings', + reduce_motion: 'web.reduce_motion', + disable_swiping: 'web.disable_swiping', + show_application: 'show_application', + system_font_ui: 'web.use_system_font', + aggregate_reblogs: 'aggregate_reblogs', + advanced_layout: 'web.advanced_layout', + use_blurhash: 'web.use_blurhash', + use_pending_items: 'web.use_pending_items', + crop_images: 'web.crop_images', + notification_emails: { + follow: 'notification_emails.follow', + reblog: 'notification_emails.reblog', + favourite: 'notification_emails.favourite', + mention: 'notification_emails.mention', + follow_request: 'notification_emails.follow_request', + report: 'notification_emails.report', + pending_account: 'notification_emails.pending_account', + trending_tag: 'notification_emails.trends', + appeal: 'notification_emails.appeal', + }.freeze, + always_send_emails: 'always_send_emails', + interactions: { + must_be_follower: 'interactions.must_be_follower', + must_be_following: 'interactions.must_be_following', + must_be_following_dm: 'interactions.must_be_following_dm', + }.freeze, + }.freeze + + class LegacySetting < ApplicationRecord + self.table_name = 'settings' + + def var + self[:var]&.to_sym + end + + def value + YAML.safe_load(self[:value], permitted_classes: [ActiveSupport::HashWithIndifferentAccess]) if self[:value].present? + end + end + + def up + User.find_each do |user| + previous_settings = LegacySetting.where(thing_type: 'User', thing_id: user.id).index_by(&:var) + + user_settings = {} + + MAPPING.each do |legacy_key, new_key| + value = previous_settings[legacy_key]&.value + + next if value.blank? + + if value.is_a?(Hash) + value.each do |nested_key, nested_value| + user_settings[MAPPING[legacy_key][nested_key.to_sym]] = nested_value + end + else + user_settings[new_key] = value + end + end + + user.update_column('settings', Oj.dump(user_settings)) # rubocop:disable Rails/SkipsModelValidations + end + end + + def down; end +end diff --git a/db/schema.rb b/db/schema.rb index 704cef122..620bed2bc 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2022_12_06_114142) do +ActiveRecord::Schema.define(version: 2023_02_15_074423) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -1060,6 +1060,7 @@ ActiveRecord::Schema.define(version: 2022_12_06_114142) do t.inet "sign_up_ip" t.boolean "skip_sign_in_token" t.bigint "role_id" + t.text "settings" t.index ["account_id"], name: "index_users_on_account_id" t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["created_by_application_id"], name: "index_users_on_created_by_application_id", where: "(created_by_application_id IS NOT NULL)" diff --git a/lib/tasks/tests.rake b/lib/tasks/tests.rake index 51a6ee0d7..35073b78b 100644 --- a/lib/tasks/tests.rake +++ b/lib/tasks/tests.rake @@ -54,7 +54,7 @@ namespace :tests do exit(1) end - unless User.find(1).settings.notification_emails['favourite'] == true && User.find(1).settings.notification_emails['mention'] == false + unless User.find(1).settings['notification_emails.favourite'] == true && User.find(1).settings['notification_emails.mention'] == false puts 'User settings not kept as expected' exit(1) end diff --git a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb index 57fe0aee6..b5d5c37a9 100644 --- a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb @@ -46,6 +46,7 @@ describe Api::V1::Accounts::CredentialsController do end it 'updates account info' do + user.reload user.account.reload expect(user.account.display_name).to eq("Alice Isn't Dead") diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 35c7326cb..bc6c6c0c5 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -88,21 +88,19 @@ describe ApplicationController, type: :controller do it 'returns instances\'s default theme when user didn\'t set theme' do current_user = Fabricate(:user) + current_user.settings.update(theme: 'contrast', noindex: false) + current_user.save sign_in current_user - allow(Setting).to receive(:[]).with('theme').and_return 'contrast' - allow(Setting).to receive(:[]).with('noindex').and_return false - expect(controller.view_context.current_theme).to eq 'contrast' end it 'returns user\'s theme when it is set' do current_user = Fabricate(:user) - current_user.settings['theme'] = 'mastodon-light' + current_user.settings.update(theme: 'mastodon-light') + current_user.save sign_in current_user - allow(Setting).to receive(:[]).with('theme').and_return 'contrast' - expect(controller.view_context.current_theme).to eq 'mastodon-light' end end diff --git a/spec/controllers/settings/preferences/notifications_controller_spec.rb b/spec/controllers/settings/preferences/notifications_controller_spec.rb index 66fb8c5eb..29b7b6aec 100644 --- a/spec/controllers/settings/preferences/notifications_controller_spec.rb +++ b/spec/controllers/settings/preferences/notifications_controller_spec.rb @@ -20,20 +20,22 @@ describe Settings::Preferences::NotificationsController do describe 'PUT #update' do it 'updates notifications settings' do - user.settings['notification_emails'] = user.settings['notification_emails'].merge('follow' => false) - user.settings['interactions'] = user.settings['interactions'].merge('must_be_follower' => true) + user.settings.update('notification_emails.follow': false, 'interactions.must_be_follower': true) + user.save put :update, params: { user: { - notification_emails: { follow: '1' }, - interactions: { must_be_follower: '0' }, + settings_attributes: { + 'notification_emails.follow': '1', + 'interactions.must_be_follower': '0', + }, }, } expect(response).to redirect_to(settings_preferences_notifications_path) user.reload - expect(user.settings['notification_emails']['follow']).to be true - expect(user.settings['interactions']['must_be_follower']).to be false + expect(user.settings['notification_emails.follow']).to be true + expect(user.settings['interactions.must_be_follower']).to be false end end end diff --git a/spec/controllers/settings/preferences/other_controller_spec.rb b/spec/controllers/settings/preferences/other_controller_spec.rb index 63eeefaf0..249d1b5b5 100644 --- a/spec/controllers/settings/preferences/other_controller_spec.rb +++ b/spec/controllers/settings/preferences/other_controller_spec.rb @@ -29,20 +29,22 @@ describe Settings::Preferences::OtherController do end it 'updates user settings' do - user.settings['boost_modal'] = false - user.settings['delete_modal'] = true + user.settings.update('web.reblog_modal': false, 'web.delete_modal': true) + user.save put :update, params: { user: { - setting_boost_modal: '1', - setting_delete_modal: '0', + settings_attributes: { + 'web.reblog_modal': '1', + 'web.delete_modal': '0', + }, }, } expect(response).to redirect_to(settings_preferences_other_path) user.reload - expect(user.settings['boost_modal']).to be true - expect(user.settings['delete_modal']).to be false + expect(user.settings['web.reblog_modal']).to be true + expect(user.settings['web.delete_modal']).to be false end end end diff --git a/spec/lib/settings/extend_spec.rb b/spec/lib/settings/extend_spec.rb deleted file mode 100644 index ea623137b..000000000 --- a/spec/lib/settings/extend_spec.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe Settings::Extend do - class User - include Settings::Extend - end - - describe '#settings' do - it 'sets @settings as an instance of Settings::ScopedSettings' do - user = Fabricate(:user) - expect(user.settings).to be_a Settings::ScopedSettings - end - end -end diff --git a/spec/lib/settings/scoped_settings_spec.rb b/spec/lib/settings/scoped_settings_spec.rb deleted file mode 100644 index 7566685b4..000000000 --- a/spec/lib/settings/scoped_settings_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe Settings::ScopedSettings do - let(:object) { Fabricate(:user) } - let(:scoped_setting) { described_class.new(object) } - let(:val) { 'whatever' } - let(:methods) { %i(auto_play_gif default_sensitive unfollow_modal boost_modal delete_modal reduce_motion system_font_ui noindex theme) } - - describe '.initialize' do - it 'sets @object' do - scoped_setting = described_class.new(object) - expect(scoped_setting.instance_variable_get(:@object)).to be object - end - end - - describe '#method_missing' do - it 'sets scoped_setting.method_name = val' do - methods.each do |key| - scoped_setting.send("#{key}=", val) - expect(scoped_setting.send(key)).to eq val - end - end - end - - describe '#[]= and #[]' do - it 'sets [key] = val' do - methods.each do |key| - scoped_setting[key] = val - expect(scoped_setting[key]).to eq val - end - end - end -end diff --git a/spec/lib/user_settings_decorator_spec.rb b/spec/lib/user_settings_decorator_spec.rb deleted file mode 100644 index 3b9b7ee2b..000000000 --- a/spec/lib/user_settings_decorator_spec.rb +++ /dev/null @@ -1,84 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -describe UserSettingsDecorator do - describe 'update' do - let(:user) { Fabricate(:user) } - let(:settings) { described_class.new(user) } - - it 'updates the user settings value for email notifications' do - values = { 'notification_emails' => { 'follow' => '1' } } - - settings.update(values) - expect(user.settings['notification_emails']['follow']).to be true - end - - it 'updates the user settings value for interactions' do - values = { 'interactions' => { 'must_be_follower' => '0' } } - - settings.update(values) - expect(user.settings['interactions']['must_be_follower']).to be false - end - - it 'updates the user settings value for privacy' do - values = { 'setting_default_privacy' => 'public' } - - settings.update(values) - expect(user.settings['default_privacy']).to eq 'public' - end - - it 'updates the user settings value for sensitive' do - values = { 'setting_default_sensitive' => '1' } - - settings.update(values) - expect(user.settings['default_sensitive']).to be true - end - - it 'updates the user settings value for unfollow modal' do - values = { 'setting_unfollow_modal' => '0' } - - settings.update(values) - expect(user.settings['unfollow_modal']).to be false - end - - it 'updates the user settings value for boost modal' do - values = { 'setting_boost_modal' => '1' } - - settings.update(values) - expect(user.settings['boost_modal']).to be true - end - - it 'updates the user settings value for delete toot modal' do - values = { 'setting_delete_modal' => '0' } - - settings.update(values) - expect(user.settings['delete_modal']).to be false - end - - it 'updates the user settings value for gif auto play' do - values = { 'setting_auto_play_gif' => '0' } - - settings.update(values) - expect(user.settings['auto_play_gif']).to be false - end - - it 'updates the user settings value for system font in UI' do - values = { 'setting_system_font_ui' => '0' } - - settings.update(values) - expect(user.settings['system_font_ui']).to be false - end - - it 'decoerces setting values before applying' do - values = { - 'setting_delete_modal' => 'false', - 'setting_boost_modal' => 'true', - } - - settings.update(values) - expect(user.settings['delete_modal']).to be false - expect(user.settings['boost_modal']).to be true - end - end -end diff --git a/spec/models/user_settings/namespace_spec.rb b/spec/models/user_settings/namespace_spec.rb new file mode 100644 index 000000000..ae2fa7b48 --- /dev/null +++ b/spec/models/user_settings/namespace_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe UserSettings::Namespace do + subject { described_class.new(name) } + + let(:name) { :foo } + + describe '#setting' do + before do + subject.setting :bar, default: 'baz' + end + + it 'adds setting to definitions' do + expect(subject.definitions[:'foo.bar']).to have_attributes(name: :bar, namespace: :foo, default_value: 'baz') + end + end + + describe '#definitions' do + it 'returns a hash' do + expect(subject.definitions).to be_a Hash + end + end +end diff --git a/spec/models/user_settings/setting_spec.rb b/spec/models/user_settings/setting_spec.rb new file mode 100644 index 000000000..6e4ec6789 --- /dev/null +++ b/spec/models/user_settings/setting_spec.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe UserSettings::Setting do + subject { described_class.new(name, options) } + + let(:name) { :foo } + let(:options) { { default: default, namespace: namespace } } + let(:default) { false } + let(:namespace) { nil } + + describe '#default_value' do + context 'when default value is a primitive value' do + it 'returns default value' do + expect(subject.default_value).to eq default + end + end + + context 'when default value is a proc' do + let(:default) { -> { 'bar' } } + + it 'returns value from proc' do + expect(subject.default_value).to eq 'bar' + end + end + end + + describe '#type' do + it 'returns a type' do + expect(subject.type).to be_a ActiveModel::Type::Value + end + end + + describe '#type_cast' do + context 'when default value is a boolean' do + let(:default) { false } + + it 'returns boolean' do + expect(subject.type_cast('1')).to be true + end + end + + context 'when default value is a string' do + let(:default) { '' } + + it 'returns string' do + expect(subject.type_cast(1)).to eq '1' + end + end + end + + describe '#to_a' do + it 'returns an array' do + expect(subject.to_a).to eq [name, default] + end + end + + describe '#key' do + context 'when there is no namespace' do + it 'returnsn a symbol' do + expect(subject.key).to eq :foo + end + end + + context 'when there is a namespace' do + let(:namespace) { :bar } + + it 'returns a symbol' do + expect(subject.key).to eq :'bar.foo' + end + end + end +end diff --git a/spec/models/user_settings_spec.rb b/spec/models/user_settings_spec.rb new file mode 100644 index 000000000..f0e4272fd --- /dev/null +++ b/spec/models/user_settings_spec.rb @@ -0,0 +1,110 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe UserSettings do + subject { described_class.new(json) } + + let(:json) { {} } + + describe '#[]' do + context 'when setting is not set' do + it 'returns default value' do + expect(subject[:always_send_emails]).to be false + end + end + + context 'when setting is set' do + let(:json) { { default_language: 'fr' } } + + it 'returns value' do + expect(subject[:default_language]).to eq 'fr' + end + end + + context 'when setting was not defined' do + it 'raises error' do + expect { subject[:foo] }.to raise_error UserSettings::KeyError + end + end + end + + describe '#[]=' do + context 'when value matches type' do + before do + subject[:always_send_emails] = true + end + + it 'updates value' do + expect(subject[:always_send_emails]).to be true + end + end + + context 'when value needs to be type-cast' do + before do + subject[:always_send_emails] = '1' + end + + it 'updates value with a type-cast' do + expect(subject[:always_send_emails]).to be true + end + end + end + + describe '#update' do + before do + subject.update(always_send_emails: true, default_language: 'fr', default_privacy: nil) + end + + it 'updates values' do + expect(subject[:always_send_emails]).to be true + expect(subject[:default_language]).to eq 'fr' + end + + it 'does not set values that are nil' do + expect(subject.as_json).to_not include(default_privacy: nil) + end + end + + describe '#as_json' do + let(:json) { { default_language: 'fr' } } + + it 'returns hash' do + expect(subject.as_json).to eq json + end + end + + describe '.keys' do + it 'returns an array' do + expect(described_class.keys).to be_a Array + end + end + + describe '.definition_for' do + context 'when key is defined' do + it 'returns a setting' do + expect(described_class.definition_for(:always_send_emails)).to be_a UserSettings::Setting + end + end + + context 'when key is not defined' do + it 'returns nil' do + expect(described_class.definition_for(:foo)).to be_nil + end + end + end + + describe '.definition_for?' do + context 'when key is defined' do + it 'returns true' do + expect(described_class.definition_for?(:always_send_emails)).to be true + end + end + + context 'when key is not defined' do + it 'returns false' do + expect(described_class.definition_for?(:foo)).to be false + end + end + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 3e7b59f17..ab883927a 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -313,9 +313,9 @@ RSpec.describe User, type: :model do end describe 'settings' do - it 'is instance of Settings::ScopedSettings' do + it 'is instance of UserSettings' do user = Fabricate(:user) - expect(user.settings).to be_a Settings::ScopedSettings + expect(user.settings).to be_a UserSettings end end @@ -379,16 +379,6 @@ RSpec.describe User, type: :model do end end - it_behaves_like 'Settings-extended' do - def create! - User.create!(account: Fabricate(:account, user: nil), email: 'foo@mastodon.space', password: 'abcd1234', agreement: true) - end - - def fabricate - Fabricate(:user) - end - end - describe 'token_for_app' do let(:user) { Fabricate(:user) } let(:app) { Fabricate(:application, owner: user) } diff --git a/spec/services/notify_service_spec.rb b/spec/services/notify_service_spec.rb index c58cebbfb..616a7aa20 100644 --- a/spec/services/notify_service_spec.rb +++ b/spec/services/notify_service_spec.rb @@ -54,7 +54,8 @@ RSpec.describe NotifyService, type: :service do let(:type) { :mention } before do - user.settings.interactions = user.settings.interactions.merge('must_be_following_dm' => enabled) + user.settings.update('interactions.must_be_following_dm': enabled) + user.save end context 'if recipient is supposed to be following sender' do @@ -155,8 +156,8 @@ RSpec.describe NotifyService, type: :service do before do ActionMailer::Base.deliveries.clear - notification_emails = user.settings.notification_emails - user.settings.notification_emails = notification_emails.merge('follow' => enabled) + user.settings.update('notification_emails.follow': enabled) + user.save end context 'when email notification is enabled' do diff --git a/spec/services/report_service_spec.rb b/spec/services/report_service_spec.rb index 9d81bd971..452400f72 100644 --- a/spec/services/report_service_spec.rb +++ b/spec/services/report_service_spec.rb @@ -96,7 +96,8 @@ RSpec.describe ReportService, type: :service do before do ActionMailer::Base.deliveries.clear - source_account.user.settings.notification_emails['report'] = true + source_account.user.settings['notification_emails.report'] = true + source_account.user.save end it 'does not send an e-mail' do -- cgit From b4f38edf74e376f6006def9bf9fc22db40586264 Mon Sep 17 00:00:00 2001 From: Christian Schmidt Date: Fri, 31 Mar 2023 07:33:17 +0200 Subject: Wrong type for user setting when default is defined by lambda (#24321) --- app/models/user_settings/setting.rb | 3 ++- spec/models/user_settings/setting_spec.rb | 32 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/user_settings/setting.rb b/app/models/user_settings/setting.rb index c359c593b..5f5504254 100644 --- a/app/models/user_settings/setting.rb +++ b/app/models/user_settings/setting.rb @@ -19,7 +19,8 @@ class UserSettings::Setting end def type - if @default_value.is_a?(TrueClass) || @default_value.is_a?(FalseClass) + case default_value + when TrueClass, FalseClass ActiveModel::Type::Boolean.new else ActiveModel::Type::String.new diff --git a/spec/models/user_settings/setting_spec.rb b/spec/models/user_settings/setting_spec.rb index 6e4ec6789..9884ae4f8 100644 --- a/spec/models/user_settings/setting_spec.rb +++ b/spec/models/user_settings/setting_spec.rb @@ -30,6 +30,38 @@ RSpec.describe UserSettings::Setting do it 'returns a type' do expect(subject.type).to be_a ActiveModel::Type::Value end + + context 'when default value is a boolean' do + let(:default) { false } + + it 'returns boolean' do + expect(subject.type).to be_a ActiveModel::Type::Boolean + end + end + + context 'when default value is a string' do + let(:default) { '' } + + it 'returns string' do + expect(subject.type).to be_a ActiveModel::Type::String + end + end + + context 'when default value is a lambda returning a boolean' do + let(:default) { -> { false } } + + it 'returns boolean' do + expect(subject.type).to be_a ActiveModel::Type::Boolean + end + end + + context 'when default value is a lambda returning a string' do + let(:default) { -> { '' } } + + it 'returns boolean' do + expect(subject.type).to be_a ActiveModel::Type::String + end + end end describe '#type_cast' do -- cgit From cb2ce842b0626b3ae379017da4cbab20539b782a Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Fri, 31 Mar 2023 09:07:22 -0400 Subject: Autofix Rubocop Rails/IgnoredColumnsAssignment (#23761) --- .rubocop_todo.yml | 11 ----------- app/models/account.rb | 2 +- app/models/account_stat.rb | 2 +- app/models/admin/action_log.rb | 2 +- app/models/custom_filter.rb | 2 +- app/models/email_domain_block.rb | 2 +- app/models/report.rb | 2 +- app/models/status_edit.rb | 2 +- 8 files changed, 7 insertions(+), 18 deletions(-) (limited to 'app/models') diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index e15cb30f5..2e4801a55 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1431,17 +1431,6 @@ Rails/I18nLocaleTexts: - 'lib/tasks/mastodon.rake' - 'spec/helpers/flashes_helper_spec.rb' -# This cop supports unsafe autocorrection (--autocorrect-all). -Rails/IgnoredColumnsAssignment: - Exclude: - - 'app/models/account.rb' - - 'app/models/account_stat.rb' - - 'app/models/admin/action_log.rb' - - 'app/models/custom_filter.rb' - - 'app/models/email_domain_block.rb' - - 'app/models/report.rb' - - 'app/models/status_edit.rb' - # Configuration parameters: IgnoreScopes, Include. # Include: app/models/**/*.rb Rails/InverseOf: diff --git a/app/models/account.rb b/app/models/account.rb index c4df48878..f49cae901 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -53,7 +53,7 @@ # class Account < ApplicationRecord - self.ignored_columns = %w( + self.ignored_columns += %w( subscription_expires_at secret remote_url diff --git a/app/models/account_stat.rb b/app/models/account_stat.rb index 834f8ba4c..0fea7732e 100644 --- a/app/models/account_stat.rb +++ b/app/models/account_stat.rb @@ -16,7 +16,7 @@ class AccountStat < ApplicationRecord self.locking_column = nil - self.ignored_columns = %w(lock_version) + self.ignored_columns += %w(lock_version) belongs_to :account, inverse_of: :account_stat diff --git a/app/models/admin/action_log.rb b/app/models/admin/action_log.rb index 4fa8008f5..f2c121d75 100644 --- a/app/models/admin/action_log.rb +++ b/app/models/admin/action_log.rb @@ -17,7 +17,7 @@ # class Admin::ActionLog < ApplicationRecord - self.ignored_columns = %w( + self.ignored_columns += %w( recorded_changes ) diff --git a/app/models/custom_filter.rb b/app/models/custom_filter.rb index d85e196e9..0f4fd78cb 100644 --- a/app/models/custom_filter.rb +++ b/app/models/custom_filter.rb @@ -15,7 +15,7 @@ # class CustomFilter < ApplicationRecord - self.ignored_columns = %w(whole_word irreversible) + self.ignored_columns += %w(whole_word irreversible) alias_attribute :title, :phrase alias_attribute :filter_action, :action diff --git a/app/models/email_domain_block.rb b/app/models/email_domain_block.rb index 276e7d31a..3c9be51ca 100644 --- a/app/models/email_domain_block.rb +++ b/app/models/email_domain_block.rb @@ -12,7 +12,7 @@ # class EmailDomainBlock < ApplicationRecord - self.ignored_columns = %w( + self.ignored_columns += %w( ips last_refresh_at ) diff --git a/app/models/report.rb b/app/models/report.rb index a9940459d..c3a0c4c8b 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -21,7 +21,7 @@ # class Report < ApplicationRecord - self.ignored_columns = %w(action_taken) + self.ignored_columns += %w(action_taken) include Paginable include RateLimitable diff --git a/app/models/status_edit.rb b/app/models/status_edit.rb index 683441bb5..2b3248bb2 100644 --- a/app/models/status_edit.rb +++ b/app/models/status_edit.rb @@ -20,7 +20,7 @@ class StatusEdit < ApplicationRecord include RateLimitable - self.ignored_columns = %w( + self.ignored_columns += %w( media_attachments_changed ) -- cgit From 3dcba94e68889f3d6603fa5416d54edd08dcf4bd Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 31 Mar 2023 21:37:57 +0200 Subject: Migrate glitch-soc's exclusive user settings --- app/controllers/settings/flavours_controller.rb | 14 +----- app/helpers/accounts_helper.rb | 2 +- app/models/concerns/has_user_settings.rb | 36 +++++++++++++- app/models/user_settings.rb | 9 +++- .../20230215074424_move_glitch_user_settings.rb | 57 ++++++++++++++++++++++ db/schema.rb | 2 +- 6 files changed, 103 insertions(+), 17 deletions(-) create mode 100644 db/migrate/20230215074424_move_glitch_user_settings.rb (limited to 'app/models') diff --git a/app/controllers/settings/flavours_controller.rb b/app/controllers/settings/flavours_controller.rb index 62c52eee9..c1172598b 100644 --- a/app/controllers/settings/flavours_controller.rb +++ b/app/controllers/settings/flavours_controller.rb @@ -21,18 +21,8 @@ class Settings::FlavoursController < Settings::BaseController 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/helpers/accounts_helper.rb b/app/helpers/accounts_helper.rb index e15aee6df..91c3a116b 100644 --- a/app/helpers/accounts_helper.rb +++ b/app/helpers/accounts_helper.rb @@ -28,7 +28,7 @@ module AccountsHelper end def hide_followers_count?(account) - Setting.hide_followers_count || account.user&.setting_hide_followers_count + Setting.hide_followers_count || account.user&.settings['hide_followers_count'] end def account_description(account) diff --git a/app/models/concerns/has_user_settings.rb b/app/models/concerns/has_user_settings.rb index b3fa1f683..0e9d4e1cd 100644 --- a/app/models/concerns/has_user_settings.rb +++ b/app/models/concerns/has_user_settings.rb @@ -39,6 +39,10 @@ module HasUserSettings settings['web.delete_modal'] end + def setting_favourite_modal + settings['web.favourite_modal'] + end + def setting_reduce_motion settings['web.reduce_motion'] end @@ -47,12 +51,20 @@ module HasUserSettings settings['web.use_system_font'] end + def setting_system_emoji_font + settings['web.use_system_emoji_font'] + end + def setting_noindex settings['noindex'] end - def setting_theme - settings['theme'] + def setting_flavour + settings['flavour'] + end + + def setting_skin + settings['skin'] end def setting_display_media @@ -107,6 +119,14 @@ module HasUserSettings settings['default_privacy'] || (account.locked? ? 'private' : 'public') end + def setting_default_content_type + settings['default_content_type'] + end + + def setting_hide_followers_count + settings['hide_followers_count'] + end + def allows_report_emails? settings['notification_emails.report'] end @@ -123,6 +143,18 @@ module HasUserSettings settings['notification_emails.trends'] end + def allows_trending_tags_review_emails? + settings['notification_emails.trends'] + end + + def allows_trending_links_review_emails? + settings['notification_emails.link_trends'] + end + + def allows_trending_statuses_review_emails? + settings['notification_emails.status_trends'] + end + def aggregates_reblogs? settings['aggregate_reblogs'] end diff --git a/app/models/user_settings.rb b/app/models/user_settings.rb index 2c025d6c5..0be8c5fbc 100644 --- a/app/models/user_settings.rb +++ b/app/models/user_settings.rb @@ -9,12 +9,15 @@ class UserSettings setting :always_send_emails, default: false setting :aggregate_reblogs, default: true - setting :theme, default: -> { ::Setting.theme } + setting :flavour, default: -> { ::Setting.flavour } + setting :skin, default: -> { ::Setting.skin } setting :noindex, default: -> { ::Setting.noindex } setting :show_application, default: true setting :default_language, default: nil setting :default_sensitive, default: false setting :default_privacy, default: nil + setting :default_content_type, default: 'text/plain' + setting :hide_followers_count, default: false namespace :web do setting :crop_images, default: true @@ -27,10 +30,12 @@ class UserSettings setting :delete_modal, default: true setting :reblog_modal, default: false setting :unfollow_modal, default: true + setting :favourite_modal, default: false setting :reduce_motion, default: false setting :expand_content_warnings, default: false setting :display_media, default: 'default', in: %w(default show_all hide_all) setting :auto_play, default: false + setting :use_system_emoji_font, default: false end namespace :notification_emails do @@ -42,6 +47,8 @@ class UserSettings setting :report, default: true setting :pending_account, default: true setting :trends, default: true + setting :link_trends, default: false + setting :status_trends, default: false setting :appeal, default: true end diff --git a/db/migrate/20230215074424_move_glitch_user_settings.rb b/db/migrate/20230215074424_move_glitch_user_settings.rb new file mode 100644 index 000000000..6b5a25925 --- /dev/null +++ b/db/migrate/20230215074424_move_glitch_user_settings.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +class MoveGlitchUserSettings < ActiveRecord::Migration[6.1] + class User < ApplicationRecord; end + + MAPPING = { + favourite_modal: 'web.favourite_modal', + system_emoji_font: 'web.use_system_emoji_font', + hide_followers_count: 'hide_followers_count', + default_content_type: 'default_content_type', + flavour: 'flavour', + skin: 'skin', + notification_emails: { + trending_link: 'notification_emails.link_trends', + trending_status: 'notification_emails.status_trends', + }.freeze, + }.freeze + + class LegacySetting < ApplicationRecord + self.table_name = 'settings' + + def var + self[:var]&.to_sym + end + + def value + YAML.safe_load(self[:value], permitted_classes: [ActiveSupport::HashWithIndifferentAccess]) if self[:value].present? + end + end + + def up + User.find_each do |user| + previous_settings = LegacySetting.where(thing_type: 'User', thing_id: user.id).index_by(&:var) + + user_settings = Oj.load(user.settings || '{}') + user_settings.delete('theme') + + MAPPING.each do |legacy_key, new_key| + value = previous_settings[legacy_key]&.value + + next if value.blank? + + if value.is_a?(Hash) + value.each do |nested_key, nested_value| + user_settings[MAPPING[legacy_key][nested_key.to_sym]] = nested_value + end + else + user_settings[new_key] = value + end + end + + user.update_column('settings', Oj.dump(user_settings)) # rubocop:disable Rails/SkipsModelValidations + end + end + + def down; end +end diff --git a/db/schema.rb b/db/schema.rb index 5b03e24f5..7d894b1aa 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2023_02_15_074423) do +ActiveRecord::Schema.define(version: 2023_02_15_074424) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" -- cgit From 0e919397db4977182386b93d2092fdeb5dff1f16 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 4 Apr 2023 12:42:38 +0200 Subject: Fix unescaped user input in LDAP query (#24379) --- app/models/concerns/ldap_authenticable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/concerns/ldap_authenticable.rb b/app/models/concerns/ldap_authenticable.rb index dc5abcd5a..775df0817 100644 --- a/app/models/concerns/ldap_authenticable.rb +++ b/app/models/concerns/ldap_authenticable.rb @@ -6,7 +6,7 @@ module LdapAuthenticable class_methods do def authenticate_with_ldap(params = {}) ldap = Net::LDAP.new(ldap_options) - filter = format(Devise.ldap_search_filter, uid: Devise.ldap_uid, mail: Devise.ldap_mail, email: params[:email]) + filter = format(Devise.ldap_search_filter, uid: Devise.ldap_uid, mail: Devise.ldap_mail, email: Net::LDAP::Filter.escape(params[:email])) if (user_info = ldap.bind_as(base: Devise.ldap_base, filter: filter, password: params[:password])) ldap_get_user(user_info.first) -- cgit From ff168ef2024626f37fa776fde5739dcd58ecb9f2 Mon Sep 17 00:00:00 2001 From: Claire Date: Sun, 9 Apr 2023 11:25:30 +0200 Subject: Fix most rubocop issues (#2165) * Run rubocop --autocorrect on app/, config/ and lib/, also manually fix some remaining style issues * Run rubocop --autocorrect-all on db/ * Run rubocop --autocorrect-all on `spec/` and fix remaining issues --- .rubocop_todo.yml | 2 + .../api/v1/timelines/public_controller.rb | 2 +- app/controllers/auth/confirmations_controller.rb | 13 ++-- app/controllers/settings/flavours_controller.rb | 4 +- app/helpers/accounts_helper.rb | 2 +- app/lib/advanced_text_formatter.rb | 1 + app/lib/feed_manager.rb | 2 + app/lib/themes.rb | 45 ++++++------ app/models/direct_feed.rb | 9 +-- app/models/status.rb | 19 ++--- app/models/user.rb | 1 - app/serializers/activitypub/note_serializer.rb | 1 + app/serializers/rest/account_serializer.rb | 2 +- app/serializers/rest/mute_serializer.rb | 4 +- app/serializers/rest/status_serializer.rb | 4 +- app/services/backup_service.rb | 2 +- app/services/fan_out_on_write_service.rb | 2 +- app/services/post_status_service.rb | 25 ++++--- app/validators/status_pin_validator.rb | 2 +- config/initializers/0_duplicate_migrations.rb | 24 ++++--- config/initializers/simple_form.rb | 1 + db/migrate/20171009222537_create_keyword_mutes.rb | 2 + ...900_move_keyword_mutes_into_glitch_namespace.rb | 2 + ...171210213213_add_local_only_flag_to_statuses.rb | 2 + db/migrate/20180410220657_create_bookmarks.rb | 2 + ..._add_apply_to_mentions_flag_to_keyword_mutes.rb | 2 + db/migrate/20180707193142_migrate_filters.rb | 12 ++-- .../20190512200918_add_content_type_to_statuses.rb | 2 + ...20209175231_add_content_type_to_status_edits.rb | 2 + .../20180813160548_post_migrate_filters.rb | 6 +- lib/sanitize_ext/sanitize_config.rb | 8 +-- lib/tasks/assets.rake | 12 ++-- lib/tasks/glitchsoc.rake | 8 ++- .../api/v1/accounts/credentials_controller_spec.rb | 4 +- .../api/v1/timelines/direct_controller_spec.rb | 2 +- spec/controllers/application_controller_spec.rb | 4 +- .../settings/flavours_controller_spec.rb | 3 +- spec/lib/advanced_text_formatter_spec.rb | 82 +++++++++++----------- spec/models/concerns/account_interactions_spec.rb | 39 +--------- spec/models/public_feed_spec.rb | 12 ++-- spec/models/status_spec.rb | 42 +++++------ spec/models/tag_feed_spec.rb | 2 +- spec/policies/status_policy_spec.rb | 4 +- spec/services/notify_service_spec.rb | 2 +- spec/validators/status_length_validator_spec.rb | 2 +- 45 files changed, 210 insertions(+), 215 deletions(-) (limited to 'app/models') diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 2e4801a55..dc7e21dc5 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -473,6 +473,7 @@ RSpec/ContextWording: - 'spec/lib/activitypub/activity/create_spec.rb' - 'spec/lib/activitypub/activity/follow_spec.rb' - 'spec/lib/activitypub/activity/reject_spec.rb' + - 'spec/lib/advanced_text_formatter_spec.rb' - 'spec/lib/emoji_formatter_spec.rb' - 'spec/lib/entity_cache_spec.rb' - 'spec/lib/feed_manager_spec.rb' @@ -1321,6 +1322,7 @@ Rails/FilePath: - 'app/models/setting.rb' - 'app/validators/reaction_validator.rb' - 'config/environments/test.rb' + - 'config/initializers/locale.rb' - 'db/migrate/20170716191202_add_hide_notifications_to_mute.rb' - 'db/migrate/20171005171936_add_disabled_to_custom_emojis.rb' - 'db/migrate/20171028221157_add_reblogs_to_follows.rb' 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/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/settings/flavours_controller.rb b/app/controllers/settings/flavours_controller.rb index c1172598b..b179b9429 100644 --- a/app/controllers/settings/flavours_controller.rb +++ b/app/controllers/settings/flavours_controller.rb @@ -12,9 +12,7 @@ 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] diff --git a/app/helpers/accounts_helper.rb b/app/helpers/accounts_helper.rb index 91c3a116b..b8277ee17 100644 --- a/app/helpers/accounts_helper.rb +++ b/app/helpers/accounts_helper.rb @@ -28,7 +28,7 @@ module AccountsHelper end def hide_followers_count?(account) - Setting.hide_followers_count || account.user&.settings['hide_followers_count'] + Setting.hide_followers_count || account.user&.settings&.[]('hide_followers_count') end def account_description(account) diff --git a/app/lib/advanced_text_formatter.rb b/app/lib/advanced_text_formatter.rb index 21e81d4d1..cdf1e2d9c 100644 --- a/app/lib/advanced_text_formatter.rb +++ b/app/lib/advanced_text_formatter.rb @@ -15,6 +15,7 @@ class AdvancedTextFormatter < TextFormatter def autolink(link, link_type) return link if link_type == :email + @format_link.call(link) end end diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 4ce888fc9..15ff6d15f 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -306,6 +306,7 @@ class FeedManager statuses.each do |status| next if filter_from_direct?(status, account) + added += 1 if add_to_feed(:direct, account.id, status) end @@ -459,6 +460,7 @@ class FeedManager # @return [Boolean] def filter_from_direct?(status, receiver_id) return false if receiver_id == status.account_id + filter_from_mentions?(status, receiver_id) end diff --git a/app/lib/themes.rb b/app/lib/themes.rb index 81e016d4a..45ba47780 100644 --- a/app/lib/themes.rb +++ b/app/lib/themes.rb @@ -7,24 +7,23 @@ class Themes include Singleton def initialize - core = YAML.load_file(Rails.root.join('app', 'javascript', 'core', 'theme.yml')) - core['pack'] = Hash.new unless core['pack'] + core['pack'] = {} unless core['pack'] - result = Hash.new - Dir.glob(Rails.root.join('app', 'javascript', 'flavours', '*', 'theme.yml')) do |path| - data = YAML.load_file(path) + result = {} + Rails.root.glob('app/javascript/flavours/*/theme.yml') do |pathname| + data = YAML.load_file(pathname) next unless data['pack'] - dir = File.dirname(path) - name = File.basename(dir) + dir = pathname.dirname + name = dir.basename.to_s locales = [] screenshots = [] if data['locales'] Dir.glob(File.join(dir, data['locales'], '*.{js,json}')) do |locale| - localeName = File.basename(locale, File.extname(locale)) - locales.push(localeName) unless localeName.match(/defaultMessages|whitelist|index/) + locale_name = File.basename(locale, File.extname(locale)) + locales.push(locale_name) unless /defaultMessages|whitelist|index/.match?(locale_name) end end @@ -43,34 +42,30 @@ class Themes result[name] = data end - Dir.glob(Rails.root.join('app', 'javascript', 'skins', '*', '*')) do |path| - ext = File.extname(path) - skin = File.basename(path) - name = File.basename(File.dirname(path)) + Rails.root.glob('app/javascript/skins/*/*') do |pathname| + ext = pathname.extname.to_s + skin = pathname.basename.to_s + name = pathname.dirname.basename.to_s next unless result[name] - if File.directory?(path) + if pathname.directory? pack = [] - Dir.glob(File.join(path, '*.{css,scss}')) do |sheet| - pack.push(File.basename(sheet, File.extname(sheet))) + pathname.glob('*.{css,scss}') do |sheet| + pack.push(sheet.basename(sheet.extname).to_s) end - elsif ext.match(/^\.s?css$/i) - skin = File.basename(path, ext) + elsif /^\.s?css$/i.match?(ext) + skin = pathname.basename(ext).to_s pack = ['common'] end - if skin != 'default' - result[name]['skin'][skin] = pack - end + result[name]['skin'][skin] = pack if skin != 'default' end @core = core @conf = result end - def core - @core - end + attr_reader :core def flavour(name) @conf[name] @@ -86,7 +81,7 @@ class Themes def flavours_and_skins flavours.map do |flavour| - [flavour, skins_for(flavour).map{ |skin| [flavour, skin] }] + [flavour, skins_for(flavour).map { |skin| [flavour, skin] }] end end end diff --git a/app/models/direct_feed.rb b/app/models/direct_feed.rb index 1f2448070..689a735b3 100644 --- a/app/models/direct_feed.rb +++ b/app/models/direct_feed.rb @@ -4,9 +4,8 @@ class DirectFeed < Feed include Redisable def initialize(account) - @type = :direct - @id = account.id @account = account + super(:direct, account.id) end def get(limit, max_id = nil, since_id = nil, min_id = nil) @@ -19,10 +18,12 @@ class DirectFeed < Feed private - def from_database(limit, max_id, since_id, min_id) + # TODO: _min_id is not actually handled by `as_direct_timeline` + def from_database(limit, max_id, since_id, _min_id) loop do - statuses = Status.as_direct_timeline(@account, limit, max_id, since_id, min_id) + statuses = Status.as_direct_timeline(@account, limit, max_id, since_id) return statuses if statuses.empty? + max_id = statuses.last.id statuses = statuses.reject { |status| FeedManager.instance.filter?(:direct, status, @account) } return statuses unless statuses.empty? diff --git a/app/models/status.rb b/app/models/status.rb index e01ddb5c5..8a58e5d68 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -338,7 +338,7 @@ class Status < ApplicationRecord visibilities.keys - %w(direct limited) end - def as_direct_timeline(account, limit = 20, max_id = nil, since_id = nil, cache_ids = false) + def as_direct_timeline(account, limit = 20, max_id = nil, since_id = nil) # direct timeline is mix of direct message from_me and to_me. # 2 queries are executed with pagination. # constant expression using arel_table is required for partial index @@ -369,14 +369,9 @@ class Status < ApplicationRecord query_to_me = query_to_me.where('mentions.status_id > ?', since_id) end - if cache_ids - # returns array of cache_ids object that have id and updated_at - (query_from_me.cache_ids.to_a + query_to_me.cache_ids.to_a).uniq(&:id).sort_by(&:id).reverse.take(limit) - else - # returns ActiveRecord.Relation - items = (query_from_me.select(:id).to_a + query_to_me.select(:id).to_a).uniq(&:id).sort_by(&:id).reverse.take(limit) - Status.where(id: items.map(&:id)) - end + # returns ActiveRecord.Relation + items = (query_from_me.select(:id).to_a + query_to_me.select(:id).to_a).uniq(&:id).sort_by(&:id).reverse.take(limit) + Status.where(id: items.map(&:id)) end def favourites_map(status_ids, account_id) @@ -553,9 +548,9 @@ class Status < ApplicationRecord end def set_locality - if account.domain.nil? && !attribute_changed?(:local_only) - self.local_only = marked_local_only? - end + return unless account.domain.nil? && !attribute_changed?(:local_only) + + self.local_only = marked_local_only? end def set_conversation diff --git a/app/models/user.rb b/app/models/user.rb index 3471bb2c1..daf8768e8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -244,7 +244,6 @@ class User < ApplicationRecord end def functional? - functional_or_moved? end diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb index ca067ed9b..52ffaf717 100644 --- a/app/serializers/activitypub/note_serializer.rb +++ b/app/serializers/activitypub/note_serializer.rb @@ -32,6 +32,7 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer def id raise Mastodon::NotPermittedError, 'Local-only statuses should not be serialized' if object.local_only? && !instance_options[:allow_local_only] + ActivityPub::TagManager.instance.uri_for(object) end diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb index e6c8fe4b2..d4e7ac974 100644 --- a/app/serializers/rest/account_serializer.rb +++ b/app/serializers/rest/account_serializer.rb @@ -91,7 +91,7 @@ class REST::AccountSerializer < ActiveModel::Serializer end def followers_count - (Setting.hide_followers_count || object.user&.setting_hide_followers_count) ? -1 : object.followers_count + Setting.hide_followers_count || object.user&.setting_hide_followers_count ? -1 : object.followers_count end def display_name diff --git a/app/serializers/rest/mute_serializer.rb b/app/serializers/rest/mute_serializer.rb index 043a2f059..c9b55ff16 100644 --- a/app/serializers/rest/mute_serializer.rb +++ b/app/serializers/rest/mute_serializer.rb @@ -2,7 +2,7 @@ class REST::MuteSerializer < ActiveModel::Serializer include RoutingHelper - + attributes :id, :account, :target_account, :created_at, :hide_notifications def account @@ -12,4 +12,4 @@ class REST::MuteSerializer < ActiveModel::Serializer def target_account REST::AccountSerializer.new(object.target_account) end -end \ No newline at end of file +end diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index 659c45b83..eb5f3c3ea 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -13,7 +13,7 @@ class REST::StatusSerializer < ActiveModel::Serializer attribute :muted, if: :current_user? attribute :bookmarked, if: :current_user? attribute :pinned, if: :pinnable? - attribute :local_only if :local? + attribute :local_only, if: :local? has_many :filtered, serializer: REST::FilterResultSerializer, if: :current_user? attribute :content, unless: :source_requested? @@ -32,6 +32,8 @@ class REST::StatusSerializer < ActiveModel::Serializer has_one :preview_card, key: :card, serializer: REST::PreviewCardSerializer has_one :preloadable_poll, key: :poll, serializer: REST::PollSerializer + delegate :local?, to: :object + def id object.id.to_s end diff --git a/app/services/backup_service.rb b/app/services/backup_service.rb index a9d740211..c5e7a8e58 100644 --- a/app/services/backup_service.rb +++ b/app/services/backup_service.rb @@ -154,7 +154,7 @@ class BackupService < BaseService object, serializer: serializer, adapter: ActivityPub::Adapter, - allow_local_only: true, + allow_local_only: true ).as_json end diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb index 8e74e152e..3b14a6748 100644 --- a/app/services/fan_out_on_write_service.rb +++ b/app/services/fan_out_on_write_service.rb @@ -116,7 +116,7 @@ class FanOutOnWriteService < BaseService end def deliver_to_direct_timelines! - FeedInsertWorker.push_bulk(@status.mentions.includes(:account).map(&:account).select { |mentioned_account| mentioned_account.local? }) do |account| + FeedInsertWorker.push_bulk(@status.mentions.includes(:account).map(&:account).select(&:local?)) do |account| [@status.id, account.id, 'direct', { 'update' => update? }] end end diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb index bca3b3ff7..74ec47a33 100644 --- a/app/services/post_status_service.rb +++ b/app/services/post_status_service.rb @@ -61,17 +61,22 @@ class PostStatusService < BaseService private - def preprocess_attributes! - if @text.blank? && @options[:spoiler_text].present? - @text = '.' - if @media&.find(&:video?) || @media&.find(&:gifv?) - @text = '📹' - elsif @media&.find(&:audio?) - @text = '🎵' - elsif @media&.find(&:image?) - @text = '🖼' - end + def fill_blank_text! + return unless @text.blank? && @options[:spoiler_text].present? + + if @media&.any?(&:video?) || @media&.any?(&:gifv?) + @text = '📹' + elsif @media&.any?(&:audio?) + @text = '🎵' + elsif @media&.any?(&:image?) + @text = '🖼' + else + @text = '.' end + end + + def preprocess_attributes! + fill_blank_text! @sensitive = (@options[:sensitive].nil? ? @account.user&.setting_default_sensitive : @options[:sensitive]) || @options[:spoiler_text].present? @visibility = @options[:visibility] || @account.user&.setting_default_privacy @visibility = :unlisted if @visibility&.to_sym == :public && @account.silenced? diff --git a/app/validators/status_pin_validator.rb b/app/validators/status_pin_validator.rb index 9466a81fe..4af7bd295 100644 --- a/app/validators/status_pin_validator.rb +++ b/app/validators/status_pin_validator.rb @@ -7,6 +7,6 @@ class StatusPinValidator < ActiveModel::Validator pin.errors.add(:base, I18n.t('statuses.pin_errors.reblog')) if pin.status.reblog? pin.errors.add(:base, I18n.t('statuses.pin_errors.ownership')) if pin.account_id != pin.status.account_id pin.errors.add(:base, I18n.t('statuses.pin_errors.direct')) if pin.status.direct_visibility? - pin.errors.add(:base, I18n.t('statuses.pin_errors.limit')) if pin.account.status_pins.count >= MAX_PINNED && pin.account.local? + pin.errors.add(:base, I18n.t('statuses.pin_errors.limit')) if pin.account.status_pins.count >= MAX_PINNED && pin.account.local? end end diff --git a/config/initializers/0_duplicate_migrations.rb b/config/initializers/0_duplicate_migrations.rb index 6c45e4bd2..1b8b59025 100644 --- a/config/initializers/0_duplicate_migrations.rb +++ b/config/initializers/0_duplicate_migrations.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Some migrations have been present in glitch-soc for a long time and have then # been merged in upstream Mastodon, under a different version number. # @@ -12,24 +14,26 @@ # we decided monkey-patching Rails' Migrator to completely ignore the duplicate, # keeping only the one that has run, or an arbitrary one. -ALLOWED_DUPLICATES = [20180410220657, 20180831171112].freeze +ALLOWED_DUPLICATES = [2018_04_10_220657, 2018_08_31_171112].freeze module ActiveRecord class Migrator def self.new(direction, migrations, schema_migration, target_version = nil) migrated = Set.new(Base.connection.migration_context.get_all_versions) - migrations.group_by(&:name).each do |name, duplicates| - if duplicates.length > 1 && duplicates.all? { |m| ALLOWED_DUPLICATES.include?(m.version) } - # We have a set of allowed duplicates. Keep the migrated one, if any. - non_migrated = duplicates.reject { |m| migrated.include?(m.version.to_i) } + migrations.group_by(&:name).each do |_name, duplicates| + next unless duplicates.length > 1 && duplicates.all? { |m| ALLOWED_DUPLICATES.include?(m.version) } + + # We have a set of allowed duplicates. Keep the migrated one, if any. + non_migrated = duplicates.reject { |m| migrated.include?(m.version.to_i) } - if duplicates.length == non_migrated.length || non_migrated.length == 0 + migrations = begin + if duplicates.length == non_migrated.length || non_migrated.empty? # There weren't any migrated one, so we have to pick one “canonical” migration - migrations = migrations - duplicates[1..-1] + migrations - duplicates[1..] else # Just reject every duplicate which hasn't been migrated yet - migrations = migrations - non_migrated + migrations - non_migrated end end end @@ -43,10 +47,10 @@ module ActiveRecord # A set of duplicated migrations is considered migrated if at least one of # them is migrated. migrated = get_all_versions - migrations.group_by(&:name).each do |name, duplicates| + migrations.group_by(&:name).each do |_name, duplicates| return true unless duplicates.any? { |m| migrated.include?(m.version.to_i) } end - return false + false end end end diff --git a/config/initializers/simple_form.rb b/config/initializers/simple_form.rb index d167a1600..fff4f538e 100644 --- a/config/initializers/simple_form.rb +++ b/config/initializers/simple_form.rb @@ -22,6 +22,7 @@ end module GlitchOnlyComponent def glitch_only(_wrapper_options = nil) return unless options[:glitch_only] + options[:label_text] = ->(raw_label_text, _required_label_text, _label_present) { safe_join([raw_label_text, ' ', content_tag(:span, I18n.t('simple_form.glitch_only'), class: 'glitch_only')]) } nil end diff --git a/db/migrate/20171009222537_create_keyword_mutes.rb b/db/migrate/20171009222537_create_keyword_mutes.rb index 66411ba1d..77c88b0a5 100644 --- a/db/migrate/20171009222537_create_keyword_mutes.rb +++ b/db/migrate/20171009222537_create_keyword_mutes.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class CreateKeywordMutes < ActiveRecord::Migration[5.1] def change create_table :keyword_mutes do |t| diff --git a/db/migrate/20171021191900_move_keyword_mutes_into_glitch_namespace.rb b/db/migrate/20171021191900_move_keyword_mutes_into_glitch_namespace.rb index 269bb49d6..b6ea537c2 100644 --- a/db/migrate/20171021191900_move_keyword_mutes_into_glitch_namespace.rb +++ b/db/migrate/20171021191900_move_keyword_mutes_into_glitch_namespace.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class MoveKeywordMutesIntoGlitchNamespace < ActiveRecord::Migration[5.1] def change safety_assured do diff --git a/db/migrate/20171210213213_add_local_only_flag_to_statuses.rb b/db/migrate/20171210213213_add_local_only_flag_to_statuses.rb index af1e29d6a..010503b10 100644 --- a/db/migrate/20171210213213_add_local_only_flag_to_statuses.rb +++ b/db/migrate/20171210213213_add_local_only_flag_to_statuses.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddLocalOnlyFlagToStatuses < ActiveRecord::Migration[5.1] def change add_column :statuses, :local_only, :boolean diff --git a/db/migrate/20180410220657_create_bookmarks.rb b/db/migrate/20180410220657_create_bookmarks.rb index bc79022e4..aba21f5ea 100644 --- a/db/migrate/20180410220657_create_bookmarks.rb +++ b/db/migrate/20180410220657_create_bookmarks.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This migration is a duplicate of 20180831171112 and may get ignored, see # config/initializers/0_duplicate_migrations.rb diff --git a/db/migrate/20180604000556_add_apply_to_mentions_flag_to_keyword_mutes.rb b/db/migrate/20180604000556_add_apply_to_mentions_flag_to_keyword_mutes.rb index cd97d0f20..8078a07bf 100644 --- a/db/migrate/20180604000556_add_apply_to_mentions_flag_to_keyword_mutes.rb +++ b/db/migrate/20180604000556_add_apply_to_mentions_flag_to_keyword_mutes.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'mastodon/migration_helpers' class AddApplyToMentionsFlagToKeywordMutes < ActiveRecord::Migration[5.2] diff --git a/db/migrate/20180707193142_migrate_filters.rb b/db/migrate/20180707193142_migrate_filters.rb index 067c53357..8f6b3e1bb 100644 --- a/db/migrate/20180707193142_migrate_filters.rb +++ b/db/migrate/20180707193142_migrate_filters.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + class MigrateFilters < ActiveRecord::Migration[5.2] class GlitchKeywordMute < ApplicationRecord # Dummy class, as we removed Glitch::KeywordMute - belongs_to :account, required: true + belongs_to :account, optional: false validates_presence_of :keyword end @@ -15,7 +17,7 @@ class MigrateFilters < ActiveRecord::Migration[5.2] private def clean_up_contexts - self.context = Array(context).map(&:strip).map(&:presence).compact + self.context = Array(context).map(&:strip).filter_map(&:presence) end end @@ -27,7 +29,8 @@ class MigrateFilters < ActiveRecord::Migration[5.2] phrase: filter.keyword, context: filter.apply_to_mentions ? %w(home public notifications) : %w(home public), whole_word: filter.whole_word, - irreversible: true) + irreversible: true + ) end end @@ -48,7 +51,8 @@ class MigrateFilters < ActiveRecord::Migration[5.2] GlitchKeywordMute.where(account: filter.account).create!( keyword: filter.phrase, whole_word: filter.whole_word, - apply_to_mentions: filter.context.include?('notifications')) + apply_to_mentions: filter.context.include?('notifications') + ) end end end diff --git a/db/migrate/20190512200918_add_content_type_to_statuses.rb b/db/migrate/20190512200918_add_content_type_to_statuses.rb index efbe2caa7..31c1a4f17 100644 --- a/db/migrate/20190512200918_add_content_type_to_statuses.rb +++ b/db/migrate/20190512200918_add_content_type_to_statuses.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddContentTypeToStatuses < ActiveRecord::Migration[5.2] def change add_column :statuses, :content_type, :string diff --git a/db/migrate/20220209175231_add_content_type_to_status_edits.rb b/db/migrate/20220209175231_add_content_type_to_status_edits.rb index 0e4e52fcb..bb414535d 100644 --- a/db/migrate/20220209175231_add_content_type_to_status_edits.rb +++ b/db/migrate/20220209175231_add_content_type_to_status_edits.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddContentTypeToStatusEdits < ActiveRecord::Migration[6.1] def change add_column :status_edits, :content_type, :string diff --git a/db/post_migrate/20180813160548_post_migrate_filters.rb b/db/post_migrate/20180813160548_post_migrate_filters.rb index 588548c1d..82acf13d5 100644 --- a/db/post_migrate/20180813160548_post_migrate_filters.rb +++ b/db/post_migrate/20180813160548_post_migrate_filters.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class PostMigrateFilters < ActiveRecord::Migration[5.2] disable_ddl_transaction! @@ -5,7 +7,5 @@ class PostMigrateFilters < ActiveRecord::Migration[5.2] drop_table :glitch_keyword_mutes if table_exists? :glitch_keyword_mutes end - def down - end + def down; end end - diff --git a/lib/sanitize_ext/sanitize_config.rb b/lib/sanitize_ext/sanitize_config.rb index dfc586561..4c0e9b858 100644 --- a/lib/sanitize_ext/sanitize_config.rb +++ b/lib/sanitize_ext/sanitize_config.rb @@ -48,9 +48,9 @@ class Sanitize node.content = "[🖼 #{node['alt']}]" else url = node['href'] - prefix = url.match(/\Ahttps?:\/\/(www\.)?/).to_s + prefix = url.match(%r{\Ahttps?://(www\.)?}).to_s text = url[prefix.length, 30] - text = text + "…" if url[prefix.length..-1].length > 30 + text += '…' if url.length - prefix.length > 30 node.content = "[🖼 #{text}]" end end @@ -88,7 +88,7 @@ class Sanitize }, protocols: { - 'a' => { 'href' => LINK_PROTOCOLS }, + 'a' => { 'href' => LINK_PROTOCOLS }, 'blockquote' => { 'cite' => LINK_PROTOCOLS }, }, @@ -126,7 +126,7 @@ class Sanitize node = env[:node] - rel = (node['rel'] || '').split(' ') & ['tag'] + rel = (node['rel'] || '').split & ['tag'] rel += ['nofollow', 'noopener', 'noreferrer'] unless TagManager.instance.local_url?(node['href']) if rel.empty? diff --git a/lib/tasks/assets.rake b/lib/tasks/assets.rake index e1102af33..76e190f70 100644 --- a/lib/tasks/assets.rake +++ b/lib/tasks/assets.rake @@ -3,14 +3,14 @@ namespace :assets do desc 'Generate static pages' task generate_static_pages: :environment do - class StaticApplicationController < ApplicationController - def current_user - nil + def render_static_page(action, dest:, **opts) + renderer = Class.new(ApplicationController) do + def current_user + nil + end end - end - def render_static_page(action, dest:, **opts) - html = StaticApplicationController.render(action, opts) + html = renderer.render(action, opts) File.write(dest, html) end diff --git a/lib/tasks/glitchsoc.rake b/lib/tasks/glitchsoc.rake index 79e864648..72558fa19 100644 --- a/lib/tasks/glitchsoc.rake +++ b/lib/tasks/glitchsoc.rake @@ -1,8 +1,12 @@ +# frozen_string_literal: true + namespace :glitchsoc do desc 'Backfill local-only flag on statuses table' task backfill_local_only: :environment do - Status.local.where(local_only: nil).find_each do |st| - ActiveRecord::Base.logger.silence { st.update_attribute(:local_only, st.marked_local_only?) } + Status.local.where(local_only: nil).find_each do |status| + ActiveRecord::Base.logger.silence do + status.update_attribute(:local_only, status.marked_local_only?) # rubocop:disable Rails/SkipsModelValidations + end end end end diff --git a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb index de08dd524..a677aaad0 100644 --- a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb @@ -75,10 +75,10 @@ describe Api::V1::Accounts::CredentialsController do end end - describe 'with invalid data' do + describe 'with a too long profile bio' do before do note = 'This is too long. ' - note = note + 'a' * (Account::MAX_NOTE_LENGTH - note.length + 1) + note += 'a' * (Account::MAX_NOTE_LENGTH - note.length + 1) patch :update, params: { note: note } end diff --git a/spec/controllers/api/v1/timelines/direct_controller_spec.rb b/spec/controllers/api/v1/timelines/direct_controller_spec.rb index a22c2cbea..def67a0fe 100644 --- a/spec/controllers/api/v1/timelines/direct_controller_spec.rb +++ b/spec/controllers/api/v1/timelines/direct_controller_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -RSpec.describe Api::V1::Timelines::DirectController, type: :controller do +RSpec.describe Api::V1::Timelines::DirectController do let(:user) { Fabricate(:user) } let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses') } diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 1aabae0ea..82455d874 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -75,8 +75,8 @@ describe ApplicationController, type: :controller do describe 'helper_method :current_flavour' do it 'returns "glitch" when theme wasn\'t changed in admin settings' do - allow(Setting).to receive(:default_settings).and_return({'skin' => 'default'}) - allow(Setting).to receive(:default_settings).and_return({'flavour' => 'glitch'}) + allow(Setting).to receive(:default_settings).and_return({ 'skin' => 'default' }) + allow(Setting).to receive(:default_settings).and_return({ 'flavour' => 'glitch' }) expect(controller.view_context.current_flavour).to eq 'glitch' end diff --git a/spec/controllers/settings/flavours_controller_spec.rb b/spec/controllers/settings/flavours_controller_spec.rb index f89bde1f9..8c7d4a768 100644 --- a/spec/controllers/settings/flavours_controller_spec.rb +++ b/spec/controllers/settings/flavours_controller_spec.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true + require 'rails_helper' -RSpec.describe Settings::FlavoursController, type: :controller do +RSpec.describe Settings::FlavoursController do let(:user) { Fabricate(:user) } before do diff --git a/spec/lib/advanced_text_formatter_spec.rb b/spec/lib/advanced_text_formatter_spec.rb index c1e469606..8b27b56a1 100644 --- a/spec/lib/advanced_text_formatter_spec.rb +++ b/spec/lib/advanced_text_formatter_spec.rb @@ -1,12 +1,14 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe AdvancedTextFormatter do describe '#to_s' do + subject { described_class.new(text, preloaded_accounts: preloaded_accounts, content_type: content_type).to_s } + let(:preloaded_accounts) { nil } let(:content_type) { 'text/markdown' } - subject { described_class.new(text, preloaded_accounts: preloaded_accounts, content_type: content_type).to_s } - context 'given a markdown source' do let(:content_type) { 'text/markdown' } @@ -14,7 +16,7 @@ RSpec.describe AdvancedTextFormatter do let(:text) { 'text' } it 'paragraphizes the text' do - is_expected.to eq '

text

' + expect(subject).to eq '

text

' end end @@ -22,7 +24,7 @@ RSpec.describe AdvancedTextFormatter do let(:text) { "line\nfeed" } it 'removes line feeds' do - is_expected.not_to include "\n" + expect(subject).to_not include "\n" end end @@ -30,7 +32,7 @@ RSpec.describe AdvancedTextFormatter do let(:text) { 'test `foo` bar' } it 'formats code using ' do - is_expected.to include 'test foo bar' + expect(subject).to include 'test foo bar' end end @@ -38,15 +40,15 @@ RSpec.describe AdvancedTextFormatter do let(:text) { "test\n\n```\nint main(void) {\n return 0; // https://joinmastodon.org/foo\n}\n```\n" } it 'formats code using
 and ' do
-          is_expected.to include '
int main'
+          expect(subject).to include '
int main'
         end
 
         it 'does not strip leading spaces' do
-          is_expected.to include '>  return 0'
+          expect(subject).to include '>  return 0'
         end
 
         it 'does not format links' do
-          is_expected.to include 'return 0; // https://joinmastodon.org/foo'
+          expect(subject).to include 'return 0; // https://joinmastodon.org/foo'
         end
       end
 
@@ -54,7 +56,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { 'test `https://foo.bar/bar` bar' }
 
         it 'does not rewrite the link' do
-          is_expected.to include 'test https://foo.bar/bar bar'
+          expect(subject).to include 'test https://foo.bar/bar bar'
         end
       end
 
@@ -62,7 +64,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { 'foo https://cb6e6126.ngrok.io/about/more' }
 
         it 'creates a link' do
-          is_expected.to include '@alice'
+          expect(subject).to include '@alice'
         end
       end
 
@@ -80,7 +82,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { '@alice' }
 
         it 'does not create a mention link' do
-          is_expected.to include '@alice'
+          expect(subject).to include '@alice'
         end
       end
 
@@ -88,7 +90,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { 'https://hackernoon.com/the-power-to-build-communities-a-response-to-mark-zuckerberg-3f2cac9148a4' }
 
         it 'matches the full URL' do
-          is_expected.to include 'href="https://hackernoon.com/the-power-to-build-communities-a-response-to-mark-zuckerberg-3f2cac9148a4"'
+          expect(subject).to include 'href="https://hackernoon.com/the-power-to-build-communities-a-response-to-mark-zuckerberg-3f2cac9148a4"'
         end
       end
 
@@ -96,7 +98,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { 'http://google.com' }
 
         it 'matches the full URL' do
-          is_expected.to include 'href="http://google.com"'
+          expect(subject).to include 'href="http://google.com"'
         end
       end
 
@@ -104,7 +106,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { 'http://example.gay' }
 
         it 'matches the full URL' do
-          is_expected.to include 'href="http://example.gay"'
+          expect(subject).to include 'href="http://example.gay"'
         end
       end
 
@@ -112,11 +114,11 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { 'https://nic.みんな/' }
 
         it 'matches the full URL' do
-          is_expected.to include 'href="https://nic.みんな/"'
+          expect(subject).to include 'href="https://nic.みんな/"'
         end
 
         it 'has display URL' do
-          is_expected.to include 'nic.みんな/'
+          expect(subject).to include 'nic.みんな/'
         end
       end
 
@@ -124,7 +126,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { 'http://www.mcmansionhell.com/post/156408871451/50-states-of-mcmansion-hell-scottsdale-arizona. ' }
 
         it 'matches the full URL but not the period' do
-          is_expected.to include 'href="http://www.mcmansionhell.com/post/156408871451/50-states-of-mcmansion-hell-scottsdale-arizona"'
+          expect(subject).to include 'href="http://www.mcmansionhell.com/post/156408871451/50-states-of-mcmansion-hell-scottsdale-arizona"'
         end
       end
 
@@ -132,7 +134,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { '(http://google.com/)' }
 
         it 'matches the full URL but not the parentheses' do
-          is_expected.to include 'href="http://google.com/"'
+          expect(subject).to include 'href="http://google.com/"'
         end
       end
 
@@ -140,7 +142,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { 'http://www.google.com!' }
 
         it 'matches the full URL but not the exclamation point' do
-          is_expected.to include 'href="http://www.google.com"'
+          expect(subject).to include 'href="http://www.google.com"'
         end
       end
 
@@ -148,7 +150,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { "http://www.google.com'" }
 
         it 'matches the full URL but not the single quote' do
-          is_expected.to include 'href="http://www.google.com"'
+          expect(subject).to include 'href="http://www.google.com"'
         end
       end
     end
@@ -157,7 +159,7 @@ RSpec.describe AdvancedTextFormatter do
       let(:text) { 'http://www.google.com>' }
 
       it 'matches the full URL but not the angle bracket' do
-        is_expected.to include 'href="http://www.google.com"'
+        expect(subject).to include 'href="http://www.google.com"'
       end
     end
 
@@ -166,7 +168,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { 'https://www.ruby-toolbox.com/search?utf8=%E2%9C%93&q=autolink' }
 
         it 'matches the full URL' do
-          is_expected.to include 'href="https://www.ruby-toolbox.com/search?utf8=%E2%9C%93&q=autolink"'
+          expect(subject).to include 'href="https://www.ruby-toolbox.com/search?utf8=%E2%9C%93&q=autolink"'
         end
       end
 
@@ -174,7 +176,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { 'https://www.ruby-toolbox.com/search?utf8=✓&q=autolink' }
 
         it 'matches the full URL' do
-          is_expected.to include 'href="https://www.ruby-toolbox.com/search?utf8=✓&q=autolink"'
+          expect(subject).to include 'href="https://www.ruby-toolbox.com/search?utf8=✓&q=autolink"'
         end
       end
 
@@ -182,7 +184,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { 'https://www.ruby-toolbox.com/search?utf8=✓' }
 
         it 'matches the full URL' do
-          is_expected.to include 'href="https://www.ruby-toolbox.com/search?utf8=✓"'
+          expect(subject).to include 'href="https://www.ruby-toolbox.com/search?utf8=✓"'
         end
       end
 
@@ -190,7 +192,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { 'https://www.ruby-toolbox.com/search?utf8=%E2%9C%93&utf81=✓&q=autolink' }
 
         it 'preserves escaped unicode characters' do
-          is_expected.to include 'href="https://www.ruby-toolbox.com/search?utf8=%E2%9C%93&utf81=✓&q=autolink"'
+          expect(subject).to include 'href="https://www.ruby-toolbox.com/search?utf8=%E2%9C%93&utf81=✓&q=autolink"'
         end
       end
 
@@ -198,7 +200,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { 'https://en.wikipedia.org/wiki/Diaspora_(software)' }
 
         it 'matches the full URL' do
-          is_expected.to include 'href="https://en.wikipedia.org/wiki/Diaspora_(software)"'
+          expect(subject).to include 'href="https://en.wikipedia.org/wiki/Diaspora_(software)"'
         end
       end
 
@@ -206,7 +208,7 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { '"https://example.com/"' }
 
         it 'does not match the quotation marks' do
-          is_expected.to include 'href="https://example.com/"'
+          expect(subject).to include 'href="https://example.com/"'
         end
       end
 
@@ -214,19 +216,19 @@ RSpec.describe AdvancedTextFormatter do
         let(:text) { '' }
 
         it 'does not match the angle brackets' do
-          is_expected.to include 'href="https://example.com/"'
+          expect(subject).to include 'href="https://example.com/"'
         end
       end
 
       context 'given a URL containing unsafe code (XSS attack, invisible part)' do
-        let(:text) { %q{http://example.com/blahblahblahblah/a} }
+        let(:text) { 'http://example.com/blahblahblahblah/a' }
 
         it 'does not include the HTML in the URL' do
-          is_expected.to include '"http://example.com/blahblahblahblah/a"'
+          expect(subject).to include '"http://example.com/blahblahblahblah/a"'
         end
 
         it 'does not include a script tag' do
-          is_expected.to_not include '' }
 
         it 'does not include a script tag' do
-          is_expected.to_not include '