diff options
Diffstat (limited to 'app/models/user.rb')
-rw-r--r-- | app/models/user.rb | 87 |
1 files changed, 60 insertions, 27 deletions
diff --git a/app/models/user.rb b/app/models/user.rb index ca7fc3b058f..01eba7e0426 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -28,7 +28,7 @@ class User < ActiveRecord::Base ignore_column :email_provider ignore_column :authentication_token - add_authentication_token_field :incoming_email_token + add_authentication_token_field :incoming_email_token, token_generator: -> { SecureRandom.hex.to_i(16).to_s(36) } add_authentication_token_field :feed_token default_value_for :admin, false @@ -88,7 +88,7 @@ class User < ActiveRecord::Base has_one :namespace, -> { where(type: nil) }, dependent: :destroy, foreign_key: :owner_id, inverse_of: :owner, autosave: true # rubocop:disable Cop/ActiveRecordDependent # Profile - has_many :keys, -> { where(type: ['Key', nil]) }, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent + has_many :keys, -> { regular_keys }, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :deploy_keys, -> { where(type: 'DeployKey') }, dependent: :nullify # rubocop:disable Cop/ActiveRecordDependent has_many :gpg_keys @@ -347,18 +347,36 @@ class User < ActiveRecord::Base # Find a User by their primary email or any associated secondary email def find_by_any_email(email, confirmed: false) + return unless email + by_any_email(email, confirmed: confirmed).take end - # Returns a relation containing all the users for the given Email address - def by_any_email(email, confirmed: false) - users = where(email: email) - users = users.confirmed if confirmed + # Returns a relation containing all the users for the given email addresses + # + # @param emails [String, Array<String>] email addresses to check + # @param confirmed [Boolean] Only return users where the email is confirmed + def by_any_email(emails, confirmed: false) + emails = Array(emails).map(&:downcase) + + from_users = where(email: emails) + from_users = from_users.confirmed if confirmed + + from_emails = joins(:emails).where(emails: { email: emails }) + from_emails = from_emails.confirmed if confirmed + + items = [from_users, from_emails] + + user_ids = Gitlab::PrivateCommitEmail.user_ids_for_emails(emails) + items << where(id: user_ids) if user_ids.present? + + from_union(items) + end - emails = joins(:emails).where(emails: { email: email }) - emails = emails.confirmed if confirmed + def find_by_private_commit_email(email) + user_id = Gitlab::PrivateCommitEmail.user_id_for_email(email) - from_union([users, emails]) + find_by(id: user_id) end def filter(filter_name) @@ -460,12 +478,6 @@ class User < ActiveRecord::Base by_username(username).take! end - def find_by_personal_access_token(token_string) - return unless token_string - - PersonalAccessTokensFinder.new(state: 'active').find_by(token: token_string)&.user # rubocop: disable CodeReuse/Finder - end - # Returns a user for the given SSH key. def find_by_ssh_key_id(key_id) Key.find_by(id: key_id)&.user @@ -639,6 +651,10 @@ class User < ActiveRecord::Base def commit_email return self.email unless has_attribute?(:commit_email) + if super == Gitlab::PrivateCommitEmail::TOKEN + return private_commit_email + end + # The commit email is the same as the primary email if undefined super.presence || self.email end @@ -651,6 +667,10 @@ class User < ActiveRecord::Base has_attribute?(:commit_email) && super end + def private_commit_email + Gitlab::PrivateCommitEmail.for_user(self) + end + # see if the new email is already a verified secondary email def check_for_verified_email skip_reconfirmation! if emails.confirmed.where(email: self.email).any? @@ -941,12 +961,17 @@ class User < ActiveRecord::Base if !Gitlab.config.ldap.enabled false elsif ldap_user? - !last_credential_check_at || (last_credential_check_at + 1.hour) < Time.now + !last_credential_check_at || (last_credential_check_at + ldap_sync_time) < Time.now else false end end + def ldap_sync_time + # This number resides in this method so it can be redefined in EE. + 1.hour + end + def try_obtain_ldap_lease # After obtaining this lease LDAP checks will be blocked for 600 seconds # (10 minutes) for this user. @@ -1014,6 +1039,7 @@ class User < ActiveRecord::Base def all_emails all_emails = [] all_emails << email unless temp_oauth_email? + all_emails << private_commit_email all_emails.concat(emails.map(&:email)) all_emails end @@ -1021,13 +1047,29 @@ class User < ActiveRecord::Base def verified_emails verified_emails = [] verified_emails << email if primary_email_verified? + verified_emails << private_commit_email verified_emails.concat(emails.confirmed.pluck(:email)) verified_emails end + def any_email?(check_email) + downcased = check_email.downcase + + # handle the outdated private commit email case + return true if persisted? && + id == Gitlab::PrivateCommitEmail.user_id_for_email(downcased) + + all_emails.include?(check_email.downcase) + end + def verified_email?(check_email) downcased = check_email.downcase - email == downcased ? primary_email_verified? : emails.confirmed.where(email: downcased).exists? + + # handle the outdated private commit email case + return true if persisted? && + id == Gitlab::PrivateCommitEmail.user_id_for_email(downcased) + + verified_emails.include?(check_email.downcase) end def hook_attrs @@ -1138,7 +1180,7 @@ class User < ActiveRecord::Base events = Event.select(:project_id) .contributions.where(author_id: self) .where("created_at > ?", Time.now - 1.year) - .uniq + .distinct .reorder(nil) Project.where(id: events) @@ -1464,15 +1506,6 @@ class User < ActiveRecord::Base end end - def generate_token(token_field) - if token_field == :incoming_email_token - # Needs to be all lowercase and alphanumeric because it's gonna be used in an email address. - SecureRandom.hex.to_i(16).to_s(36) - else - super - end - end - def self.unique_internal(scope, username, email_pattern, &block) scope.first || create_unique_internal(scope, username, email_pattern, &block) end |