diff --git a/lib/ldclient-rb/impl/context_filter.rb b/lib/ldclient-rb/impl/context_filter.rb index 3e8c9f6a..6fe8d68c 100644 --- a/lib/ldclient-rb/impl/context_filter.rb +++ b/lib/ldclient-rb/impl/context_filter.rb @@ -73,12 +73,12 @@ def filter_redact_anonymous(context) private_attributes = @private_attributes + context.private_attributes name = context.get_value(:name) - if !name.nil? && !check_whole_attribute_private(:name, private_attributes, redacted, anonymous && redact_anonymous) + if !name.nil? && !check_whole_attribute_private(Reference.create_literal(:name), private_attributes, redacted, anonymous && redact_anonymous) filtered[:name] = name end context.get_custom_attribute_names.each do |attribute| - unless check_whole_attribute_private(attribute, private_attributes, redacted, anonymous && redact_anonymous) + unless check_whole_attribute_private(Reference.create_literal(attribute), private_attributes, redacted, anonymous && redact_anonymous) value = context.get_value(attribute) filtered[attribute] = redact_json_value(nil, attribute, value, private_attributes, redacted) end @@ -92,7 +92,7 @@ def filter_redact_anonymous(context) # # Check if an entire attribute should be redacted. # - # @param attribute [Symbol] + # @param attribute [Reference] # @param private_attributes [Array] # @param redacted [Array] # @param redact_all [Boolean] @@ -100,13 +100,13 @@ def filter_redact_anonymous(context) # private def check_whole_attribute_private(attribute, private_attributes, redacted, redact_all) if @all_attributes_private || redact_all - redacted << attribute + redacted << attribute.raw_path.to_sym return true end private_attributes.each do |private_attribute| - if private_attribute.component(0) == attribute && private_attribute.depth == 1 - redacted << attribute + if private_attribute.component(0) == attribute.component(0) && private_attribute.depth == 1 + redacted << attribute.raw_path.to_sym return true end end diff --git a/spec/impl/context_filter_spec.rb b/spec/impl/context_filter_spec.rb index 000849c9..0c1e205a 100644 --- a/spec/impl/context_filter_spec.rb +++ b/spec/impl/context_filter_spec.rb @@ -3,6 +3,34 @@ module LaunchDarkly module Impl describe ContextFilter do + it "reports redacted attribute names as escaped attribute references" do + filter = ContextFilter.new(true, []) + context = LDContext.create({ kind: "user", key: "user-key", :"/ssn" => "123-45-6789", :"a/b~c" => "value" }) + + filtered = filter.filter(context) + + expect(filtered[:_meta][:redactedAttributes]).to contain_exactly(:"/~1ssn", :"a/b~c") + end + + it "escapes redacted attribute names when redacting anonymous contexts" do + filter = ContextFilter.new(false, []) + context = LDContext.create({ kind: "user", key: "user-key", anonymous: true, name: "name", :"/ssn" => "123-45-6789" }) + + filtered = filter.filter_redact_anonymous(context) + + expect(filtered[:_meta][:redactedAttributes]).to contain_exactly(:name, :"/~1ssn") + end + + it "escapes redacted attribute names configured as private" do + filter = ContextFilter.new(false, ["/~1ssn"]) + context = LDContext.create({ kind: "user", key: "user-key", :"/ssn" => "123-45-6789", name: "name" }) + + filtered = filter.filter(context) + + expect(filtered[:name]).to eq("name") + expect(filtered[:_meta][:redactedAttributes]).to eq([:"/~1ssn"]) + end + it "does not apply per-context private attributes to later contexts" do filter = ContextFilter.new(false, []) private_context = LDContext.create({ kind: "user", key: "user-key", email: "email", _meta: { privateAttributes: ["email"] } })