2023-11-03 09:24:38 +01:00
|
|
|
class ExpiredUsersDeletionService
|
2023-11-03 13:52:37 +01:00
|
|
|
include MailRateLimitable
|
|
|
|
|
2023-11-03 10:39:41 +01:00
|
|
|
RETENTION_AFTER_NOTICE_IN_WEEK = 2
|
2023-11-03 13:52:37 +01:00
|
|
|
EXPIRABLE_AFTER_IN_YEAR = 2
|
2023-11-03 10:11:08 +01:00
|
|
|
|
2023-11-03 13:52:37 +01:00
|
|
|
def process_expired
|
2023-11-06 09:29:47 +01:00
|
|
|
[expiring_users_without_dossiers, expiring_users_with_dossiers].each do |expiring_segment|
|
2023-11-03 12:13:41 +01:00
|
|
|
delete_expired_users(expiring_segment)
|
|
|
|
send_inactive_close_to_expiration_notice(expiring_segment)
|
|
|
|
end
|
2023-11-03 10:11:08 +01:00
|
|
|
end
|
|
|
|
|
2023-11-06 09:29:47 +01:00
|
|
|
private
|
|
|
|
|
2023-11-03 13:52:37 +01:00
|
|
|
def send_inactive_close_to_expiration_notice(users)
|
2023-11-03 12:13:41 +01:00
|
|
|
to_notify_only(users).in_batches do |batch|
|
2023-11-03 10:11:08 +01:00
|
|
|
batch.each do |user|
|
2023-11-03 13:52:37 +01:00
|
|
|
safe_send_email(UserMailer.notify_inactive_close_to_deletion(user))
|
2023-11-03 10:11:08 +01:00
|
|
|
end
|
|
|
|
batch.update_all(inactive_close_to_expiration_notice_sent_at: Time.zone.now.utc)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-11-03 13:52:37 +01:00
|
|
|
def delete_expired_users(users)
|
2023-11-03 12:13:41 +01:00
|
|
|
to_delete_only(users).find_each do |user|
|
2023-11-04 08:45:40 +01:00
|
|
|
begin
|
|
|
|
user.delete_and_keep_track_dossiers_also_delete_user(nil)
|
|
|
|
rescue => e
|
|
|
|
Sentry.capture_exception(e, extra: { user_id: user.id })
|
|
|
|
end
|
2023-11-03 09:24:38 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# rubocop:disable DS/Unscoped
|
2023-11-03 13:52:37 +01:00
|
|
|
def expiring_users_with_dossiers
|
2023-11-06 10:43:21 +01:00
|
|
|
users = User.arel_table
|
|
|
|
dossiers = Dossier.arel_table
|
|
|
|
|
2023-11-03 09:24:38 +01:00
|
|
|
User.unscoped # avoid default_scope eager_loading :export, :instructeur, :administrateur
|
2023-11-06 09:18:22 +01:00
|
|
|
.where.missing(:expert, :instructeur, :administrateur)
|
2023-11-06 10:43:21 +01:00
|
|
|
.joins(
|
|
|
|
users.join(dossiers, Arel::Nodes::InnerJoin)
|
|
|
|
.on(users[:id].eq(dossiers[:user_id])
|
|
|
|
.and(dossiers[:state].not_eq(Dossier.states.fetch(:en_instruction))))
|
|
|
|
.join_sources
|
|
|
|
)
|
2023-11-03 13:52:37 +01:00
|
|
|
.having('MAX(dossiers.created_at) < ?', EXPIRABLE_AFTER_IN_YEAR.years.ago)
|
2023-11-03 09:24:38 +01:00
|
|
|
.group('users.id')
|
|
|
|
end
|
2023-11-03 12:13:41 +01:00
|
|
|
|
2023-11-03 13:52:37 +01:00
|
|
|
def expiring_users_without_dossiers
|
2023-11-03 12:13:41 +01:00
|
|
|
User.unscoped
|
2023-11-06 09:18:22 +01:00
|
|
|
.where.missing(:expert, :instructeur, :administrateur, :dossiers)
|
2023-11-03 13:52:37 +01:00
|
|
|
.where(last_sign_in_at: ..EXPIRABLE_AFTER_IN_YEAR.years.ago)
|
2023-11-03 12:13:41 +01:00
|
|
|
end
|
2023-11-03 09:24:38 +01:00
|
|
|
# rubocop:enable DS/Unscoped
|
2023-11-03 10:11:08 +01:00
|
|
|
|
2023-11-03 13:52:37 +01:00
|
|
|
def to_notify_only(users)
|
2023-11-03 12:13:41 +01:00
|
|
|
users.where(inactive_close_to_expiration_notice_sent_at: nil)
|
2023-11-04 08:45:40 +01:00
|
|
|
.limit(limit)
|
2023-11-03 10:11:08 +01:00
|
|
|
end
|
|
|
|
|
2023-11-03 13:52:37 +01:00
|
|
|
def to_delete_only(users)
|
2023-11-03 12:13:41 +01:00
|
|
|
users.where.not(inactive_close_to_expiration_notice_sent_at: RETENTION_AFTER_NOTICE_IN_WEEK.weeks.ago..)
|
2023-11-03 10:11:08 +01:00
|
|
|
end
|
2023-11-04 08:45:40 +01:00
|
|
|
|
|
|
|
def limit
|
|
|
|
(ENV['EXPIRE_USER_DELETION_JOB_LIMIT'] || 10_000).to_i
|
|
|
|
end
|
2023-11-03 09:24:38 +01:00
|
|
|
end
|