diff options
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/account.rb | 4 | ||||
-rw-r--r-- | app/models/account_filter.rb | 4 | ||||
-rw-r--r-- | app/models/account_warning.rb | 8 | ||||
-rw-r--r-- | app/models/admin/action_log_filter.rb | 2 | ||||
-rw-r--r-- | app/models/admin/appeal_filter.rb | 49 | ||||
-rw-r--r-- | app/models/admin/status_filter.rb | 2 | ||||
-rw-r--r-- | app/models/appeal.rb | 60 | ||||
-rw-r--r-- | app/models/media_attachment.rb | 13 | ||||
-rw-r--r-- | app/models/notification.rb | 14 | ||||
-rw-r--r-- | app/models/user.rb | 6 |
10 files changed, 145 insertions, 17 deletions
diff --git a/app/models/account.rb b/app/models/account.rb index e41fdf003..8f6663e7c 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -274,6 +274,10 @@ class Account < ApplicationRecord true end + def previous_strikes_count + strikes.where(overruled_at: nil).count + end + def keypair @keypair ||= OpenSSL::PKey::RSA.new(private_key || public_key) end diff --git a/app/models/account_filter.rb b/app/models/account_filter.rb index dcb174122..9da1522dd 100644 --- a/app/models/account_filter.rb +++ b/app/models/account_filter.rb @@ -24,6 +24,8 @@ class AccountFilter scope = Account.includes(:account_stat, user: [:ips, :invite_request]).without_instance_actor.reorder(nil) params.each do |key, value| + next if key.to_s == 'page' + scope.merge!(scope_for(key, value.to_s.strip)) if value.present? end @@ -49,7 +51,7 @@ class AccountFilter when 'email' accounts_with_users.merge(User.matches_email(value)) when 'ip' - valid_ip?(value) ? accounts_with_users.merge(User.matches_ip(value)) : Account.none + valid_ip?(value) ? accounts_with_users.merge(User.matches_ip(value).group('users.id, accounts.id')) : Account.none when 'invited_by' invited_by_scope(value) when 'order' diff --git a/app/models/account_warning.rb b/app/models/account_warning.rb index fc0d988fd..05d01942d 100644 --- a/app/models/account_warning.rb +++ b/app/models/account_warning.rb @@ -12,6 +12,7 @@ # updated_at :datetime not null # report_id :bigint(8) # status_ids :string is an Array +# overruled_at :datetime # class AccountWarning < ApplicationRecord @@ -28,12 +29,17 @@ class AccountWarning < ApplicationRecord belongs_to :target_account, class_name: 'Account', inverse_of: :strikes belongs_to :report, optional: true - has_one :appeal, dependent: :destroy + has_one :appeal, dependent: :destroy, inverse_of: :strike scope :latest, -> { order(id: :desc) } scope :custom, -> { where.not(text: '') } + scope :active, -> { where(overruled_at: nil).or(where('account_warnings.overruled_at >= ?', 30.days.ago)) } def statuses Status.with_discarded.where(id: status_ids || []) end + + def overruled? + overruled_at.present? + end end diff --git a/app/models/admin/action_log_filter.rb b/app/models/admin/action_log_filter.rb index 12136223b..0f2f712a2 100644 --- a/app/models/admin/action_log_filter.rb +++ b/app/models/admin/action_log_filter.rb @@ -8,6 +8,8 @@ class Admin::ActionLogFilter ).freeze ACTION_TYPE_MAP = { + approve_appeal: { target_type: 'Appeal', action: 'approve' }.freeze, + reject_appeal: { target_type: 'Appeal', action: 'reject' }.freeze, assigned_to_self_report: { target_type: 'Report', action: 'assigned_to_self' }.freeze, change_email_user: { target_type: 'User', action: 'change_email' }.freeze, confirm_user: { target_type: 'User', action: 'confirm' }.freeze, diff --git a/app/models/admin/appeal_filter.rb b/app/models/admin/appeal_filter.rb new file mode 100644 index 000000000..b163d2e56 --- /dev/null +++ b/app/models/admin/appeal_filter.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +class Admin::AppealFilter + KEYS = %i( + status + ).freeze + + attr_reader :params + + def initialize(params) + @params = params + end + + def results + scope = Appeal.order(id: :desc) + + params.each do |key, value| + next if %w(page).include?(key.to_s) + + scope.merge!(scope_for(key, value.to_s.strip)) if value.present? + end + + scope + end + + private + + def scope_for(key, value) + case key.to_s + when 'status' + status_scope(value) + else + raise "Unknown filter: #{key}" + end + end + + def status_scope(value) + case value + when 'approved' + Appeal.approved + when 'rejected' + Appeal.rejected + when 'pending' + Appeal.pending + else + raise "Unknown status: #{value}" + end + end +end diff --git a/app/models/admin/status_filter.rb b/app/models/admin/status_filter.rb index ce5bb5f46..4fba612a6 100644 --- a/app/models/admin/status_filter.rb +++ b/app/models/admin/status_filter.rb @@ -31,7 +31,7 @@ class Admin::StatusFilter def scope_for(key, value) case key.to_s when 'media' - Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id) + Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id).reorder('statuses.id desc') when 'id' Status.where(id: value) else diff --git a/app/models/appeal.rb b/app/models/appeal.rb new file mode 100644 index 000000000..1f32cfa8b --- /dev/null +++ b/app/models/appeal.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: appeals +# +# id :bigint(8) not null, primary key +# account_id :bigint(8) not null +# account_warning_id :bigint(8) not null +# text :text default(""), not null +# approved_at :datetime +# approved_by_account_id :bigint(8) +# rejected_at :datetime +# rejected_by_account_id :bigint(8) +# created_at :datetime not null +# updated_at :datetime not null +# +class Appeal < ApplicationRecord + MAX_STRIKE_AGE = 20.days + + belongs_to :account + belongs_to :strike, class_name: 'AccountWarning', foreign_key: 'account_warning_id' + belongs_to :approved_by_account, class_name: 'Account', optional: true + belongs_to :rejected_by_account, class_name: 'Account', optional: true + + validates :text, presence: true, length: { maximum: 2_000 } + validates :account_warning_id, uniqueness: true + + validate :validate_time_frame, on: :create + + scope :approved, -> { where.not(approved_at: nil) } + scope :rejected, -> { where.not(rejected_at: nil) } + scope :pending, -> { where(approved_at: nil, rejected_at: nil) } + + def pending? + !approved? && !rejected? + end + + def approved? + approved_at.present? + end + + def rejected? + rejected_at.present? + end + + def approve!(current_account) + update!(approved_at: Time.now.utc, approved_by_account: current_account) + end + + def reject!(current_account) + update!(rejected_at: Time.now.utc, rejected_by_account: current_account) + end + + private + + def validate_time_frame + errors.add(:base, I18n.t('strikes.errors.too_late')) if strike.created_at < MAX_STRIKE_AGE.ago + end +end diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index 9eaacdc03..4b38d729e 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -38,6 +38,12 @@ class MediaAttachment < ApplicationRecord MAX_DESCRIPTION_LENGTH = 1_500 + IMAGE_LIMIT = (ENV['MAX_IMAGE_SIZE'] || 10.megabytes).to_i + VIDEO_LIMIT = (ENV['MAX_VIDEO_SIZE'] || 40.megabytes).to_i + + MAX_VIDEO_MATRIX_LIMIT = 2_304_000 # 1920x1200px + MAX_VIDEO_FRAME_RATE = 60 + IMAGE_FILE_EXTENSIONS = %w(.jpg .jpeg .png .gif).freeze VIDEO_FILE_EXTENSIONS = %w(.webm .mp4 .m4v .mov).freeze AUDIO_FILE_EXTENSIONS = %w(.ogg .oga .mp3 .wav .flac .opus .aac .m4a .3gp .wma).freeze @@ -75,6 +81,7 @@ class MediaAttachment < ApplicationRecord VIDEO_FORMAT = { format: 'mp4', content_type: 'video/mp4', + vfr_frame_rate_threshold: MAX_VIDEO_FRAME_RATE, convert_options: { output: { 'loglevel' => 'fatal', @@ -152,12 +159,6 @@ class MediaAttachment < ApplicationRecord all: '-quality 90 -strip +set modify-date +set create-date', }.freeze - IMAGE_LIMIT = (ENV['MAX_IMAGE_SIZE'] || 10.megabytes).to_i - VIDEO_LIMIT = (ENV['MAX_VIDEO_SIZE'] || 40.megabytes).to_i - - MAX_VIDEO_MATRIX_LIMIT = 2_304_000 # 1920x1200px - MAX_VIDEO_FRAME_RATE = 60 - belongs_to :account, inverse_of: :media_attachments, optional: true belongs_to :status, inverse_of: :media_attachments, optional: true belongs_to :scheduled_status, inverse_of: :media_attachments, optional: true diff --git a/app/models/notification.rb b/app/models/notification.rb index c14eb8a7e..9bf296386 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -36,6 +36,7 @@ class Notification < ApplicationRecord favourite poll update + admin.sign_up ).freeze TARGET_STATUS_INCLUDES_BY_TYPE = { @@ -63,13 +64,10 @@ class Notification < ApplicationRecord scope :without_suspended, -> { joins(:from_account).merge(Account.without_suspended) } scope :browserable, ->(exclude_types = [], account_id = nil) { - types = TYPES - exclude_types.map(&:to_sym) - - if account_id.nil? - where(type: types) - else - where(type: types, from_account_id: account_id) - end + scope = all + scope = where(from_account_id: account_id) if account_id.present? + scope = scope.where(type: TYPES - exclude_types.map(&:to_sym)) unless exclude_types.empty? + scope } def type @@ -142,6 +140,8 @@ class Notification < ApplicationRecord self.from_account_id = activity&.account_id when 'Mention' self.from_account_id = activity&.status&.account_id + when 'Account' + self.from_account_id = activity&.id end end end diff --git a/app/models/user.rb b/app/models/user.rb index ee20e293e..a21e96ae5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -111,7 +111,7 @@ class User < ApplicationRecord scope :inactive, -> { where(arel_table[:current_sign_in_at].lt(ACTIVE_DURATION.ago)) } scope :active, -> { confirmed.where(arel_table[:current_sign_in_at].gteq(ACTIVE_DURATION.ago)).joins(:account).where(accounts: { suspended_at: nil }) } scope :matches_email, ->(value) { where(arel_table[:email].matches("#{value}%")) } - scope :matches_ip, ->(value) { left_joins(:ips).where('user_ips.ip <<= ?', value) } + scope :matches_ip, ->(value) { left_joins(:ips).where('user_ips.ip <<= ?', value).group('users.id') } scope :emailable, -> { confirmed.enabled.joins(:account).merge(Account.searchable) } before_validation :sanitize_languages @@ -265,6 +265,10 @@ class User < ApplicationRecord settings.notification_emails['pending_account'] end + def allows_appeal_emails? + settings.notification_emails['appeal'] + end + def allows_trending_tag_emails? settings.notification_emails['trending_tag'] end |