FEATURE: Fetch custom attributes from the user details. (#47)

Other plugins can tell the authenticator to traverse the user details JSON using custom paths and store the values in the user associated account extra field.
This commit is contained in:
Roman Rizzi 2021-07-01 18:23:27 -03:00 committed by GitHub
parent 6ee31f6b02
commit d1a912ebc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 2 deletions

View File

@ -71,6 +71,10 @@ class OAuth2FaradayFormatter < Faraday::Logging::Formatter
end
end
# You should use this register if you want to add custom paths to traverse the user details JSON.
# We'll store the value in the user associated account's extra attribute hash using the full path as the key.
DiscoursePluginRegistry.define_filtered_register :oauth2_basic_additional_json_paths
class ::OAuth2BasicAuthenticator < Auth::ManagedAuthenticator
def name
'oauth2_basic'
@ -164,8 +168,8 @@ class ::OAuth2BasicAuthenticator < Auth::ManagedAuthenticator
end
end
def json_walk(result, user_json, prop)
path = SiteSetting.public_send("oauth2_json_#{prop}_path")
def json_walk(result, user_json, prop, custom_path: nil)
path = custom_path || SiteSetting.public_send("oauth2_json_#{prop}_path")
if path.present?
#this.[].that is the same as this.that, allows for both this[0].that and this.[0].that path styles
path = path.gsub(".[].", ".").gsub(".[", "[")
@ -229,6 +233,11 @@ class ::OAuth2BasicAuthenticator < Auth::ManagedAuthenticator
json_walk(result, user_json, :email)
json_walk(result, user_json, :email_verified)
json_walk(result, user_json, :avatar)
DiscoursePluginRegistry.oauth2_basic_additional_json_paths.each do |detail|
prop = "extra:#{detail}"
json_walk(result, user_json, prop, custom_path: detail)
end
end
result
else
@ -259,6 +268,10 @@ class ::OAuth2BasicAuthenticator < Auth::ManagedAuthenticator
['name', 'email', 'email_verified'].each do |property|
auth['info'][property] = fetched_user_details[property.to_sym] if fetched_user_details[property.to_sym]
end
DiscoursePluginRegistry.oauth2_basic_additional_json_paths.each do |detail|
auth['extra'][detail] = fetched_user_details["extra:#{detail}"]
end
else
result = Auth::Result.new
result.failed = true

View File

@ -122,6 +122,31 @@ describe OAuth2BasicAuthenticator do
result = authenticator.after_authenticate(auth)
expect(result.failed).to eq(true)
end
describe 'fetch custom attributes' do
after { DiscoursePluginRegistry.reset! }
let(:response) do
{
status: 200,
body: '{"account":{"email":"newemail@example.com","custom_attr":"received"}}'
}
end
it 'stores custom attributes in the user associated account' do
custom_path = 'account.custom_attr'
DiscoursePluginRegistry.register_oauth2_basic_additional_json_path(
custom_path,
Plugin::Instance.new
)
stub_request(:get, SiteSetting.oauth2_user_json_url).to_return(response)
result = authenticator.after_authenticate(auth)
associated_account = UserAssociatedAccount.last
expect(associated_account.extra[custom_path]).to eq("received")
end
end
end
context 'avatar downloading' do