Feature #21421 » 0004-Send-a-security-notification-when-a-user-s-email-add.patch
| app/models/email_address.rb | ||
|---|---|---|
| 19 | 19 |
belongs_to :user |
| 20 | 20 |
attr_protected :id |
| 21 |
after_update :destroy_tokens |
|
| 22 |
after_destroy :destroy_tokens |
|
| 21 |
after_create :deliver_security_notification_create |
|
| 22 |
after_update :destroy_tokens, :deliver_security_notification_update |
|
| 23 |
after_destroy :destroy_tokens, :deliver_security_notification_destroy |
|
| 23 | 24 |
validates_presence_of :address |
| 24 | 25 |
validates_format_of :address, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, :allow_blank => true
|
| ... | ... | |
| 42 | 43 |
private |
| 44 |
# send a security notification to user that a new email address was added |
|
| 45 |
def deliver_security_notification_create |
|
| 46 |
# only deliver if this isn't the only address. |
|
| 47 |
# in that case, the user is just being created and |
|
| 48 |
# should not receive this email. |
|
| 49 |
if user.mails != [address] |
|
| 50 |
deliver_security_notification(user, |
|
| 51 |
message: :mail_body_security_notification_add, |
|
| 52 |
field: :field_mail, |
|
| 53 |
value: address |
|
| 54 |
) |
|
| 55 |
end |
|
| 56 |
end |
|
| 57 | ||
| 58 |
# send a security notification to user that an email has been changed (notified/not notified) |
|
| 59 |
def deliver_security_notification_update |
|
| 60 |
if address_changed? |
|
| 61 |
recipients = [user, address_was] |
|
| 62 |
options = {
|
|
| 63 |
message: :mail_body_security_notification_change_to, |
|
| 64 |
field: :field_mail, |
|
| 65 |
value: address |
|
| 66 |
} |
|
| 67 |
elsif notify_changed? |
|
| 68 |
recipients = [user, address] |
|
| 69 |
options = {
|
|
| 70 |
message: notify_was ? :mail_body_security_notification_notify_disabled : :mail_body_security_notification_notify_enabled, |
|
| 71 |
value: address |
|
| 72 |
} |
|
| 73 |
end |
|
| 74 |
deliver_security_notification(recipients, options) |
|
| 75 |
end |
|
| 76 | ||
| 77 |
# send a security notification to user that an email address was deleted |
|
| 78 |
def deliver_security_notification_destroy |
|
| 79 |
deliver_security_notification([user, address], |
|
| 80 |
message: :mail_body_security_notification_remove, |
|
| 81 |
field: :field_mail, |
|
| 82 |
value: address |
|
| 83 |
) |
|
| 84 |
end |
|
| 85 | ||
| 86 |
# generic method to send security notifications for email addresses |
|
| 87 |
def deliver_security_notification(recipients, options={})
|
|
| 88 |
Mailer.security_notification(recipients, |
|
| 89 |
options.merge( |
|
| 90 |
title: :label_my_account, |
|
| 91 |
url: {controller: 'my', action: 'account'}
|
|
| 92 |
) |
|
| 93 |
).deliver |
|
| 94 |
end |
|
| 95 | ||
| 43 | 96 |
# Delete all outstanding password reset tokens on email change. |
| 44 | 97 |
# This helps to keep the account secure in case the associated email account |
| 45 | 98 |
# was compromised. |
| config/locales/de.yml | ||
|---|---|---|
| 853 | 853 |
mail_body_security_notification_change_to: "%{field} wurde geändert zu %{value}."
|
| 854 | 854 |
mail_body_security_notification_add: "%{field} %{value} wurde hinzugefügt."
|
| 855 | 855 |
mail_body_security_notification_remove: "%{field} %{value} wurde entfernt."
|
| 856 |
mail_body_security_notification_notify_enabled: "E-Mail-Adresse %{value} erhält nun Benachrichtigungen."
|
|
| 857 |
mail_body_security_notification_notify_disabled: "E-Mail-Adresse %{value} erhält keine Benachrichtigungen mehr."
|
|
| 856 | 858 |
notice_account_activated: Ihr Konto ist aktiviert. Sie können sich jetzt anmelden. |
| 857 | 859 |
notice_account_deleted: Ihr Benutzerkonto wurde unwiderruflich gelöscht. |
| config/locales/en.yml | ||
|---|---|---|
| 232 | 232 |
mail_body_security_notification_change_to: "%{field} was changed to %{value}."
|
| 233 | 233 |
mail_body_security_notification_add: "%{field} %{value} was added."
|
| 234 | 234 |
mail_body_security_notification_remove: "%{field} %{value} was removed."
|
| 235 |
mail_body_security_notification_notify_enabled: "Email address %{value} now receives notifications."
|
|
| 236 |
mail_body_security_notification_notify_disabled: "Email address %{value} no longer receives notifications."
|
|
| 235 | 237 |
field_name: Name |
| 236 | 238 |
field_description: Description |
| test/functional/email_addresses_controller_test.rb | ||
|---|---|---|
| 92 | 92 |
end |
| 93 | 93 |
end |
| 94 |
def test_create_should_send_security_notification |
|
| 95 |
@request.session[:user_id] = 2 |
|
| 96 |
ActionMailer::Base.deliveries.clear |
|
| 97 |
post :create, :user_id => 2, :email_address => {:address => 'something@example.fr'}
|
|
| 98 | ||
| 99 |
assert_not_nil (mail = ActionMailer::Base.deliveries.last) |
|
| 100 |
assert_mail_body_match '0.0.0.0', mail |
|
| 101 |
assert_mail_body_match I18n.t(:mail_body_security_notification_add, field: I18n.t(:field_mail), value: 'something@example.fr'), mail |
|
| 102 |
assert_select_email do |
|
| 103 |
assert_select 'a[href^=?]', 'http://localhost:3000/my/account', :text => 'My account' |
|
| 104 |
end |
|
| 105 |
# The old email address should be notified about a new address for security purposes |
|
| 106 |
assert [mail.bcc, mail.cc].flatten.include?(User.find(2).mail) |
|
| 107 |
assert [mail.bcc, mail.cc].flatten.include?('something@example.fr')
|
|
| 108 |
end |
|
| 109 | ||
| 94 | 110 |
def test_update |
| 95 | 111 |
@request.session[:user_id] = 2 |
| 96 | 112 |
email = EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo') |
| ... | ... | |
| 112 | 128 |
assert_equal false, email.reload.notify |
| 113 | 129 |
end |
| 130 |
def test_update_should_send_security_notification |
|
| 131 |
@request.session[:user_id] = 2 |
|
| 132 |
email = EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo') |
|
| 133 | ||
| 134 |
ActionMailer::Base.deliveries.clear |
|
| 135 |
xhr :put, :update, :user_id => 2, :id => email.id, :notify => '0' |
|
| 136 | ||
| 137 |
assert_not_nil (mail = ActionMailer::Base.deliveries.last) |
|
| 138 |
assert_mail_body_match I18n.t(:mail_body_security_notification_notify_disabled, value: 'another@somenet.foo'), mail |
|
| 139 | ||
| 140 |
# The changed address should be notified for security purposes |
|
| 141 |
assert [mail.bcc, mail.cc].flatten.include?('another@somenet.foo')
|
|
| 142 |
end |
|
| 143 | ||
| 144 | ||
| 114 | 145 |
def test_destroy |
| 115 | 146 |
@request.session[:user_id] = 2 |
| 116 | 147 |
email = EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo') |
| ... | ... | |
| 141 | 172 |
assert_response 404 |
| 142 | 173 |
end |
| 143 | 174 |
end |
| 175 | ||
| 176 |
def test_destroy_should_send_security_notification |
|
| 177 |
@request.session[:user_id] = 2 |
|
| 178 |
email = EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo') |
|
| 179 | ||
| 180 |
ActionMailer::Base.deliveries.clear |
|
| 181 |
xhr :delete, :destroy, :user_id => 2, :id => email.id |
|
| 182 | ||
| 183 |
assert_not_nil (mail = ActionMailer::Base.deliveries.last) |
|
| 184 |
assert_mail_body_match I18n.t(:mail_body_security_notification_remove, field: I18n.t(:field_mail), value: 'another@somenet.foo'), mail |
|
| 185 | ||
| 186 |
# The removed address should be notified for security purposes |
|
| 187 |
assert [mail.bcc, mail.cc].flatten.include?('another@somenet.foo')
|
|
| 188 |
end |
|
| 144 | 189 |
end |
| test/functional/my_controller_test.rb | ||
|---|---|---|
| 117 | 117 |
assert user.groups.empty? |
| 118 | 118 |
end |
| 119 |
def test_update_account_should_send_security_notification |
|
| 120 |
ActionMailer::Base.deliveries.clear |
|
| 121 |
post :account, |
|
| 122 |
:user => {
|
|
| 123 |
:mail => 'foobar@example.com' |
|
| 124 |
} |
|
| 125 | ||
| 126 |
assert_not_nil (mail = ActionMailer::Base.deliveries.last) |
|
| 127 |
assert_mail_body_match '0.0.0.0', mail |
|
| 128 |
assert_mail_body_match I18n.t(:mail_body_security_notification_change_to, field: I18n.t(:field_mail), value: 'foobar@example.com'), mail |
|
| 129 |
assert_select_email do |
|
| 130 |
assert_select 'a[href^=?]', 'http://localhost:3000/my/account', :text => 'My account' |
|
| 131 |
end |
|
| 132 |
# The old email address should be notified about the change for security purposes |
|
| 133 |
assert [mail.bcc, mail.cc].flatten.include?(User.find(2).mail) |
|
| 134 |
assert [mail.bcc, mail.cc].flatten.include?('foobar@example.com')
|
|
| 135 |
end |
|
| 136 | ||
| 119 | 137 |
def test_my_account_should_show_destroy_link |
| 120 | 138 |
get :account |
| 121 | 139 |
assert_select 'a[href="/my/account/destroy"]' |