demarches-normaliennes/app/models/user.rb

285 lines
8.3 KiB
Ruby
Raw Normal View History

2020-08-06 16:35:45 +02:00
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# blocked_at :datetime
# blocked_reason :text
2020-08-06 16:35:45 +02:00
# confirmation_sent_at :datetime
# confirmation_token :string
# confirmed_at :datetime
# current_sign_in_at :datetime
# current_sign_in_ip :string
# email :string default(""), not null
# encrypted_password :string default(""), not null
# failed_attempts :integer default(0), not null
# last_sign_in_at :datetime
# last_sign_in_ip :string
2021-09-01 18:16:01 +02:00
# locale :string
2020-08-06 16:35:45 +02:00
# locked_at :datetime
# loged_in_with_france_connect :string default(NULL)
# remember_created_at :datetime
# reset_password_sent_at :datetime
# reset_password_token :string
# sign_in_count :integer default(0), not null
# siret :string
# team_account :boolean default(FALSE)
2020-08-06 16:35:45 +02:00
# unconfirmed_email :text
# unlock_token :string
# created_at :datetime
# updated_at :datetime
# requested_merge_into_id :bigint
2020-08-06 16:35:45 +02:00
#
2018-03-06 13:44:29 +01:00
class User < ApplicationRecord
include EmailSanitizableConcern
include PasswordComplexityConcern
enum loged_in_with_france_connect: {
particulier: 'particulier',
entreprise: 'entreprise'
}
2015-09-23 10:02:01 +02:00
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable, :lockable
2015-09-23 12:16:21 +02:00
# We should never cascade delete dossiers. In normal case we call delete_and_keep_track_dossiers
# before deleting a user (which dissociate dossiers from the user).
# Destroying a user with dossier is always a mistake.
has_many :dossiers, dependent: :restrict_with_exception
has_many :targeted_user_links, dependent: :destroy
has_many :invites, dependent: :destroy
has_many :dossiers_invites, through: :invites, source: :dossier
2020-12-07 15:10:26 +01:00
has_many :deleted_dossiers
2021-10-26 14:41:30 +02:00
has_many :merge_logs, dependent: :destroy
2021-11-04 15:51:54 +01:00
has_many :requested_merge_from, class_name: 'User', dependent: :nullify, inverse_of: :requested_merge_into, foreign_key: :requested_merge_into_id
has_one :france_connect_information, dependent: :destroy
has_one :instructeur, dependent: :destroy
has_one :administrateur, dependent: :destroy
has_one :expert, dependent: :destroy
belongs_to :requested_merge_into, class_name: 'User', optional: true
accepts_nested_attributes_for :france_connect_information
2017-02-07 16:56:21 +01:00
2021-02-28 22:19:22 +01:00
default_scope { eager_load(:instructeur, :administrateur, :expert) }
before_validation -> { sanitize_email(:email) }
validate :does_not_merge_on_self, if: :requested_merge_into_id_changed?
def validate_password_complexity?
administrateur?
end
# Override of Devise::Models::Confirmable#send_confirmation_instructions
def send_confirmation_instructions
unless @raw_confirmation_token
generate_confirmation_token!
end
opts = pending_reconfirmation? ? { to: unconfirmed_email } : {}
# Make our procedure_after_confirmation available to the Mailer
opts[:procedure_after_confirmation] = CurrentConfirmation.procedure_after_confirmation
opts[:prefill_token] = CurrentConfirmation.prefill_token
send_devise_notification(:confirmation_instructions, @raw_confirmation_token, opts)
end
# Callback provided by Devise
def after_confirmation
link_invites!
end
2018-05-30 18:26:23 +02:00
def owns?(dossier)
dossier.user_id == id
end
def invite?(dossier)
invites.exists?(dossier:)
end
def owns_or_invite?(dossier)
owns?(dossier) || invite?(dossier)
end
2019-08-07 15:52:38 +02:00
def invite!
UserMailer.invite_instructeur(self, set_reset_password_token).deliver_later
end
2019-08-09 11:41:36 +02:00
def invite_administrateur!(administration_id)
AdministrationMailer.invite_admin(self, set_reset_password_token, administration_id).deliver_later
2019-08-09 11:41:36 +02:00
end
def remind_invitation!
reset_password_token = set_reset_password_token
AdministrateurMailer.activate_before_expiration(self, reset_password_token).deliver_later
end
2019-08-09 11:41:36 +02:00
def self.create_or_promote_to_instructeur(email, password, administrateurs: [])
user = User
.create_with(password: password, confirmed_at: Time.zone.now)
.find_or_create_by(email: email)
if user.valid?
if user.instructeur.nil?
user.create_instructeur!
user.update(france_connect_information: nil)
end
user.instructeur.administrateurs << administrateurs
end
user
end
def self.create_or_promote_to_administrateur(email, password)
user = User.create_or_promote_to_instructeur(email, password)
if user.valid? && user.administrateur.nil?
2020-02-03 11:09:54 +01:00
user.create_administrateur!
user.update(france_connect_information: nil)
AdminUpdateDefaultZonesJob.perform_later(user.administrateur)
end
user
end
2021-01-15 16:33:36 +01:00
def self.create_or_promote_to_expert(email, password)
user = User
.create_with(password: password, confirmed_at: Time.zone.now)
.find_or_create_by(email: email)
if user.valid?
if user.expert.nil?
2021-01-15 16:33:36 +01:00
user.create_expert!
end
end
user
end
2019-07-04 12:36:17 +02:00
def flipper_id
"User:#{id}"
end
2019-11-05 10:01:07 +01:00
def active?
last_sign_in_at.present?
end
def administrateur?
administrateur.present?
end
def instructeur?
instructeur.present?
end
2021-04-14 15:54:30 +02:00
def expert?
expert.present?
2021-04-14 15:54:30 +02:00
end
def can_france_connect?
!administrateur? && !instructeur?
end
2020-01-06 17:33:09 +01:00
def can_be_deleted?
2021-05-01 12:20:24 +02:00
!administrateur? && !instructeur? && !expert?
2020-01-06 17:33:09 +01:00
end
def delete_and_keep_track_dossiers_also_delete_user(super_admin)
if !can_be_deleted?
2021-05-01 12:20:24 +02:00
raise "Cannot delete this user because they are also instructeur, expert or administrateur"
end
transaction do
# delete invites
Invite.where(dossier: dossiers).destroy_all
delete_and_keep_track_dossiers(super_admin)
destroy!
end
end
def delete_and_keep_track_dossiers(super_admin)
transaction do
# delete dossiers brouillon
dossiers.state_brouillon.each do |dossier|
dossier.hide_and_keep_track!(dossier.user, :user_removed)
end
dossiers.state_brouillon.find_each(&:purge_discarded)
# delete dossiers en_construction
dossiers.state_en_construction.each do |dossier|
dossier.hide_and_keep_track!(dossier.user, :user_removed)
end
dossiers.state_en_construction.find_each(&:purge_discarded)
# delete dossiers terminé
dossiers.state_termine.each do |dossier|
dossier.hide_and_keep_track!(dossier.user, :user_removed)
end
dossiers.update_all(deleted_user_email_never_send: email, user_id: nil, dossier_transfer_id: nil)
2020-01-08 10:50:16 +01:00
end
end
2021-10-22 15:17:25 +02:00
def merge(old_user)
raise "Merging same user, no way" if old_user.id == self.id
2021-10-26 15:50:38 +02:00
transaction do
old_user.dossiers.update_all(user_id: id)
2021-10-26 15:50:38 +02:00
old_user.invites.update_all(user_id: id)
old_user.merge_logs.update_all(user_id: id)
old_user.targeted_user_links.update_all(user_id: id)
2021-10-26 15:50:38 +02:00
# Move or merge old user's roles to the user
2021-10-26 15:50:38 +02:00
[
[old_user.instructeur, instructeur],
[old_user.expert, expert],
[old_user.administrateur, administrateur]
].each do |old_role, targeted_role|
if targeted_role.nil?
old_role&.update(user: self)
else
targeted_role.merge(old_role)
end
2021-10-22 15:17:25 +02:00
end
# (Ensure the old user doesn't reference its former roles anymore)
old_user.reload
2021-10-26 15:50:38 +02:00
merge_logs.create(from_user_id: old_user.id, from_user_email: old_user.email)
old_user.destroy
end
2021-10-22 15:17:25 +02:00
end
2021-10-26 13:36:14 +02:00
def ask_for_merge(requested_user)
if update(requested_merge_into: requested_user)
UserMailer.ask_for_merge(self, requested_user.email).deliver_later
return true
else
return false
end
2021-10-26 13:36:14 +02:00
end
def send_devise_notification(notification, *args)
devise_mailer.send(notification, self, *args).deliver_later
end
def active_for_authentication?
super && blocked_at.nil?
end
private
def does_not_merge_on_self
return if requested_merge_into_id != self.id
errors.add(:requested_merge_into, :same)
end
def link_invites!
Invite.where(email: email).update_all(user_id: id)
end
2015-09-23 10:02:01 +02:00
end