retrospring/app/models/user.rb

165 lines
5.6 KiB
Ruby
Raw Normal View History

2022-06-26 11:00:09 +02:00
# frozen_string_literal: true
class User < ApplicationRecord
2021-12-31 22:19:21 +01:00
include User::Relationship
include User::Relationship::Follow
2022-04-18 21:24:15 +02:00
include User::Relationship::Block
2022-12-28 02:59:51 +01:00
include User::Relationship::Mute
include User::AnswerMethods
include User::BanMethods
include User::InboxMethods
2023-02-25 15:46:11 +01:00
include User::NotificationMethods
include User::QuestionMethods
include User::PushNotificationMethods
include User::ReactionMethods
include User::RelationshipMethods
include User::SharingMethods
include User::TimelineMethods
2020-10-18 10:39:46 +02:00
include ActiveModel::OneTimePassword
2014-08-01 12:07:16 +02:00
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
2015-01-01 18:17:34 +01:00
devise :database_authenticatable, :async, :registerable,
2014-08-01 15:27:08 +02:00
:recoverable, :rememberable, :trackable,
2023-01-02 11:16:47 +01:00
:validatable, :confirmable, authentication_keys: [:login]
2014-11-30 19:43:22 +01:00
2020-10-18 10:39:46 +02:00
has_one_time_password
enum otp_module: { disabled: 0, enabled: 1 }, _prefix: true
2020-10-18 10:39:46 +02:00
attr_accessor :otp_attempt, :otp_validation
2023-01-02 11:16:47 +01:00
attr_writer :login
2020-10-18 10:39:46 +02:00
rolify
has_many :questions, dependent: :destroy_async
has_many :answers, dependent: :destroy_async
has_many :comments, dependent: :destroy_async
has_many :inboxes, dependent: :destroy_async
has_many :smiles, class_name: "Reaction", dependent: :destroy_async
has_many :notifications, foreign_key: :recipient_id, dependent: :destroy_async
has_many :reports, dependent: :destroy_async
has_many :lists, dependent: :destroy_async
has_many :list_memberships, class_name: "ListMember", dependent: :destroy_async
has_many :mute_rules, dependent: :destroy_async
has_many :anonymous_blocks, dependent: :destroy_async
2014-11-30 14:43:35 +01:00
has_many :subscriptions, dependent: :destroy_async
has_many :totp_recovery_codes, dependent: :destroy_async
2022-09-11 20:10:21 +02:00
has_many :web_push_subscriptions, dependent: :destroy_async
2015-04-21 03:12:11 +02:00
has_one :profile, dependent: :destroy
has_one :theme, dependent: :destroy
has_many :bans, class_name: "UserBan", dependent: :destroy_async
2023-01-02 11:16:47 +01:00
has_many :banned_users, class_name: "UserBan",
foreign_key: "banned_by_id",
dependent: :nullify
SCREEN_NAME_REGEX = /\A[a-zA-Z0-9_]+\z/
2023-01-02 11:16:47 +01:00
WEBSITE_REGEX = /https?:\/\/([A-Za-z.-]+)\/?(?:.*)/i
2014-11-30 19:43:22 +01:00
before_validation do
screen_name.strip!
end
validates :email, fake_email: true, typoed_email: true
validates :sharing_custom_url, allow_blank: true, valid_url: true
validates :screen_name,
presence: true,
format: { with: SCREEN_NAME_REGEX, message: I18n.t("activerecord.validation.user.screen_name.format") },
length: { minimum: 1, maximum: 16 },
uniqueness: { case_sensitive: false },
screen_name: true
2020-05-02 00:43:46 +02:00
mount_uploader :profile_picture, ProfilePictureUploader, mount_on: :profile_picture_file_name
2020-05-17 20:58:27 +02:00
process_in_background :profile_picture
2020-05-02 00:43:46 +02:00
mount_uploader :profile_header, ProfileHeaderUploader, mount_on: :profile_header_file_name
2020-05-17 20:58:27 +02:00
process_in_background :profile_header
2014-12-29 10:18:12 +01:00
2020-05-02 18:45:11 +02:00
# when a user has been deleted, all reports relating to the user become invalid
2015-04-30 02:04:43 +02:00
before_destroy do
2023-01-02 11:16:47 +01:00
Report.where(target_id: id, type: "Reports::User").find_each do |r|
2015-04-30 02:04:43 +02:00
unless r.nil?
r.deleted = true
r.save
end
end
end
after_destroy do
Retrospring::Metrics::USERS_DESTROYED.increment
end
after_create do
Profile.create(user_id: id) if Profile.where(user_id: id).count.zero?
Retrospring::Metrics::USERS_CREATED.increment
end
# use the screen name as parameter for url helpers
def to_param = screen_name
2023-01-02 11:16:47 +01:00
def login = @login || screen_name || email
2014-11-30 19:43:22 +01:00
2014-08-01 15:27:08 +02:00
def self.find_first_by_auth_conditions(warden_conditions)
2015-04-22 00:33:55 +02:00
conditions = warden_conditions.dup
2023-01-02 11:16:47 +01:00
if (login = conditions.delete(:login))
where(conditions).where(["lower(screen_name) = :value OR lower(email) = :value", { value: login.downcase }]).first
2014-08-01 15:27:08 +02:00
else
where(conditions).first
end
end
# @param list [List]
# @return [Boolean] true if +self+ is a member of +list+
2023-01-02 11:16:47 +01:00
def member_of?(list) = list_memberships.pluck(:list_id).include? list.id
2015-01-14 07:07:40 +01:00
# answers a question
# @param question [Question] the question to answer
# @param content [String] the answer content
def answer(question, content)
raise Errors::AnsweringOtherBlockedSelf if question.user&.blocking?(self)
2022-06-11 23:14:01 +02:00
raise Errors::AnsweringSelfBlockedOther if self.blocking?(question.user)
Retrospring::Metrics::QUESTIONS_ANSWERED.increment
2023-01-02 11:16:47 +01:00
Answer.create!(content:, user: self, question:)
end
2015-01-03 18:40:56 +01:00
# has the user answered +question+ yet?
# @param question [Question]
2023-01-02 11:16:47 +01:00
def answered?(question) = question.answers.pluck(:user_id).include? id
2015-01-03 18:40:56 +01:00
2014-12-05 14:11:08 +01:00
def comment(answer, content)
raise Errors::CommentingSelfBlockedOther if self.blocking?(answer.user)
raise Errors::CommentingOtherBlockedSelf if answer.user.blocking?(self)
Retrospring::Metrics::COMMENTS_CREATED.increment
2023-01-02 11:16:47 +01:00
Comment.create!(user: self, answer:, content:)
2014-12-05 14:11:08 +01:00
end
2014-12-28 19:32:08 +01:00
# @return [Boolean] is the user a moderator?
2023-01-02 11:16:47 +01:00
def mod? = has_cached_role?(:moderator) || has_cached_role?(:administrator)
2022-08-21 15:02:49 +02:00
2023-01-02 11:16:47 +01:00
def admin? = has_cached_role?(:administrator)
2014-12-28 19:32:08 +01:00
# region stuff used for reporting/moderation
2015-04-22 04:59:10 +02:00
def report(object, reason = nil)
2023-01-02 11:16:47 +01:00
existing = Report.find_by(type: "Reports::#{object.class}", target_id: object.id, user_id: id, deleted: false)
2015-04-22 04:59:10 +02:00
if existing.nil?
2023-01-02 11:16:47 +01:00
Report.create(type: "Reports::#{object.class}", target_id: object.id, user_id: id, reason:)
elsif !reason.nil? && reason.length.positive?
existing.append_reason(reason)
2015-04-22 04:59:10 +02:00
end
2014-12-28 19:32:08 +01:00
end
# endregion
2014-12-29 14:51:52 +01:00
2016-01-05 20:54:13 +01:00
def can_export?
2023-01-02 11:16:47 +01:00
return (Time.zone.now > export_created_at.in(1.week)) && !export_processing unless export_created_at.nil?
2023-01-02 11:16:47 +01:00
!export_processing
2022-11-06 14:59:56 +01:00
end
2023-01-02 11:16:47 +01:00
def inbox_locked? = privacy_lock_inbox
2014-08-01 12:07:16 +02:00
end