Files
manyfold/app/models/user.rb
T

209 lines
5.3 KiB
Ruby

require "uri"
class User < ApplicationRecord
include Lister
include Follower
include CaberSubject
include PublicIDable
before_save :set_quota
acts_as_federails_actor(
username_field: :username,
name_field: :username,
user_count_method: :user_count
)
rolify
devise :database_authenticatable,
:registerable, :zxcvbnable,
:rememberable, :recoverable,
:lockable, :timeoutable
devise :omniauthable, omniauth_providers: %i[openid_connect] if SiteSettings.oidc_enabled?
validates :username, multimodel_uniqueness: {case_sensitive: false, check: FederailsCommon::FEDIVERSE_USERNAMES}
validates :username,
presence: true,
uniqueness: {case_sensitive: false},
format: {with: /\A[[:alnum:]]+\z/}
validates :email,
presence: true,
uniqueness: {case_sensitive: false},
format: {with: URI::MailTo::EMAIL_REGEXP}
validates :password,
presence: true,
confirmation: true,
if: :password_required?
after_create :assign_default_role
# Explicitly explain serialization for MariaDB
attribute :pagination_settings, :json
attribute :renderer_settings, :json
attribute :tag_cloud_settings, :json
attribute :problem_settings, :json
attribute :file_list_settings, :json
has_many :access_grants, # rubocop:disable Rails/InverseOf
class_name: "Doorkeeper::AccessGrant",
foreign_key: :resource_owner_id,
dependent: :delete_all
has_many :access_tokens, # rubocop:disable Rails/InverseOf
class_name: "Doorkeeper::AccessToken",
foreign_key: :resource_owner_id,
dependent: :delete_all
has_many :oauth_applications,
class_name: "Doorkeeper::Application",
as: :owner,
dependent: :delete_all,
inverse_of: :owner
def federails_name
username
end
def to_param
username
end
def self.find_param(param)
find_by!(username: param)
end
def printed?(file)
listed?(file, :printed)
end
def self.ransackable_attributes(auth_object = nil)
["created_at", "email", "id", "updated_at", "username"]
end
def self.ransackable_associations(auth_object = nil)
["role"]
end
def is_administrator?
has_any_role_of? :administrator
end
def is_moderator?
has_any_role_of? :administrator, :moderator
end
def is_contributor?
has_any_role_of? :administrator, :moderator, :contributor
end
def is_member?
has_any_role_of? :administrator, :moderator, :contributor, :member
end
def problem_severity(category)
problem_settings[category.to_s]&.to_sym || Problem::DEFAULT_SEVERITIES[category.to_sym]
end
def self.from_omniauth(auth)
# Match existing users by email first
user = find_by(auth_provider: nil, auth_uid: nil, email: auth.info.email)
if user
user.update!(
auth_provider: auth.provider,
auth_uid: auth.uid
)
else
# Email isn't present, so let's match by ID
user = find_or_create_by(auth_provider: auth.provider, auth_uid: auth.uid) do |user|
user.email = auth.info.email
# Find an unused username - get the first of a few options
user.username = [
auth.info.preferred_username,
auth.info.nickname&.parameterize,
auth.info.email&.split("@")&.[](0),
# Fallback to any of the above with some random numbers on the end
(auth.info.preferred_username || auth.info.nickname&.parameterize || auth.info.email&.split("@")&.[](0) || "") + SecureRandom.hex(2)
].compact.find { |u| !User.exists?(username: u) }
end
end
user
end
def self.user_count(range)
return User.count if range.nil? # rubocop:disable Pundit/UsePolicyScope
# Updated date isn't a great proxy for activity, but it'll do for now
# We can improve this by using devise trackable to track logins at some point
User.where(updated_at: range).count # rubocop:disable Pundit/UsePolicyScope
end
# Devise approval checks
def active_for_authentication?
super && approved?
end
def inactive_message
approved? ? super : :not_approved
end
def self.send_reset_password_instructions(attributes = {})
recoverable = find_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
if recoverable.persisted?
if recoverable.approved?
recoverable.send_reset_password_instructions
else
recoverable.errors.add(:base, :not_approved)
end
end
recoverable
end
def to_activitypub_object
ActivityPub::UserSerializer.new(self).serialize
end
def public?
true
end
# Quota is in MB and is referred to in the UI as file storage limits for clarity
def quota
quota_use_site_default ? SiteSettings.default_user_quota : attributes["quota"].to_i * 1.megabyte
end
def has_quota?
!(attributes["quota"] == 0) && SiteSettings.enable_user_quota
end
def current_space_used
permitted_models.with_permission("own").sum(&:size_on_disk)
end
private
def set_quota
attributes["quota"] = SiteSettings.default_user_quota if quota_use_site_default
end
def has_any_role_of?(*args)
args.map { |it| has_role? it }.any?
end
def assign_default_role
add_role(:member) if roles.blank?
end
def password_required?
return false if auth_provider && auth_uid
!persisted? || !password.nil? || !password_confirmation.nil?
end
def weak_words
["manyfold", username]
end
end