Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
b7206bfa
Commit
b7206bfa
authored
Sep 07, 2018
by
Nick Thomas
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Port of 23986-choose-commit-email to EE
parent
745eebda
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
156 additions
and
7 deletions
+156
-7
app/controllers/profiles_controller.rb
app/controllers/profiles_controller.rb
+1
-0
app/models/user.rb
app/models/user.rb
+38
-1
app/views/profiles/emails/index.html.haml
app/views/profiles/emails/index.html.haml
+7
-1
app/views/profiles/show.html.haml
app/views/profiles/show.html.haml
+3
-0
changelogs/unreleased/23986-choose-commit-email.yml
changelogs/unreleased/23986-choose-commit-email.yml
+5
-0
db/migrate/20180814153625_add_commit_email_to_users.rb
db/migrate/20180814153625_add_commit_email_to_users.rb
+33
-0
db/schema.rb
db/schema.rb
+1
-0
doc/user/profile/index.md
doc/user/profile/index.md
+1
-0
doc/user/project/repository/web_editor.md
doc/user/project/repository/web_editor.md
+4
-0
lib/gitlab/git/user.rb
lib/gitlab/git/user.rb
+1
-1
spec/factories/emails.rb
spec/factories/emails.rb
+1
-0
spec/lib/gitlab/git/user_spec.rb
spec/lib/gitlab/git/user_spec.rb
+12
-3
spec/models/user_spec.rb
spec/models/user_spec.rb
+49
-1
No files found.
app/controllers/profiles_controller.rb
View file @
b7206bfa
...
@@ -96,6 +96,7 @@ class ProfilesController < Profiles::ApplicationController
...
@@ -96,6 +96,7 @@ class ProfilesController < Profiles::ApplicationController
:location
,
:location
,
:name
,
:name
,
:public_email
,
:public_email
,
:commit_email
,
:skype
,
:skype
,
:twitter
,
:twitter
,
:username
,
:username
,
...
...
app/models/user.rb
View file @
b7206bfa
...
@@ -163,6 +163,7 @@ class User < ActiveRecord::Base
...
@@ -163,6 +163,7 @@ class User < ActiveRecord::Base
validates
:notification_email
,
presence:
true
validates
:notification_email
,
presence:
true
validates
:notification_email
,
email:
true
,
if:
->
(
user
)
{
user
.
notification_email
!=
user
.
email
}
validates
:notification_email
,
email:
true
,
if:
->
(
user
)
{
user
.
notification_email
!=
user
.
email
}
validates
:public_email
,
presence:
true
,
uniqueness:
true
,
email:
true
,
allow_blank:
true
validates
:public_email
,
presence:
true
,
uniqueness:
true
,
email:
true
,
allow_blank:
true
validates
:commit_email
,
email:
true
,
allow_nil:
true
,
if:
->
(
user
)
{
user
.
commit_email
!=
user
.
email
}
validates
:bio
,
length:
{
maximum:
255
},
allow_blank:
true
validates
:bio
,
length:
{
maximum:
255
},
allow_blank:
true
validates
:projects_limit
,
validates
:projects_limit
,
presence:
true
,
presence:
true
,
...
@@ -175,12 +176,15 @@ class User < ActiveRecord::Base
...
@@ -175,12 +176,15 @@ class User < ActiveRecord::Base
validate
:unique_email
,
if: :email_changed?
validate
:unique_email
,
if: :email_changed?
validate
:owns_notification_email
,
if: :notification_email_changed?
validate
:owns_notification_email
,
if: :notification_email_changed?
validate
:owns_public_email
,
if: :public_email_changed?
validate
:owns_public_email
,
if: :public_email_changed?
validate
:owns_commit_email
,
if: :commit_email_changed?
validate
:signup_domain_valid?
,
on: :create
,
if:
->
(
user
)
{
!
user
.
created_by_id
}
validate
:signup_domain_valid?
,
on: :create
,
if:
->
(
user
)
{
!
user
.
created_by_id
}
before_validation
:sanitize_attrs
before_validation
:sanitize_attrs
before_validation
:set_notification_email
,
if: :new_record?
before_validation
:set_notification_email
,
if: :new_record?
before_validation
:set_public_email
,
if: :public_email_changed?
before_validation
:set_public_email
,
if: :public_email_changed?
before_validation
:set_commit_email
,
if: :commit_email_changed?
before_save
:set_public_email
,
if: :public_email_changed?
# in case validation is skipped
before_save
:set_public_email
,
if: :public_email_changed?
# in case validation is skipped
before_save
:set_commit_email
,
if: :commit_email_changed?
# in case validation is skipped
before_save
:ensure_incoming_email_token
before_save
:ensure_incoming_email_token
before_save
:ensure_user_rights_and_limits
,
if:
->
(
user
)
{
user
.
new_record?
||
user
.
external_changed?
}
before_save
:ensure_user_rights_and_limits
,
if:
->
(
user
)
{
user
.
new_record?
||
user
.
external_changed?
}
before_save
:skip_reconfirmation!
,
if:
->
(
user
)
{
user
.
email_changed?
&&
user
.
read_only_attribute?
(
:email
)
}
before_save
:skip_reconfirmation!
,
if:
->
(
user
)
{
user
.
email_changed?
&&
user
.
read_only_attribute?
(
:email
)
}
...
@@ -637,6 +641,32 @@ class User < ActiveRecord::Base
...
@@ -637,6 +641,32 @@ class User < ActiveRecord::Base
errors
.
add
(
:public_email
,
"is not an email you own"
)
unless
all_emails
.
include?
(
public_email
)
errors
.
add
(
:public_email
,
"is not an email you own"
)
unless
all_emails
.
include?
(
public_email
)
end
end
def
owns_commit_email
return
if
read_attribute
(
:commit_email
).
blank?
errors
.
add
(
:commit_email
,
"is not an email you own"
)
unless
verified_emails
.
include?
(
commit_email
)
end
# Define commit_email-related attribute methods explicitly instead of relying
# on ActiveRecord to provide them. Some of the specs use the current state of
# the model code but an older database schema, so we need to guard against the
# possibility of the commit_email column not existing.
def
commit_email
return
unless
has_attribute?
(
:commit_email
)
# The commit email is the same as the primary email if undefined
super
.
presence
||
self
.
email
end
def
commit_email
=
(
email
)
super
if
has_attribute?
(
:commit_email
)
end
def
commit_email_changed?
has_attribute?
(
:commit_email
)
&&
super
end
# see if the new email is already a verified secondary email
# see if the new email is already a verified secondary email
def
check_for_verified_email
def
check_for_verified_email
skip_reconfirmation!
if
emails
.
confirmed
.
where
(
email:
self
.
email
).
any?
skip_reconfirmation!
if
emails
.
confirmed
.
where
(
email:
self
.
email
).
any?
...
@@ -891,10 +921,17 @@ class User < ActiveRecord::Base
...
@@ -891,10 +921,17 @@ class User < ActiveRecord::Base
end
end
end
end
def
set_commit_email
if
commit_email
.
blank?
||
verified_emails
.
exclude?
(
commit_email
)
self
.
commit_email
=
nil
end
end
def
update_secondary_emails!
def
update_secondary_emails!
set_notification_email
set_notification_email
set_public_email
set_public_email
save
if
notification_email_changed?
||
public_email_changed?
set_commit_email
save
if
notification_email_changed?
||
public_email_changed?
||
commit_email_changed?
end
end
def
set_projects_limit
def
set_projects_limit
...
...
app/views/profiles/emails/index.html.haml
View file @
b7206bfa
...
@@ -22,7 +22,9 @@
...
@@ -22,7 +22,9 @@
.account-well.append-bottom-default
.account-well.append-bottom-default
%ul
%ul
%li
%li
Your Primary Email will be used for avatar detection and web based operations, such as edits and merges.
Your Primary Email will be used for avatar detection.
%li
Your Commit Email will be used for web based operations, such as edits and merges.
%li
%li
Your Notification Email will be used for account notifications.
Your Notification Email will be used for account notifications.
%li
%li
...
@@ -34,6 +36,8 @@
...
@@ -34,6 +36,8 @@
=
render
partial:
'shared/email_with_badge'
,
locals:
{
email:
@primary_email
,
verified:
current_user
.
confirmed?
}
=
render
partial:
'shared/email_with_badge'
,
locals:
{
email:
@primary_email
,
verified:
current_user
.
confirmed?
}
%span
.float-right
%span
.float-right
%span
.badge.badge-success
Primary email
%span
.badge.badge-success
Primary email
-
if
@primary_email
===
current_user
.
commit_email
%span
.badge.badge-info
Commit email
-
if
@primary_email
===
current_user
.
public_email
-
if
@primary_email
===
current_user
.
public_email
%span
.badge.badge-info
Public email
%span
.badge.badge-info
Public email
-
if
@primary_email
===
current_user
.
notification_email
-
if
@primary_email
===
current_user
.
notification_email
...
@@ -42,6 +46,8 @@
...
@@ -42,6 +46,8 @@
%li
%li
=
render
partial:
'shared/email_with_badge'
,
locals:
{
email:
email
.
email
,
verified:
email
.
confirmed?
}
=
render
partial:
'shared/email_with_badge'
,
locals:
{
email:
email
.
email
,
verified:
email
.
confirmed?
}
%span
.float-right
%span
.float-right
-
if
email
.
email
===
current_user
.
commit_email
%span
.badge.badge-info
Commit email
-
if
email
.
email
===
current_user
.
public_email
-
if
email
.
email
===
current_user
.
public_email
%span
.badge.badge-info
Public email
%span
.badge.badge-info
Public email
-
if
email
.
email
===
current_user
.
notification_email
-
if
email
.
email
===
current_user
.
notification_email
...
...
app/views/profiles/show.html.haml
View file @
b7206bfa
...
@@ -91,6 +91,9 @@
...
@@ -91,6 +91,9 @@
=
f
.
select
:public_email
,
options_for_select
(
@user
.
all_emails
,
selected:
@user
.
public_email
),
=
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"
)
},
{
help:
s_
(
"Profiles|This email will be displayed on your public profile."
),
include_blank:
s_
(
"Profiles|Do not show on profile"
)
},
control_class:
'select2'
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.'
},
control_class:
'select2'
=
f
.
select
:preferred_language
,
Gitlab
::
I18n
::
AVAILABLE_LANGUAGES
.
map
{
|
value
,
label
|
[
label
,
value
]
},
=
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."
)
},
{
help:
s_
(
"Profiles|This feature is experimental and translations are not complete yet."
)
},
control_class:
'select2'
control_class:
'select2'
...
...
changelogs/unreleased/23986-choose-commit-email.yml
0 → 100644
View file @
b7206bfa
---
title
:
Allow user to choose the email used for commits made through GitLab's UI.
merge_request
:
21213
author
:
Joshua Campbell
type
:
added
db/migrate/20180814153625_add_commit_email_to_users.rb
0 → 100644
View file @
b7206bfa
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class
AddCommitEmailToUsers
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME
=
false
# When a migration requires downtime you **must** uncomment the following
# constant and define a short and easy to understand explanation as to why the
# migration requires downtime.
# DOWNTIME_REASON = ''
# When using the methods "add_concurrent_index", "remove_concurrent_index" or
# "add_column_with_default" you must disable the use of transactions
# as these methods can not run in an existing transaction.
# When using "add_concurrent_index" or "remove_concurrent_index" methods make sure
# that either of them is the _only_ method called in the migration,
# any other changes should go in a separate migration.
# This ensures that upon failure _only_ the index creation or removing fails
# and can be retried or reverted easily.
#
# To disable transactions uncomment the following line and remove these
# comments:
# disable_ddl_transaction!
def
change
add_column
:users
,
:commit_email
,
:string
end
end
db/schema.rb
View file @
b7206bfa
...
@@ -2893,6 +2893,7 @@ ActiveRecord::Schema.define(version: 20180906101639) do
...
@@ -2893,6 +2893,7 @@ ActiveRecord::Schema.define(version: 20180906101639) do
t
.
boolean
"private_profile"
t
.
boolean
"private_profile"
t
.
integer
"roadmap_layout"
,
limit:
2
t
.
integer
"roadmap_layout"
,
limit:
2
t
.
boolean
"include_private_contributions"
t
.
boolean
"include_private_contributions"
t
.
string
"commit_email"
end
end
add_index
"users"
,
[
"admin"
],
name:
"index_users_on_admin"
,
using: :btree
add_index
"users"
,
[
"admin"
],
name:
"index_users_on_admin"
,
using: :btree
...
...
doc/user/profile/index.md
View file @
b7206bfa
...
@@ -37,6 +37,7 @@ From there, you can:
...
@@ -37,6 +37,7 @@ From there, you can:
[
use GitLab as an OAuth provider
](
../../integration/oauth_provider.md#introduction-to-oauth
)
[
use GitLab as an OAuth provider
](
../../integration/oauth_provider.md#introduction-to-oauth
)
-
Manage
[
personal access tokens
](
personal_access_tokens.md
)
to access your account via API and authorized applications
-
Manage
[
personal access tokens
](
personal_access_tokens.md
)
to access your account via API and authorized applications
-
Add and delete emails linked to your account
-
Add and delete emails linked to your account
-
Choose which email to use for notifications, web-based commits, and display on your public profile
-
Manage
[
SSH keys
](
../../ssh/README.md#ssh
)
to access your account via SSH
-
Manage
[
SSH keys
](
../../ssh/README.md#ssh
)
to access your account via SSH
-
Manage your
[
preferences
](
preferences.md#syntax-highlighting-theme
)
-
Manage your
[
preferences
](
preferences.md#syntax-highlighting-theme
)
to customize your own GitLab experience
to customize your own GitLab experience
...
...
doc/user/project/repository/web_editor.md
View file @
b7206bfa
...
@@ -177,5 +177,9 @@ you commit the changes you will be taken to a new merge request form.
...
@@ -177,5 +177,9 @@ you commit the changes you will be taken to a new merge request form.
![
Start a new merge request with these changes
](
img/web_editor_start_new_merge_request.png
)
![
Start a new merge request with these changes
](
img/web_editor_start_new_merge_request.png
)
If you'd prefer _not_ to use your primary email address for commits created
through the web editor, you can choose to use another of your linked email
addresses from the
**User Settings > Edit Profile**
page.
[
ce-2808
]:
https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2808
[
ce-2808
]:
https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2808
[
issue closing pattern
]:
../issues/automatic_issue_closing.md
[
issue closing pattern
]:
../issues/automatic_issue_closing.md
lib/gitlab/git/user.rb
View file @
b7206bfa
...
@@ -4,7 +4,7 @@ module Gitlab
...
@@ -4,7 +4,7 @@ module Gitlab
attr_reader
:username
,
:name
,
:email
,
:gl_id
attr_reader
:username
,
:name
,
:email
,
:gl_id
def
self
.
from_gitlab
(
gitlab_user
)
def
self
.
from_gitlab
(
gitlab_user
)
new
(
gitlab_user
.
username
,
gitlab_user
.
name
,
gitlab_user
.
email
,
Gitlab
::
GlId
.
gl_id
(
gitlab_user
))
new
(
gitlab_user
.
username
,
gitlab_user
.
name
,
gitlab_user
.
commit_
email
,
Gitlab
::
GlId
.
gl_id
(
gitlab_user
))
end
end
def
self
.
from_gitaly
(
gitaly_user
)
def
self
.
from_gitaly
(
gitaly_user
)
...
...
spec/factories/emails.rb
View file @
b7206bfa
...
@@ -4,5 +4,6 @@ FactoryBot.define do
...
@@ -4,5 +4,6 @@ FactoryBot.define do
email
{
generate
(
:email_alias
)
}
email
{
generate
(
:email_alias
)
}
trait
(
:confirmed
)
{
confirmed_at
Time
.
now
}
trait
(
:confirmed
)
{
confirmed_at
Time
.
now
}
trait
(
:skip_validate
)
{
to_create
{
|
instance
|
instance
.
save
(
validate:
false
)
}
}
end
end
end
end
spec/lib/gitlab/git/user_spec.rb
View file @
b7206bfa
...
@@ -22,12 +22,21 @@ describe Gitlab::Git::User do
...
@@ -22,12 +22,21 @@ describe Gitlab::Git::User do
end
end
describe
'.from_gitlab'
do
describe
'.from_gitlab'
do
let
(
:user
)
{
build
(
:user
)
}
context
'when no commit_email has been set'
do
let
(
:user
)
{
build
(
:user
,
email:
'alice@example.com'
,
commit_email:
nil
)
}
subject
{
described_class
.
from_gitlab
(
user
)
}
subject
{
described_class
.
from_gitlab
(
user
)
}
it
{
expect
(
subject
).
to
eq
(
described_class
.
new
(
user
.
username
,
user
.
name
,
user
.
email
,
'user-'
))
}
it
{
expect
(
subject
).
to
eq
(
described_class
.
new
(
user
.
username
,
user
.
name
,
user
.
email
,
'user-'
))
}
end
end
context
'when commit_email has been set'
do
let
(
:user
)
{
build
(
:user
,
email:
'alice@example.com'
,
commit_email:
'bob@example.com'
)
}
subject
{
described_class
.
from_gitlab
(
user
)
}
it
{
expect
(
subject
).
to
eq
(
described_class
.
new
(
user
.
username
,
user
.
name
,
user
.
commit_email
,
'user-'
))
}
end
end
describe
'#=='
do
describe
'#=='
do
def
eq_other
(
username
,
name
,
email
,
gl_id
)
def
eq_other
(
username
,
name
,
email
,
gl_id
)
eq
(
described_class
.
new
(
username
,
name
,
email
,
gl_id
))
eq
(
described_class
.
new
(
username
,
name
,
email
,
gl_id
))
...
...
spec/models/user_spec.rb
View file @
b7206bfa
...
@@ -176,6 +176,55 @@ describe User do
...
@@ -176,6 +176,55 @@ describe User do
subject
{
build
(
:user
).
tap
{
|
user
|
user
.
emails
<<
build
(
:email
,
email:
email_value
)
}
}
subject
{
build
(
:user
).
tap
{
|
user
|
user
.
emails
<<
build
(
:email
,
email:
email_value
)
}
}
end
end
describe
'#commit_email'
do
subject
(
:user
)
{
create
(
:user
)
}
it
'defaults to the primary email'
do
expect
(
user
.
email
).
to
be_present
expect
(
user
.
commit_email
).
to
eq
(
user
.
email
)
end
it
'defaults to the primary email when the column in the database is null'
do
user
.
update_column
(
:commit_email
,
nil
)
found_user
=
described_class
.
find_by
(
id:
user
.
id
)
expect
(
found_user
.
commit_email
).
to
eq
(
user
.
email
)
end
it
'can be set to a confirmed email'
do
confirmed
=
create
(
:email
,
:confirmed
,
user:
user
)
user
.
commit_email
=
confirmed
.
email
expect
(
user
).
to
be_valid
expect
(
user
.
commit_email
).
to
eq
(
confirmed
.
email
)
end
it
'can not be set to an unconfirmed email'
do
unconfirmed
=
create
(
:email
,
user:
user
)
user
.
commit_email
=
unconfirmed
.
email
# This should set the commit_email attribute to the primary email
expect
(
user
).
to
be_valid
expect
(
user
.
commit_email
).
to
eq
(
user
.
email
)
end
it
'can not be set to a non-existent email'
do
user
.
commit_email
=
'non-existent-email@nonexistent.nonexistent'
# This should set the commit_email attribute to the primary email
expect
(
user
).
to
be_valid
expect
(
user
.
commit_email
).
to
eq
(
user
.
email
)
end
it
'can not be set to an invalid email, even if confirmed'
do
confirmed
=
create
(
:email
,
:confirmed
,
:skip_validate
,
user:
user
,
email:
'invalid'
)
user
.
commit_email
=
confirmed
.
email
expect
(
user
).
not_to
be_valid
end
end
describe
'email'
do
describe
'email'
do
context
'when no signup domains whitelisted'
do
context
'when no signup domains whitelisted'
do
before
do
before
do
...
@@ -1418,7 +1467,6 @@ describe User do
...
@@ -1418,7 +1467,6 @@ describe User do
it
'returns only confirmed emails'
do
it
'returns only confirmed emails'
do
email_confirmed
=
create
:email
,
user:
user
,
confirmed_at:
Time
.
now
email_confirmed
=
create
:email
,
user:
user
,
confirmed_at:
Time
.
now
create
:email
,
user:
user
create
:email
,
user:
user
user
.
reload
expect
(
user
.
verified_emails
).
to
match_array
([
user
.
email
,
email_confirmed
.
email
])
expect
(
user
.
verified_emails
).
to
match_array
([
user
.
email
,
email_confirmed
.
email
])
end
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment