diff options
author | Tiago Botelho <tiagonbotelho@hotmail.com> | 2018-11-07 11:00:21 +0000 |
---|---|---|
committer | Tiago Botelho <tiagonbotelho@hotmail.com> | 2018-11-07 12:24:14 +0000 |
commit | c239452b47f2819e3ed2fdaf4679737b3e1a456e (patch) | |
tree | bfaee22cd6c0f180faa2a9f83a97375efd804fff | |
parent | c81d4a65a255146619ccf52ece16757c7db622ae (diff) | |
download | gitlab-ce-c239452b47f2819e3ed2fdaf4679737b3e1a456e.tar.gz |
User can keep their commit email private43521-keep-personal-emails-private
The private commit email is automatically generated in the format:
id-username@noreply.HOSTNAME
GitLab instance admins are able to change the HOSTNAME portion,
that defaults to Gitlab's hostname, to whatever they prefer.
-rw-r--r-- | app/helpers/application_settings_helper.rb | 3 | ||||
-rw-r--r-- | app/helpers/avatars_helper.rb | 2 | ||||
-rw-r--r-- | app/helpers/profiles_helper.rb | 14 | ||||
-rw-r--r-- | app/models/application_setting.rb | 13 | ||||
-rw-r--r-- | app/models/commit.rb | 2 | ||||
-rw-r--r-- | app/models/user.rb | 30 | ||||
-rw-r--r-- | app/views/admin/application_settings/_email.html.haml | 6 | ||||
-rw-r--r-- | app/views/profiles/show.html.haml | 5 | ||||
-rw-r--r-- | changelogs/unreleased/43521-keep-personal-emails-private.yml | 5 | ||||
-rw-r--r-- | db/migrate/20181025115728_add_private_commit_email_hostname_to_application_settings.rb | 11 | ||||
-rw-r--r-- | db/schema.rb | 1 | ||||
-rw-r--r-- | doc/development/utilities.md | 4 | ||||
-rw-r--r-- | doc/user/admin_area/settings/email.md | 17 | ||||
-rw-r--r-- | doc/user/profile/index.md | 40 | ||||
-rw-r--r-- | lib/gitlab/private_commit_email.rb | 28 | ||||
-rw-r--r-- | locale/gitlab.pot | 15 | ||||
-rw-r--r-- | spec/helpers/profiles_helper_spec.rb | 29 | ||||
-rw-r--r-- | spec/lib/gitlab/private_commit_email_spec.rb | 41 | ||||
-rw-r--r-- | spec/models/application_setting_spec.rb | 11 | ||||
-rw-r--r-- | spec/models/user_spec.rb | 79 |
20 files changed, 345 insertions, 11 deletions
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 9a1c2a4c9e1..086bb38ce9a 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -217,7 +217,8 @@ module ApplicationSettingsHelper :user_oauth_applications, :version_check_enabled, :web_ide_clientside_preview_enabled, - :diff_max_patch_bytes + :diff_max_patch_bytes, + :commit_email_hostname ] end diff --git a/app/helpers/avatars_helper.rb b/app/helpers/avatars_helper.rb index 7fc4c1a023f..5906ddabee4 100644 --- a/app/helpers/avatars_helper.rb +++ b/app/helpers/avatars_helper.rb @@ -22,7 +22,7 @@ module AvatarsHelper end def avatar_icon_for_email(email = nil, size = nil, scale = 2, only_path: true) - user = User.find_by_any_email(email.try(:downcase)) + user = User.find_by_any_email(email) if user avatar_icon_for_user(user, size, scale, only_path: only_path) else diff --git a/app/helpers/profiles_helper.rb b/app/helpers/profiles_helper.rb index 55674e37a34..42f9a1213e9 100644 --- a/app/helpers/profiles_helper.rb +++ b/app/helpers/profiles_helper.rb @@ -1,6 +1,20 @@ # frozen_string_literal: true module ProfilesHelper + def commit_email_select_options(user) + private_email = user.private_commit_email + verified_emails = user.verified_emails - [private_email] + + [ + [s_("Profiles|Use a private email - %{email}").html_safe % { email: private_email }, Gitlab::PrivateCommitEmail::TOKEN], + verified_emails + ] + end + + def selected_commit_email(user) + user.read_attribute(:commit_email) || user.commit_email + end + def attribute_provider_label(attribute) user_synced_attributes_metadata = current_user.user_synced_attributes_metadata if user_synced_attributes_metadata&.synced?(attribute) diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 704310f53f0..207ffae873a 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -187,6 +187,8 @@ class ApplicationSetting < ActiveRecord::Base validates :user_default_internal_regex, js_regex: true, allow_nil: true + validates :commit_email_hostname, format: { with: /\A[^@]+\z/ } + validates :archive_builds_in_seconds, allow_nil: true, numericality: { only_integer: true, greater_than_or_equal_to: 1.day.seconds } @@ -299,10 +301,15 @@ class ApplicationSetting < ActiveRecord::Base user_default_internal_regex: nil, user_show_add_ssh_key_message: true, usage_stats_set_by_user_id: nil, - diff_max_patch_bytes: Gitlab::Git::Diff::DEFAULT_MAX_PATCH_BYTES + diff_max_patch_bytes: Gitlab::Git::Diff::DEFAULT_MAX_PATCH_BYTES, + commit_email_hostname: default_commit_email_hostname } end + def self.default_commit_email_hostname + "users.noreply.#{Gitlab.config.gitlab.host}" + end + def self.create_from_defaults create(defaults) end @@ -358,6 +365,10 @@ class ApplicationSetting < ActiveRecord::Base Array(read_attribute(:repository_storages)) end + def commit_email_hostname + super.presence || self.class.default_commit_email_hostname + end + def default_project_visibility=(level) super(Gitlab::VisibilityLevel.level_value(level)) end diff --git a/app/models/commit.rb b/app/models/commit.rb index a61ed03cf35..9dd0cbacd9e 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -260,7 +260,7 @@ class Commit request_cache(:author) { author_email.downcase } def committer - @committer ||= User.find_by_any_email(committer_email.downcase) + @committer ||= User.find_by_any_email(committer_email) end def parents diff --git a/app/models/user.rb b/app/models/user.rb index 039a3854edb..a400058e87e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -347,7 +347,11 @@ class User < ActiveRecord::Base # Find a User by their primary email or any associated secondary email def find_by_any_email(email, confirmed: false) - by_any_email(email, confirmed: confirmed).take + return unless email + + downcased = email.downcase + + find_by_private_commit_email(downcased) || by_any_email(downcased, confirmed: confirmed).take end # Returns a relation containing all the users for the given Email address @@ -361,6 +365,12 @@ class User < ActiveRecord::Base from_union([users, emails]) end + def find_by_private_commit_email(email) + user_id = Gitlab::PrivateCommitEmail.user_id_for_email(email) + + find_by(id: user_id) + end + def filter(filter_name) case filter_name when 'admins' @@ -633,6 +643,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 @@ -645,6 +659,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? @@ -1020,13 +1038,21 @@ 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 verified_email?(check_email) downcased = check_email.downcase - email == downcased ? primary_email_verified? : emails.confirmed.where(email: downcased).exists? + + if email == downcased + primary_email_verified? + else + user_id = Gitlab::PrivateCommitEmail.user_id_for_email(downcased) + + user_id == id || emails.confirmed.where(email: downcased).exists? + end end def hook_attrs diff --git a/app/views/admin/application_settings/_email.html.haml b/app/views/admin/application_settings/_email.html.haml index 86339e61215..60a6be731ea 100644 --- a/app/views/admin/application_settings/_email.html.haml +++ b/app/views/admin/application_settings/_email.html.haml @@ -20,5 +20,11 @@ By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format. + .form-group + = f.label :commit_email_hostname, _('Custom hostname (for private commit emails)'), class: 'label-bold' + = f.text_field :commit_email_hostname, class: 'form-control' + .form-text.text-muted + - commit_email_hostname_docs_link = link_to _('Learn more'), help_page_path('user/admin_area/settings/email', anchor: 'custom-private-commit-email-hostname'), target: '_blank' + = _("This setting will update the hostname that is used to generate private commit emails. %{learn_more}").html_safe % { learn_more: commit_email_hostname_docs_link } = f.submit 'Save changes', class: "btn btn-success" diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index ea215e3e718..2603c558c0f 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -91,8 +91,9 @@ = f.select :public_email, options_for_select(@user.all_emails, selected: @user.public_email), { help: s_("Profiles|This email will be displayed on your public profile."), include_blank: s_("Profiles|Do not show on profile") }, control_class: 'select2' - = f.select :commit_email, options_for_select(@user.verified_emails, selected: @user.commit_email), - { help: 'This email will be used for web based operations, such as edits and merges.' }, + - commit_email_docs_link = link_to s_('Profiles|Learn more'), help_page_path('user/profile/index', anchor: 'commit-email', target: '_blank') + = f.select :commit_email, options_for_select(commit_email_select_options(@user), selected: selected_commit_email(@user)), + { help: s_("Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}").html_safe % { learn_more: commit_email_docs_link } }, control_class: 'select2' = f.select :preferred_language, Gitlab::I18n::AVAILABLE_LANGUAGES.map { |value, label| [label, value] }, { help: s_("Profiles|This feature is experimental and translations are not complete yet.") }, diff --git a/changelogs/unreleased/43521-keep-personal-emails-private.yml b/changelogs/unreleased/43521-keep-personal-emails-private.yml new file mode 100644 index 00000000000..0f0bede6482 --- /dev/null +++ b/changelogs/unreleased/43521-keep-personal-emails-private.yml @@ -0,0 +1,5 @@ +--- +title: Adds option to override commit email with a noreply private email +merge_request: 22560 +author: +type: added diff --git a/db/migrate/20181025115728_add_private_commit_email_hostname_to_application_settings.rb b/db/migrate/20181025115728_add_private_commit_email_hostname_to_application_settings.rb new file mode 100644 index 00000000000..89ddaf2ae2b --- /dev/null +++ b/db/migrate/20181025115728_add_private_commit_email_hostname_to_application_settings.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class AddPrivateCommitEmailHostnameToApplicationSettings < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def change + add_column(:application_settings, :commit_email_hostname, :string, null: true) + end +end diff --git a/db/schema.rb b/db/schema.rb index cfbfd7ad375..4695d923b79 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -166,6 +166,7 @@ ActiveRecord::Schema.define(version: 20181107054254) do t.integer "receive_max_input_size" t.integer "diff_max_patch_bytes", default: 102400, null: false t.integer "archive_builds_in_seconds" + t.string "commit_email_hostname" end create_table "audit_events", force: :cascade do |t| diff --git a/doc/development/utilities.md b/doc/development/utilities.md index 0d074a3ef05..e5466ae8914 100644 --- a/doc/development/utilities.md +++ b/doc/development/utilities.md @@ -171,8 +171,8 @@ class Commit extend Gitlab::Cache::RequestCache def author - User.find_by_any_email(author_email.downcase) + User.find_by_any_email(author_email) end - request_cache(:author) { author_email.downcase } + request_cache(:author) { author_email } end ``` diff --git a/doc/user/admin_area/settings/email.md b/doc/user/admin_area/settings/email.md index 7c9e5bf882e..50c318a4969 100644 --- a/doc/user/admin_area/settings/email.md +++ b/doc/user/admin_area/settings/email.md @@ -3,3 +3,20 @@ ## Custom logo The logo in the header of some emails can be customized, see the [logo customization section](../../../customization/branded_page_and_email_header.md). + +## Custom hostname for private commit emails + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22560) in GitLab 11.5. + +This configuration option sets the email hostname for [private commit emails](../../profile/index.md#private-commit-email), +and it's, by default, set to `users.noreply.YOUR_CONFIGURED_HOSTNAME`. + +In order to change this option: + +1. Go to **Admin area > Settings** (`/admin/application_settings`). +1. Under the **Email** section, change the **Custom hostname (for private commit emails)** field. +1. Hit **Save** for the changes to take effect. + +NOTE: **Note**: Once the hostname gets configured, every private commit email using the previous hostname, will not get +recognized by GitLab. This can directly conflict with certain [Push rules](https://docs.gitlab.com/ee/push_rules/push_rules.html) such as +`Check whether author is a GitLab user` and `Check whether committer is the current authenticated user`. diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md index ab62762f343..da7c30b6b39 100644 --- a/doc/user/profile/index.md +++ b/doc/user/profile/index.md @@ -31,6 +31,7 @@ From there, you can: - Update your personal information - Set a [custom status](#current-status) for your profile +- Manage your [commit email](#commit-email) for your profile - Manage [2FA](account/two_factor_authentication.md) - Change your username and [delete your account](account/delete_account.md) - Manage applications that can @@ -132,6 +133,45 @@ They may however contain emoji codes such as `I'm on vacation :palm_tree:`. You can also set your current status [using the API](../../api/users.md#user-status). +## Commit email + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21598) in GitLab 11.4. + +A commit email, is the email that will be displayed in every Git-related action done through the +GitLab interface. + +You are able to select from the list of your own verified emails which email you want to use as the commit email. + +To change it: + +1. Open the user menu in the top-right corner of the navigation bar. +1. Hit **Commit email** selection box. +1. Select any of the verified emails. +1. Hit **Update profile settings**. + +### Private commit email + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22560) in GitLab 11.5. + +GitLab provides the user with an automatically generated private commit email option, +which allows the user to not make their email information public. + +To enable this option: + +1. Open the user menu in the top-right corner of the navigation bar. +1. Hit **Commit email** selection box. +1. Select **Use a private email** option. +1. Hit **Update profile settings**. + +Once this option is enabled, every Git-related action will be performed using the private commit email. + +In order to stay fully annonymous, you can also copy this private commit email +and configure it on your local machine using the following command: + +``` +git config --global user.email "YOUR_PRIVATE_COMMIT_EMAIL" +``` + ## Troubleshooting ### Why do I keep getting signed out? diff --git a/lib/gitlab/private_commit_email.rb b/lib/gitlab/private_commit_email.rb new file mode 100644 index 00000000000..bade2248ccd --- /dev/null +++ b/lib/gitlab/private_commit_email.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Gitlab + module PrivateCommitEmail + TOKEN = "_private".freeze + + class << self + def regex + hostname_regexp = Regexp.escape(Gitlab::CurrentSettings.current_application_settings.commit_email_hostname) + + /\A(?<id>([0-9]+))\-([^@]+)@#{hostname_regexp}\z/ + end + + def user_id_for_email(email) + match = email&.match(regex) + return unless match + + match[:id].to_i + end + + def for_user(user) + hostname = Gitlab::CurrentSettings.current_application_settings.commit_email_hostname + + "#{user.id}-#{user.username}@#{hostname}" + end + end + end +end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 45fc072900a..7d15d6a11fd 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2094,6 +2094,9 @@ msgstr "" msgid "Custom CI config path" msgstr "" +msgid "Custom hostname (for private commit emails)" +msgstr "" + msgid "Custom notification events" msgstr "" @@ -4701,6 +4704,9 @@ msgstr "" msgid "Profiles|Invalid username" msgstr "" +msgid "Profiles|Learn more" +msgstr "" + msgid "Profiles|Made a private contribution" msgstr "" @@ -4743,6 +4749,9 @@ msgstr "" msgid "Profiles|This email will be displayed on your public profile." msgstr "" +msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}" +msgstr "" + msgid "Profiles|This emoji and message will appear on your profile and throughout the interface." msgstr "" @@ -4767,6 +4776,9 @@ msgstr "" msgid "Profiles|Upload new avatar" msgstr "" +msgid "Profiles|Use a private email - %{email}" +msgstr "" + msgid "Profiles|Username change failed - %{message}" msgstr "" @@ -6296,6 +6308,9 @@ msgstr "" msgid "This setting can be overridden in each project." msgstr "" +msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}" +msgstr "" + msgid "This source diff could not be displayed because it is too large." msgstr "" diff --git a/spec/helpers/profiles_helper_spec.rb b/spec/helpers/profiles_helper_spec.rb index c1d0614c79e..9a2372de69f 100644 --- a/spec/helpers/profiles_helper_spec.rb +++ b/spec/helpers/profiles_helper_spec.rb @@ -1,6 +1,35 @@ require 'rails_helper' describe ProfilesHelper do + describe '#commit_email_select_options' do + it 'returns an array with private commit email along with all the verified emails' do + user = create(:user) + private_email = user.private_commit_email + + verified_emails = user.verified_emails - [private_email] + emails = [ + ["Use a private email - #{private_email}", Gitlab::PrivateCommitEmail::TOKEN], + verified_emails + ] + + expect(helper.commit_email_select_options(user)).to match_array(emails) + end + end + + describe '#selected_commit_email' do + let(:user) { create(:user) } + + it 'returns main email when commit email attribute is nil' do + expect(helper.selected_commit_email(user)).to eq(user.email) + end + + it 'returns DB stored commit_email' do + user.update(commit_email: Gitlab::PrivateCommitEmail::TOKEN) + + expect(helper.selected_commit_email(user)).to eq(Gitlab::PrivateCommitEmail::TOKEN) + end + end + describe '#email_provider_label' do it "returns nil for users without external email" do user = create(:user) diff --git a/spec/lib/gitlab/private_commit_email_spec.rb b/spec/lib/gitlab/private_commit_email_spec.rb new file mode 100644 index 00000000000..bc86cd3842a --- /dev/null +++ b/spec/lib/gitlab/private_commit_email_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::PrivateCommitEmail do + let(:hostname) { Gitlab::CurrentSettings.current_application_settings.commit_email_hostname } + + context '.regex' do + subject { described_class.regex } + + it { is_expected.to match("1-foo@#{hostname}") } + it { is_expected.not_to match("1-foo@#{hostname}.foo") } + it { is_expected.not_to match('1-foo@users.noreply.gitlab.com') } + it { is_expected.not_to match('foo-1@users.noreply.gitlab.com') } + it { is_expected.not_to match('foobar@gitlab.com') } + end + + context '.user_id_for_email' do + let(:id) { 1 } + + it 'parses user id from email' do + email = "#{id}-foo@#{hostname}" + + expect(described_class.user_id_for_email(email)).to eq(id) + end + + it 'returns nil on invalid commit email' do + email = "#{id}-foo@users.noreply.bar.com" + + expect(described_class.user_id_for_email(email)).to be_nil + end + end + + context '.for_user' do + it 'returns email in the format id-username@hostname' do + user = create(:user) + + expect(described_class.for_user(user)).to eq("#{user.id}-#{user.username}@#{hostname}") + end + end +end diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 95ae7bd21ab..96aa9a82b71 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -25,6 +25,9 @@ describe ApplicationSetting do it { is_expected.to allow_value(https).for(:after_sign_out_path) } it { is_expected.not_to allow_value(ftp).for(:after_sign_out_path) } + it { is_expected.to allow_value("dev.gitlab.com").for(:commit_email_hostname) } + it { is_expected.not_to allow_value("@dev.gitlab").for(:commit_email_hostname) } + describe 'default_artifacts_expire_in' do it 'sets an error if it cannot parse' do setting.update(default_artifacts_expire_in: 'a') @@ -107,6 +110,14 @@ describe ApplicationSetting do it { expect(setting.repository_storages).to eq(['default']) } end + context '#commit_email_hostname' do + it 'returns configured gitlab hostname if commit_email_hostname is not defined' do + setting.update(commit_email_hostname: nil) + + expect(setting.commit_email_hostname).to eq("users.noreply.#{Gitlab.config.gitlab.host}") + end + end + context 'auto_devops_domain setting' do context 'when auto_devops_enabled? is true' do before do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 4e7c8523e65..0ac5bd666ae 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -183,6 +183,12 @@ describe User do expect(found_user.commit_email).to eq(user.email) end + it 'returns the private commit email when commit_email has _private' do + user.update_column(:commit_email, Gitlab::PrivateCommitEmail::TOKEN) + + expect(user.commit_email).to eq(user.private_commit_email) + end + it 'can be set to a confirmed email' do confirmed = create(:email, :confirmed, user: user) user.commit_email = confirmed.email @@ -333,6 +339,40 @@ describe User do expect(user).to be_valid end end + + context 'set_commit_email' do + it 'keeps commit email when private commit email is being used' do + user = create(:user, commit_email: Gitlab::PrivateCommitEmail::TOKEN) + + expect(user.read_attribute(:commit_email)).to eq(Gitlab::PrivateCommitEmail::TOKEN) + end + + it 'keeps the commit email when nil' do + user = create(:user, commit_email: nil) + + expect(user.read_attribute(:commit_email)).to be_nil + end + + it 'reverts to nil when email is not verified' do + user = create(:user, commit_email: "foo@bar.com") + + expect(user.read_attribute(:commit_email)).to be_nil + end + end + + context 'owns_commit_email' do + it 'accepts private commit email' do + user = build(:user, commit_email: Gitlab::PrivateCommitEmail::TOKEN) + + expect(user).to be_valid + end + + it 'accepts nil commit email' do + user = build(:user, commit_email: nil) + + expect(user).to be_valid + end + end end end @@ -1075,6 +1115,14 @@ describe User do end describe '.find_by_any_email' do + it 'finds user through private commit email' do + user = create(:user) + private_email = user.private_commit_email + + expect(described_class.find_by_any_email(private_email)).to eq(user) + expect(described_class.find_by_any_email(private_email, confirmed: true)).to eq(user) + end + it 'finds by primary email' do user = create(:user, email: 'foo@example.com') @@ -1082,6 +1130,13 @@ describe User do expect(described_class.find_by_any_email(user.email, confirmed: true)).to eq user end + it 'finds by uppercased email' do + user = create(:user, email: 'foo@example.com') + + expect(described_class.find_by_any_email(user.email.upcase)).to eq user + expect(described_class.find_by_any_email(user.email.upcase, confirmed: true)).to eq user + end + it 'finds by secondary email' do email = create(:email, email: 'foo@example.com') user = email.user @@ -1457,7 +1512,7 @@ describe User do email_confirmed = create :email, user: user, confirmed_at: Time.now create :email, user: user - expect(user.verified_emails).to match_array([user.email, email_confirmed.email]) + expect(user.verified_emails).to match_array([user.email, user.private_commit_email, email_confirmed.email]) end end @@ -1473,6 +1528,10 @@ describe User do expect(user.verified_email?(email_confirmed.email.titlecase)).to be_truthy end + it 'returns true when user is found through private commit email' do + expect(user.verified_email?(user.private_commit_email)).to be_truthy + end + it 'returns false when the email is not verified/confirmed' do email_unconfirmed = create :email, user: user user.reload @@ -1668,6 +1727,24 @@ describe User do end end + describe '.find_by_private_commit_email' do + context 'with email' do + set(:user) { create(:user) } + + it 'returns user through private commit email' do + expect(described_class.find_by_private_commit_email(user.private_commit_email)).to eq(user) + end + + it 'returns nil when email other than private_commit_email is used' do + expect(described_class.find_by_private_commit_email(user.email)).to be_nil + end + end + + it 'returns nil when email is nil' do + expect(described_class.find_by_private_commit_email(nil)).to be_nil + end + end + describe '#sort_by_attribute' do before do described_class.delete_all |