From ca5f555750ff2225988f75fb87b02ad4de81b490 Mon Sep 17 00:00:00 2001 From: Josh Kerxhalli-Kleinfield Date: Tue, 21 Apr 2020 09:46:42 -0400 Subject: [PATCH] FEATURE: Allow using array indexes in json paths (#22) --- plugin.rb | 25 +++++++++++++++++++++---- spec/plugin_spec.rb | 9 +++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/plugin.rb b/plugin.rb index 7af1f18..6a06561 100644 --- a/plugin.rb +++ b/plugin.rb @@ -87,22 +87,39 @@ class ::OAuth2BasicAuthenticator < Auth::ManagedAuthenticator "Basic " + Base64.strict_encode64("#{SiteSetting.oauth2_client_id}:#{SiteSetting.oauth2_client_secret}") end - def walk_path(fragment, segments) - first_seg = segments[0] + def walk_path(fragment, segments, seg_index = 0) + first_seg = segments[seg_index] return if first_seg.blank? || fragment.blank? return nil unless fragment.is_a?(Hash) || fragment.is_a?(Array) + first_seg = segments[seg_index].scan(/([\d+])/).length > 0 ? first_seg.split("[")[0] : first_seg if fragment.is_a?(Hash) deref = fragment[first_seg] || fragment[first_seg.to_sym] else - deref = fragment[0] # Take just the first array for now, maybe later we can teach it to walk the array if we need to + array_index = 0 + if (seg_index > 0) + last_index = segments[seg_index - 1].scan(/([\d+])/).flatten() || [0] + array_index = last_index.length > 0 ? last_index[0].to_i : 0 + end + if fragment.any? && fragment.length >= array_index - 1 + deref = fragment[array_index][first_seg] + else + deref = nil + end end - (deref.blank? || segments.size == 1) ? deref : walk_path(deref, segments[1..-1]) + if (deref.blank? || seg_index == segments.size - 1) + deref + else + seg_index += 1 + walk_path(deref, segments, seg_index) + end end def json_walk(result, user_json, prop) 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(".[", "[") segments = path.split('.') val = walk_path(user_json, segments) result[prop] = val if val.present? diff --git a/spec/plugin_spec.rb b/spec/plugin_spec.rb index 9b74275..664b7b2 100644 --- a/spec/plugin_spec.rb +++ b/spec/plugin_spec.rb @@ -195,6 +195,15 @@ describe OAuth2BasicAuthenticator do expect(result).to eq nil end + it 'can walk json and find values by index in an array' do + authenticator = OAuth2BasicAuthenticator.new + json_string = '{"emails":[{"value":"test@example.com"},{"value":"test2@example.com"}]}' + SiteSetting.oauth2_json_email_path = 'emails[1].value' + result = authenticator.json_walk({}, JSON.parse(json_string), :email) + + expect(result).to eq "test2@example.com" + end + it 'can walk json and download avatar' do authenticator = OAuth2BasicAuthenticator.new json_string = '{"user":{"avatar":"http://example.com/1.png"}}'