From 891cccb8152c33cdfea77b5a8a075c34a89816ea Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 12 Nov 2024 11:08:25 -0500 Subject: [PATCH] Extract `User::Confirmation` concern --- app/models/concerns/user/confirmation.rb | 52 ++++++++++++++++++++++++ app/models/user.rb | 44 +------------------- 2 files changed, 53 insertions(+), 43 deletions(-) create mode 100644 app/models/concerns/user/confirmation.rb diff --git a/app/models/concerns/user/confirmation.rb b/app/models/concerns/user/confirmation.rb new file mode 100644 index 0000000000..646aa0d527 --- /dev/null +++ b/app/models/concerns/user/confirmation.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +module User::Confirmation + extend ActiveSupport::Concern + + included do + scope :confirmed, -> { where.not(confirmed_at: nil) } + scope :unconfirmed, -> { where(confirmed_at: nil) } + end + + def confirmed? + confirmed_at.present? + end + + def unconfirmed? + !confirmed? + end + + def confirm + wrap_email_confirmation do + super + end + end + + # Mark current email as confirmed, bypassing Devise + def mark_email_as_confirmed! + wrap_email_confirmation do + skip_confirmation! + save! + end + end + + private + + def wrap_email_confirmation + new_user = !confirmed? + self.approved = true if grant_approval_on_confirmation? + + yield + + if new_user + # Handle race condition when approving and confirming user at the same time + reload unless approved? + + if approved? + prepare_new_user! + else + notify_staff_about_pending_account! + end + end + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 9a215669b9..2cc01e8c90 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -56,6 +56,7 @@ class User < ApplicationRecord include LanguagesHelper include Redisable + include User::Confirmation include User::HasSettings include User::LdapAuthenticable include User::Omniauthable @@ -117,8 +118,6 @@ class User < ApplicationRecord scope :recent, -> { order(id: :desc) } scope :pending, -> { where(approved: false) } scope :approved, -> { where(approved: true) } - scope :confirmed, -> { where.not(confirmed_at: nil) } - scope :unconfirmed, -> { where(confirmed_at: nil) } scope :enabled, -> { where(disabled: false) } scope :disabled, -> { where(disabled: true) } scope :active, -> { confirmed.signed_in_recently.account_not_suspended } @@ -165,10 +164,6 @@ class User < ApplicationRecord end end - def confirmed? - confirmed_at.present? - end - def invited? invite_id.present? end @@ -193,20 +188,6 @@ class User < ApplicationRecord account_id end - def confirm - wrap_email_confirmation do - super - end - end - - # Mark current email as confirmed, bypassing Devise - def mark_email_as_confirmed! - wrap_email_confirmation do - skip_confirmation! - save! - end - end - def update_sign_in!(new_sign_in: false) old_current = current_sign_in_at new_current = Time.now.utc @@ -239,10 +220,6 @@ class User < ApplicationRecord confirmed? && approved? && !disabled? && !account.unavailable? && !account.memorial? end - def unconfirmed? - !confirmed? - end - def unconfirmed_or_pending? unconfirmed? || pending? end @@ -424,25 +401,6 @@ class User < ApplicationRecord open_registrations? && !sign_up_from_ip_requires_approval? && !sign_up_email_requires_approval? end - def wrap_email_confirmation - new_user = !confirmed? - self.approved = true if grant_approval_on_confirmation? - - yield - - if new_user - # Avoid extremely unlikely race condition when approving and confirming - # the user at the same time - reload unless approved? - - if approved? - prepare_new_user! - else - notify_staff_about_pending_account! - end - end - end - def sign_up_from_ip_requires_approval? sign_up_ip.present? && IpBlock.severity_sign_up_requires_approval.containing(sign_up_ip.to_s).exists? end