Files
timeoverflow/app/models/user.rb
2026-04-07 10:02:31 +02:00

154 lines
3.7 KiB
Ruby

class User < ApplicationRecord
devise *[
:database_authenticatable,
:recoverable,
:rememberable,
:confirmable,
:lockable,
:trackable,
:timeoutable
]
ransacker :username do
Arel.sql('unaccent(users.username)')
end
GENDERS = %w(
female
male
others
prefer_not_to_answer
)
attr_accessor :empty_email
attr_accessor :from_signup
attribute :confirm_immediately, :boolean
has_one_attached :avatar
has_many :members, dependent: :destroy
has_many :organizations, through: :members
has_many :accounts, through: :members
has_many :movements, through: :accounts
has_many :posts
has_many :offers
has_many :inquiries
has_many :device_tokens
has_many :petitions, dependent: :delete_all
accepts_nested_attributes_for :members, allow_destroy: true
default_scope { order("users.id ASC") }
scope :without_memberships, -> { where.missing(:members) }
scope :actives, -> { joins(:members).where(members: { active: true }) }
scope :online_active, -> { where("sign_in_count > 0") }
scope :notifications, -> { where(notifications: true) }
scope :confirmed, -> { where.not(confirmed_at: nil) }
validates :username, presence: true
validates :email, presence: true, uniqueness: true
validates :password, presence: true, if: :from_signup?
# Allows @domain.com for dummy emails but does not allow pure invalid
# emails like 'without email'
validates_format_of :email,
with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
validates :gender, inclusion: { in: GENDERS, allow_blank: true }
def as_member_of(organization)
organization && members.find_by(organization: organization)
end
def admins?(organization)
organization && !!(as_member_of(organization).try :manager)
end
alias :manages? :admins?
def superadmin?
ADMINS.include? email
end
alias :superuser? :superadmin?
def to_s
"#{username}"
end
def user
self
end
def add_to_organization(organization)
return unless organization
member = members.where(organization: organization).first_or_initialize
return member if member.persisted?
member.entry_date = DateTime.now.utc
persister = ::Persister::MemberPersister.new(member)
persister.save
member if member.persisted?
end
def active?(organization)
organization && !!(as_member_of(organization).try :active)
end
def memberships?
members.any?
end
def no_membership_warning?
confirmed? && terms_accepted_at.present? && !memberships?
end
def member(organization)
members.where(organization_id: organization).first
end
def set_dummy_email
self.email = "user#{id}@example.com"
skip_reconfirmation! # auto-reconfirm
end
def setup_and_save_user
# check if email is provided or not. If not, flag it and generate
# temporary valid email with current time milliseconds
# this will be updated to user.id@example.com later on
self.empty_email = email.strip.empty?
self.email = "user#{DateTime.now.strftime('%Q')}@example.com" if empty_email && !from_signup
skip_confirmation! unless from_signup?
save
end
def tune_after_persisted(organization)
add_to_organization organization
# If email was empty, udpate again with user.id just generated
set_dummy_email if empty_email
save
end
def add_tags(organization, tag_list)
member = as_member_of(organization)
member.update(tag_list: tag_list)
end
def has_valid_email?
!email.include? "example.com"
end
def email_if_real
has_valid_email? ? email : ""
end
def was_member?(petition)
petition.status == 'accepted' && Member.where(organization: petition.organization, user: self).none?
end
def from_signup?
from_signup
end
end