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
0
Merge Requests
0
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
Jérome Perrin
gitlab-ce
Commits
3f73b6be
Commit
3f73b6be
authored
Apr 19, 2018
by
Rémy Coutable
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Don't set the notification_email when only unconfirmed_email is changed
Signed-off-by:
Rémy Coutable
<
remy@rymai.me
>
parent
4d674bd3
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
107 additions
and
41 deletions
+107
-41
app/models/user.rb
app/models/user.rb
+19
-8
changelogs/unreleased/22846-notifications-broken-during-email-address-change-before-email-confirmed.yml
...en-during-email-address-change-before-email-confirmed.yml
+6
-0
spec/models/user_spec.rb
spec/models/user_spec.rb
+70
-18
spec/requests/api/users_spec.rb
spec/requests/api/users_spec.rb
+12
-15
No files found.
app/models/user.rb
View file @
3f73b6be
...
...
@@ -165,8 +165,7 @@ class User < ActiveRecord::Base
validate
:signup_domain_valid?
,
on: :create
,
if:
->
(
user
)
{
!
user
.
created_by_id
}
before_validation
:sanitize_attrs
before_validation
:set_notification_email
,
if: :email_changed?
before_save
:set_notification_email
,
if: :email_changed?
# in case validation is skipped
before_validation
:set_notification_email
,
if: :new_record?
before_validation
:set_public_email
,
if: :public_email_changed?
before_save
:set_public_email
,
if: :public_email_changed?
# in case validation is skipped
before_save
:ensure_incoming_email_token
...
...
@@ -179,8 +178,21 @@ class User < ActiveRecord::Base
after_update
:username_changed_hook
,
if: :username_changed?
after_destroy
:post_destroy_hook
after_destroy
:remove_key_cache
after_commit
:update_emails_with_primary_email
,
on: :update
,
if:
->
{
previous_changes
.
key?
(
'email'
)
}
after_commit
:update_invalid_gpg_signatures
,
on: :update
,
if:
->
{
previous_changes
.
key?
(
'email'
)
}
after_commit
(
on: :update
)
do
if
previous_changes
.
key?
(
'email'
)
# Grab previous_email here since previous_changes changes after
# #update_emails_with_primary_email and #update_notification_email are called
previous_email
=
previous_changes
[
:email
][
0
]
update_emails_with_primary_email
(
previous_email
)
update_invalid_gpg_signatures
if
previous_email
==
notification_email
self
.
notification_email
=
email
save
end
end
end
after_initialize
:set_projects_limit
...
...
@@ -546,8 +558,7 @@ class User < ActiveRecord::Base
# hash and `_was` variables getting munged.
# By using an `after_commit` instead of `after_update`, we avoid the recursive callback
# scenario, though it then requires us to use the `previous_changes` hash
def
update_emails_with_primary_email
previous_email
=
previous_changes
[
:email
][
0
]
# grab this before the DestroyService is called
def
update_emails_with_primary_email
(
previous_email
)
primary_email_record
=
emails
.
find_by
(
email:
email
)
Emails
::
DestroyService
.
new
(
self
,
user:
self
).
execute
(
primary_email_record
)
if
primary_email_record
...
...
@@ -772,13 +783,13 @@ class User < ActiveRecord::Base
end
def
set_notification_email
if
notification_email
.
blank?
||
!
all_emails
.
in
clude?
(
notification_email
)
if
notification_email
.
blank?
||
all_emails
.
ex
clude?
(
notification_email
)
self
.
notification_email
=
email
end
end
def
set_public_email
if
public_email
.
blank?
||
!
all_emails
.
in
clude?
(
public_email
)
if
public_email
.
blank?
||
all_emails
.
ex
clude?
(
public_email
)
self
.
public_email
=
''
end
end
...
...
changelogs/unreleased/22846-notifications-broken-during-email-address-change-before-email-confirmed.yml
0 → 100644
View file @
3f73b6be
---
title
:
Fix an issue where the notification email address would be set to an unconfirmed
email address
merge_request
:
18474
author
:
type
:
fixed
spec/models/user_spec.rb
View file @
3f73b6be
...
...
@@ -393,24 +393,6 @@ describe User do
end
describe
'after commit hook'
do
describe
'.update_invalid_gpg_signatures'
do
let
(
:user
)
do
create
(
:user
,
email:
'tula.torphy@abshire.ca'
).
tap
do
|
user
|
user
.
skip_reconfirmation!
end
end
it
'does nothing when the name is updated'
do
expect
(
user
).
not_to
receive
(
:update_invalid_gpg_signatures
)
user
.
update_attributes!
(
name:
'Bette'
)
end
it
'synchronizes the gpg keys when the email is updated'
do
expect
(
user
).
to
receive
(
:update_invalid_gpg_signatures
).
at_most
(
:twice
)
user
.
update_attributes!
(
email:
'shawnee.ritchie@denesik.com'
)
end
end
describe
'#update_emails_with_primary_email'
do
before
do
@user
=
create
(
:user
,
email:
'primary@example.com'
).
tap
do
|
user
|
...
...
@@ -450,6 +432,76 @@ describe User do
expect
(
@user
.
emails
.
first
.
confirmed_at
).
not_to
eq
nil
end
end
describe
'#update_notification_email'
do
# Regression: https://gitlab.com/gitlab-org/gitlab-ce/issues/22846
context
'when changing :email'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:new_email
)
{
'new-email@example.com'
}
it
'sets :unconfirmed_email'
do
expect
do
user
.
tap
{
|
u
|
u
.
update!
(
email:
new_email
)
}.
reload
end
.
to
change
(
user
,
:unconfirmed_email
).
to
(
new_email
)
end
it
'does not change :notification_email'
do
expect
do
user
.
tap
{
|
u
|
u
.
update!
(
email:
new_email
)
}.
reload
end
.
not_to
change
(
user
,
:notification_email
)
end
it
'updates :notification_email to the new email once confirmed'
do
user
.
update!
(
email:
new_email
)
expect
do
user
.
tap
(
&
:confirm
).
reload
end
.
to
change
(
user
,
:notification_email
).
to
eq
(
new_email
)
end
context
'and :notification_email is set to a secondary email'
do
let!
(
:email_attrs
)
{
attributes_for
(
:email
,
:confirmed
,
user:
user
)
}
let
(
:secondary
)
{
create
(
:email
,
:confirmed
,
email:
'secondary@example.com'
,
user:
user
)
}
before
do
user
.
emails
.
create
(
email_attrs
)
user
.
tap
{
|
u
|
u
.
update!
(
notification_email:
email_attrs
[
:email
])
}.
reload
end
it
'does not change :notification_email to :email'
do
expect
do
user
.
tap
{
|
u
|
u
.
update!
(
email:
new_email
)
}.
reload
end
.
not_to
change
(
user
,
:notification_email
)
end
it
'does not change :notification_email to :email once confirmed'
do
user
.
update!
(
email:
new_email
)
expect
do
user
.
tap
(
&
:confirm
).
reload
end
.
not_to
change
(
user
,
:notification_email
)
end
end
end
end
describe
'#update_invalid_gpg_signatures'
do
let
(
:user
)
do
create
(
:user
,
email:
'tula.torphy@abshire.ca'
).
tap
do
|
user
|
user
.
skip_reconfirmation!
end
end
it
'does nothing when the name is updated'
do
expect
(
user
).
not_to
receive
(
:update_invalid_gpg_signatures
)
user
.
update_attributes!
(
name:
'Bette'
)
end
it
'synchronizes the gpg keys when the email is updated'
do
expect
(
user
).
to
receive
(
:update_invalid_gpg_signatures
).
at_most
(
:twice
)
user
.
update_attributes!
(
email:
'shawnee.ritchie@denesik.com'
)
end
end
end
describe
'#update_tracked_fields!'
,
:clean_gitlab_redis_shared_state
do
...
...
spec/requests/api/users_spec.rb
View file @
3f73b6be
...
...
@@ -488,10 +488,6 @@ describe API::Users do
describe
"PUT /users/:id"
do
let!
(
:admin_user
)
{
create
(
:admin
)
}
before
do
admin
end
it
"updates user with new bio"
do
put
api
(
"/users/
#{
user
.
id
}
"
,
admin
),
{
bio:
'new test bio'
}
...
...
@@ -525,27 +521,28 @@ describe API::Users do
expect
(
json_response
[
'avatar_url'
]).
to
include
(
user
.
avatar_path
)
end
it
'updates user with his own email'
do
put
api
(
"/users/
#{
user
.
id
}
"
,
admin
),
email:
user
.
email
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
json_response
[
'email'
]).
to
eq
(
user
.
email
)
expect
(
user
.
reload
.
email
).
to
eq
(
user
.
email
)
end
it
'updates user with a new email'
do
old_email
=
user
.
email
old_notification_email
=
user
.
notification_email
put
api
(
"/users/
#{
user
.
id
}
"
,
admin
),
email:
'new@email.com'
user
.
reload
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
user
.
reload
.
notification_email
).
to
eq
(
'new@email.com'
)
expect
(
user
).
to
be_confirmed
expect
(
user
.
email
).
to
eq
(
old_email
)
expect
(
user
.
notification_email
).
to
eq
(
old_notification_email
)
expect
(
user
.
unconfirmed_email
).
to
eq
(
'new@email.com'
)
end
it
'skips reconfirmation when requested'
do
put
api
(
"/users/
#{
user
.
id
}
"
,
admin
),
{
skip_reconfirmation:
true
}
put
api
(
"/users/
#{
user
.
id
}
"
,
admin
),
email:
'new@email.com'
,
skip_reconfirmation:
true
user
.
reload
expect
(
user
.
confirmed_at
).
to
be_present
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
user
).
to
be_confirmed
expect
(
user
.
email
).
to
eq
(
'new@email.com'
)
end
it
'updates user with his own username'
do
...
...
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