FEATURE: Allow JSON paths with literal dots in the keys (#33)
This is achieved by surrounding a key with double quotes, or by escaping the dot character with a backslash. For example, given the JSON ``` { "www.example.com/uid": "myuid" } ``` Previously, there was no way to access this value. The dots would make the parser try to access `json["www"]["example"]["com/uid"]`. Now, this value can be accessed by using a `oauth2_json_user_id_path` like: ``` www\.example\.com/uid ``` or alternatively: ``` "www.example.com/uid" ```
This commit is contained in:
parent
0be01f0afd
commit
96a0bde0aa
24
plugin.rb
24
plugin.rb
|
@ -166,12 +166,34 @@ class ::OAuth2BasicAuthenticator < Auth::ManagedAuthenticator
|
|||
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(".[", "[")
|
||||
segments = path.split('.')
|
||||
segments = parse_segments(path)
|
||||
val = walk_path(user_json, segments)
|
||||
result[prop] = val if val.present?
|
||||
end
|
||||
end
|
||||
|
||||
def parse_segments(path)
|
||||
segments = [+""]
|
||||
quoted = false
|
||||
escaped = false
|
||||
|
||||
path.split("").each do |char|
|
||||
next_char_escaped = false
|
||||
if !escaped && (char == '"')
|
||||
quoted = !quoted
|
||||
elsif !escaped && !quoted && (char == '.')
|
||||
segments.append +""
|
||||
elsif !escaped && (char == '\\')
|
||||
next_char_escaped = true
|
||||
else
|
||||
segments.last << char
|
||||
end
|
||||
escaped = next_char_escaped
|
||||
end
|
||||
|
||||
segments
|
||||
end
|
||||
|
||||
def log(info)
|
||||
Rails.logger.warn("OAuth2 Debugging: #{info}") if SiteSetting.oauth2_debug_auth
|
||||
end
|
||||
|
|
|
@ -177,6 +177,38 @@ describe OAuth2BasicAuthenticator do
|
|||
expect(result).to eq "test@example.com"
|
||||
end
|
||||
|
||||
it 'allows keys containing dots, if wrapped in quotes' do
|
||||
authenticator = OAuth2BasicAuthenticator.new
|
||||
json_string = '{"www.example.com/uid": "myuid"}'
|
||||
SiteSetting.oauth2_json_user_id_path = '"www.example.com/uid"'
|
||||
result = authenticator.json_walk({}, JSON.parse(json_string), :user_id)
|
||||
|
||||
expect(result).to eq "myuid"
|
||||
end
|
||||
|
||||
it 'allows keys containing dots, if escaped' do
|
||||
authenticator = OAuth2BasicAuthenticator.new
|
||||
json_string = '{"www.example.com/uid": "myuid"}'
|
||||
SiteSetting.oauth2_json_user_id_path = 'www\.example\.com/uid'
|
||||
result = authenticator.json_walk({}, JSON.parse(json_string), :user_id)
|
||||
|
||||
expect(result).to eq "myuid"
|
||||
end
|
||||
|
||||
it 'allows keys containing literal backslashes, if escaped' do
|
||||
authenticator = OAuth2BasicAuthenticator.new
|
||||
# This 'single quoted heredoc' syntax means we don't have to escape backslashes in Ruby
|
||||
# What you see is exactly what the user would enter in the site settings
|
||||
json_string = <<~'_'.chomp
|
||||
{"www.example.com/uid\\": "myuid"}
|
||||
_
|
||||
SiteSetting.oauth2_json_user_id_path = <<~'_'.chomp
|
||||
www\.example\.com/uid\\
|
||||
_
|
||||
result = authenticator.json_walk({}, JSON.parse(json_string), :user_id)
|
||||
expect(result).to eq "myuid"
|
||||
end
|
||||
|
||||
it 'can walk json that contains an array' do
|
||||
authenticator = OAuth2BasicAuthenticator.new
|
||||
json_string = '{"email":"test@example.com","identities":[{"user_id":"123456789","provider":"auth0","isSocial":false}]}'
|
||||
|
|
Loading…
Reference in New Issue