diff options
Diffstat (limited to 'app/services/users')
4 files changed, 82 insertions, 4 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 diff --git a/app/services/users/refresh_authorized_projects_service.rb b/app/services/users/refresh_authorized_projects_service.rb index b1ffd006795..197260a80ca 100644 --- a/app/services/users/refresh_authorized_projects_service.rb +++ b/app/services/users/refresh_authorized_projects_service.rb @@ -67,8 +67,10 @@ module Users def update_authorizations(remove = [], add = []) log_refresh_details(remove, add) - ProjectAuthorization.delete_all_in_batches_for_user(user: user, project_ids: remove) if remove.any? - ProjectAuthorization.insert_all_in_batches(add) if add.any? + ProjectAuthorizations::Changes.new do |changes| + changes.add(add) + changes.remove_projects_for_user(user, remove) + end.apply! # Since we batch insert authorization rows, Rails' associations may get # out of sync. As such we force a reload of the User object. diff --git a/app/services/users/update_service.rb b/app/services/users/update_service.rb index 36c41c03303..cc179ba964a 100644 --- a/app/services/users/update_service.rb +++ b/app/services/users/update_service.rb @@ -120,7 +120,7 @@ module Users def after_update(user_exists) notify_success(user_exists) - remove_followers_and_followee! if ::Feature.enabled?(:disable_follow_users, user) + remove_followers_and_followee! success end |