Skip to content

Commit

Permalink
Fixes zammad#4410 - Automatic third-party account linking notification.
Browse files Browse the repository at this point in the history
  • Loading branch information
dvuckovic committed Dec 12, 2022
1 parent 3d0d23e commit c8075ae
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 6 deletions.
31 changes: 30 additions & 1 deletion app/models/authorization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

class Authorization < ApplicationModel
belongs_to :user, optional: true
after_create :delete_user_cache
after_create :delete_user_cache, :notification_send
after_update :delete_user_cache
after_destroy :delete_user_cache
validates :user_id, presence: true
Expand Down Expand Up @@ -107,4 +107,33 @@ def delete_user_cache
user.touch # rubocop:disable Rails/SkipsModelValidations
end

# An account is considered linked if the user originates from a source other than the current authorization provider.
def linked_account?
user.source != provider
end

def notification_send

# Send a notification only if the feature is turned on and the account is linked.
return if !Setting.get('auth_third_party_linking_notification') || !user || !linked_account?

template = 'user_auth_provider'

if user.email.blank?
Rails.logger.info { "Unable to send a notification (#{template}) to user_id: #{user.id} be cause of missing email address." }
return
end

Rails.logger.debug { "Send notification (#{template}) to: #{user.email}" }

NotificationFactory::Mailer.notification(
template: template,
user: user,
objects: {
user: user,
provider: provider,
}
)
end

end
9 changes: 9 additions & 0 deletions app/views/mailer/user_auth_provider/en.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#{config.product_name} account linked with a third-party application

<div>Hi #{user.firstname},</div>
<br>
<div>It looks like you linked your account <b>with a third-party application</b> "#{provider}".</div>
<br>
<div>If this wasn't you, please remove the linked account from your profile and change your third-party application password. Somebody might have gained unauthorized access to your account on the third-party service.</div>
<br>
<div>Your #{config.product_name} Team</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/

class Issue4410AccountLinkingNotification < ActiveRecord::Migration[6.1]
def change
# return if it's a new setup
return if !Setting.exists?(name: 'system_init_done')

Setting.create_if_not_exists(
title: 'Automatic account linking notification',
name: 'auth_third_party_linking_notification',
area: 'Security::ThirdPartyAuthentication',
description: 'Enables sending of an email notification to a user when they link their account with a third-party application.',
options: {
form: [
{
display: '',
null: true,
name: 'auth_third_party_linking_notification',
tag: 'boolean',
options: {
true => 'yes',
false => 'no',
},
},
],
},
preferences: {
permission: ['admin.security'],
prio: 20,
},
state: false,
frontend: false
)
end
end
26 changes: 26 additions & 0 deletions db/seeds/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1268,6 +1268,32 @@
state: false,
frontend: false
)
Setting.create_if_not_exists(
title: __('Automatic account linking notification'),
name: 'auth_third_party_linking_notification',
area: 'Security::ThirdPartyAuthentication',
description: __('Enables sending of an email notification to a user when they link their account with a third-party application.'),
options: {
form: [
{
display: '',
null: true,
name: 'auth_third_party_linking_notification',
tag: 'boolean',
options: {
true => 'yes',
false => 'no',
},
},
],
},
preferences: {
permission: ['admin.security'],
prio: 20,
},
state: false,
frontend: false
)
Setting.create_if_not_exists(
title: __('Authentication via %s'),
name: 'auth_twitter',
Expand Down
14 changes: 14 additions & 0 deletions i18n/zammad.pot
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ msgstr ""
msgid "# #{ticket.title}\n_<#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}|Ticket##{ticket.number}>: Will escalate at #{ticket.escalation_at}_\nThe ticket (#{ticket.title}) from \"#{ticket.customer.longname}\" will escalate at \"#{ticket.escalation_at}\"!\n\n<% if @objects[:article] %>\n#{article.body_as_text}\n<% end %>\n"
msgstr ""

#. This is the template file app/views/mailer/user_auth_provider/en.html.erb in ERB/HTML format.
#. Please make sure to translate it to a valid corresponding output structure.
#: app/views/mailer/user_auth_provider/en.html.erb
msgid "#{config.product_name} account linked with a third-party application\n\n<div>Hi #{user.firstname},</div>\n<br>\n<div>It looks like you linked your account <b>with a third-party application</b> \"#{provider}\".</div>\n<br>\n<div>If this wasn't you, please remove the linked account from your profile and change your third-party application password. Somebody might have gained unauthorized access to your account on the third-party service.</div>\n<br>\n<div>Your #{config.product_name} Team</div>\n"
msgstr ""

#. This is the template file app/views/mailer/user_device_new_location/en.html.erb in ERB/HTML format.
#. Please make sure to translate it to a valid corresponding output structure.
#: app/views/mailer/user_device_new_location/en.html.erb
Expand Down Expand Up @@ -1406,6 +1412,10 @@ msgstr ""
msgid "Automatic account link on initial logon"
msgstr ""

#: db/seeds/settings.rb
msgid "Automatic account linking notification"
msgstr ""

#: app/assets/javascripts/app/controllers/_integration/clearbit.coffee
msgid "Automatically enrich your customers and organizations with fresh, up-to-date intel. Map data directly to object fields."
msgstr ""
Expand Down Expand Up @@ -4146,6 +4156,10 @@ msgstr ""
msgid "Enables priority icons in ticket overviews."
msgstr ""

#: db/seeds/settings.rb
msgid "Enables sending of an email notification to a user when they link their account with a third-party application."
msgstr ""

#: db/seeds/settings.rb
msgid "Enables the automatic linking of an existing account on initial login via a third party application. If this is disabled, an existing user must first log into Zammad and then link his \"Third Party\" account to his Zammad account via Profile -> Linked Accounts."
msgstr ""
Expand Down
15 changes: 15 additions & 0 deletions spec/db/migrate/issue_4410_account_linking_notification_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/

require 'rails_helper'

RSpec.describe Issue4410AccountLinkingNotification, type: :db_migration do
before do
Setting.find_by(name: 'auth_third_party_linking_notification').destroy!

migrate
end

it 'does create auth_third_party_linking_notification setting' do
expect(Setting.exists?(name: 'auth_third_party_linking_notification')).to be(true)
end
end
6 changes: 3 additions & 3 deletions spec/factories/authorization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

FactoryBot.define do
factory :authorization do
transient do
user { create(:customer) }
end
uid { Faker::Number.number(digits: 10) }
user { create(:customer) }
provider { 'foo' }

factory :twitter_authorization do
provider { 'twitter' }
Expand Down
68 changes: 66 additions & 2 deletions spec/models/authorization_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,78 @@
require 'rails_helper'

RSpec.describe Authorization, type: :model do
subject(:authorization) { create(:twitter_authorization) }

describe 'User assets' do
subject(:authorization) { create(:twitter_authorization) }

it 'does update assets after new authorizations created' do
authorization.user.assets({})
create(:twitter_authorization, provider: 'twitter2', user: authorization.user)
assets = authorization.user.reload.assets({})
expect(assets[:User][authorization.user.id]['accounts'].keys.count).to eq(2)
end
end

describe 'Account linking notification', sends_notification_emails: true do
subject(:authorization) { create(:authorization, user: agent, provider: 'github') }

let(:agent) { create(:agent) }

shared_examples 'sending out email notification' do
it 'sends out an email notification' do
check_notification do
authorization

sent(
template: 'user_auth_provider',
user: authorization.user,
objects: hash_including({ user: authorization.user, provider: authorization.provider })
)
end
end
end

shared_examples 'not sending out email notification' do
it 'does not send out an email notification' do
check_notification do
authorization

not_sent(
template: 'user_auth_provider',
user: authorization.user,
objects: hash_including({ user: authorization.user, provider: authorization.provider })
)
end
end
end

context 'with setting turned on' do
before do
Setting.set('auth_third_party_linking_notification', true)
end

context 'when linking with an existing account' do
it_behaves_like 'sending out email notification'

context 'when user has no email address' do
let(:agent) { create(:agent, email: '') }

it_behaves_like 'not sending out email notification'
end
end

context 'when creating a new account' do
let(:agent) { create(:agent, source: 'github') }

it_behaves_like 'not sending out email notification'
end
end

context 'with setting turned off' do
before do
Setting.set('auth_third_party_linking_notification', false)
end

it_behaves_like 'not sending out email notification'
end
end
end

0 comments on commit c8075ae

Please sign in to comment.