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>
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
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
|
||||
Reference in New Issue
Block a user