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?
|
if path.present?
|
||||||
#this.[].that is the same as this.that, allows for both this[0].that and this.[0].that path styles
|
#this.[].that is the same as this.that, allows for both this[0].that and this.[0].that path styles
|
||||||
path = path.gsub(".[].", ".").gsub(".[", "[")
|
path = path.gsub(".[].", ".").gsub(".[", "[")
|
||||||
segments = path.split('.')
|
segments = parse_segments(path)
|
||||||
val = walk_path(user_json, segments)
|
val = walk_path(user_json, segments)
|
||||||
result[prop] = val if val.present?
|
result[prop] = val if val.present?
|
||||||
end
|
end
|
||||||
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)
|
def log(info)
|
||||||
Rails.logger.warn("OAuth2 Debugging: #{info}") if SiteSetting.oauth2_debug_auth
|
Rails.logger.warn("OAuth2 Debugging: #{info}") if SiteSetting.oauth2_debug_auth
|
||||||
end
|
end
|
||||||
|
|
|
@ -177,6 +177,38 @@ describe OAuth2BasicAuthenticator do
|
||||||
expect(result).to eq "test@example.com"
|
expect(result).to eq "test@example.com"
|
||||||
end
|
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
|
it 'can walk json that contains an array' do
|
||||||
authenticator = OAuth2BasicAuthenticator.new
|
authenticator = OAuth2BasicAuthenticator.new
|
||||||
json_string = '{"email":"test@example.com","identities":[{"user_id":"123456789","provider":"auth0","isSocial":false}]}'
|
json_string = '{"email":"test@example.com","identities":[{"user_id":"123456789","provider":"auth0","isSocial":false}]}'
|
||||||
|
|
Loading…
Reference in New Issue