Files
eminuxCRM/app/models/user.rb
T
eminuxandCursor c4e5f289cf
CI / scan_ruby (push) Failing after 11m20s
CI / scan_js (push) Successful in 10m35s
CI / lint (push) Has been cancelled
Commit iniziale di eminuxCRM: CRM Rails con pipeline, campagne email e Docker.
Include autenticazione, progetti isolati, mail marketing HTML con SMTP, test A/B e editor WYSIWYG.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 23:01:48 +02:00

128 lines
3.5 KiB
Ruby

class User < ApplicationRecord
include Auditable
has_secure_password
has_many :assigned_organizations, class_name: "Organization", foreign_key: :assigned_user_id, dependent: :nullify, inverse_of: :assigned_user
has_many :assigned_opportunities, class_name: "Opportunity", foreign_key: :assigned_user_id, dependent: :nullify, inverse_of: :assigned_user
has_many :assigned_tasks, class_name: "Task", foreign_key: :assigned_user_id, dependent: :nullify, inverse_of: :assigned_user
has_many :activities, dependent: :nullify
has_many :user_projects, dependent: :destroy
has_many :projects, through: :user_projects
ROLES = %w[admin user].freeze
validates :email, presence: true, uniqueness: { case_sensitive: false },
format: { with: URI::MailTo::EMAIL_REGEXP }
validates :first_name, :last_name, presence: true
validates :role, inclusion: { in: ROLES }
validates :password, length: { minimum: 8 }, if: -> { password.present? }
validate :must_keep_at_least_one_active_admin
before_validation :normalize_email
before_destroy :prevent_destroying_last_admin
scope :active, -> { where(active: true) }
scope :admins, -> { where(role: "admin") }
scope :active_admins, -> { active.admins }
def admin?
role == "admin"
end
def full_name
"#{first_name} #{last_name}"
end
def last_active_admin?
admin? && active? && self.class.active_admins.where.not(id: id).none?
end
def can_be_deactivated?
return true unless admin? && active?
!last_active_admin?
end
def can_be_destroyed?
!last_active_admin?
end
def accessible_projects
return Project.active.ordered if admin?
Project.active.ordered
.joins(:user_projects)
.where(user_projects: { user_id: id, enabled: true })
end
def can_access_project?(project)
return true if admin?
return false if project.nil?
user_projects.exists?(project_id: project.id, enabled: true)
end
def enable_project!(project)
up = user_projects.find_or_initialize_by(project: project)
up.enabled = true
up.save!
end
def disable_project!(project)
up = user_projects.find_or_initialize_by(project: project)
up.enabled = false
up.save!
end
def project_enabled?(project)
return true if admin?
user_projects.exists?(project_id: project.id, enabled: true)
end
def generate_password_reset_token!
update!(
password_reset_token: SecureRandom.urlsafe_base64(32),
password_reset_sent_at: Time.current
)
end
def password_reset_token_valid?
password_reset_token.present? &&
password_reset_sent_at.present? &&
password_reset_sent_at > 2.hours.ago
end
def clear_password_reset_token!
update!(password_reset_token: nil, password_reset_sent_at: nil)
end
private
def normalize_email
self.email = email.to_s.strip.downcase
end
def must_keep_at_least_one_active_admin
return if new_record?
was_active_admin = role_in_database == "admin" && active_in_database != false
return unless was_active_admin
deactivating = will_save_change_to_active? && !active?
demoting = will_save_change_to_role? && role != "admin"
return unless deactivating || demoting
return if self.class.active_admins.where.not(id: id).exists?
errors.add(:base, "Deve restare almeno un amministratore attivo. Crea o promuovi un altro admin prima.")
end
def prevent_destroying_last_admin
return unless last_active_admin?
errors.add(:base, "Non puoi eliminare l'unico amministratore attivo.")
throw :abort
end
end