diff options
Diffstat (limited to 'app/services/users/email_verification')
-rw-r--r-- | app/services/users/email_verification/base_service.rb | 2 | ||||
-rw-r--r-- | app/services/users/email_verification/update_email_service.rb | 76 |
2 files changed, 77 insertions, 1 deletions
diff --git a/app/services/users/email_verification/base_service.rb b/app/services/users/email_verification/base_service.rb index 721290fe056..174626ac2f9 100644 --- a/app/services/users/email_verification/base_service.rb +++ b/app/services/users/email_verification/base_service.rb @@ -21,7 +21,7 @@ module Users end def digest - Devise.token_generator.digest(User, user.email, token) + Devise.token_generator.digest(User, user.email.downcase.strip, token) end end end diff --git a/app/services/users/email_verification/update_email_service.rb b/app/services/users/email_verification/update_email_service.rb new file mode 100644 index 00000000000..3f9b90b2960 --- /dev/null +++ b/app/services/users/email_verification/update_email_service.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +module Users + module EmailVerification + class UpdateEmailService + include ActionView::Helpers::DateHelper + + RATE_LIMIT = :email_verification_code_send + + def initialize(user:) + @user = user + end + + def execute(email:) + return failure(:rate_limited) if rate_limited? + return failure(:already_offered) if already_offered? + return failure(:no_change) if no_change?(email) + return failure(:validation_error) unless update_email + + success + end + + private + + attr_reader :user + + def rate_limited? + Gitlab::ApplicationRateLimiter.throttled?(RATE_LIMIT, scope: user) + end + + def already_offered? + user.email_reset_offered_at.present? + end + + def no_change?(email) + user.email = email + !user.will_save_change_to_email? + end + + def update_email + user.skip_confirmation_notification! + user.save + end + + def success + { status: :success } + end + + def failure(reason) + { + status: :failure, + reason: reason, + message: failure_message(reason) + } + end + + def failure_message(reason) + case reason + when :rate_limited + interval = distance_of_time_in_words(Gitlab::ApplicationRateLimiter.rate_limits[RATE_LIMIT][:interval]) + format( + s_("IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} and try again."), + interval: interval + ) + when :already_offered + s_('IdentityVerification|Email update is only offered once.') + when :no_change + s_('IdentityVerification|A code has already been sent to this email address. ' \ + 'Check your spam folder or enter another email address.') + when :validation_error + user.errors.full_messages.join(' ') + end + end + end + end +end |