From 214a8d5b7eb24131750e474b255bf9642d5df6c2 Mon Sep 17 00:00:00 2001 From: Markus Rechtien Date: Wed, 8 Apr 2020 19:18:09 +0200 Subject: [PATCH 1/2] Implemented Blacklist strategy based on differential mongo update (only updated changed / anonymized fields) --- lib/strategy/mongodb/blacklist.rb | 42 +++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/lib/strategy/mongodb/blacklist.rb b/lib/strategy/mongodb/blacklist.rb index 4160dd9..7300049 100644 --- a/lib/strategy/mongodb/blacklist.rb +++ b/lib/strategy/mongodb/blacklist.rb @@ -2,25 +2,53 @@ module DataAnon module Strategy module MongoDB class Blacklist < DataAnon::Strategy::MongoDB::Whitelist - def self.whitelist? false end - def process_record index, document - anonymized_document = anonymize_document(document, index, @fields) - source_collection.find({'_id' => anonymized_document['_id']}).update_one(anonymized_document) + def process_record(index, document) + id = document["_id"] + begin + anonymized_document = anonymize_document(document, index, @fields) + updates = flatten_for_update anonymized_document + # differential mongodb update via { $set: { 'doc.nested.array.0.attr': 'value' }} + source_collection.update_one({ "_id" => id }, { "$set" => updates }) + rescue StandardError => e + puts e.message + end end - def anonymize_document document, index, field_strategies = {} + def anonymize_document(document, index, field_strategies = {}) + anonymized_document = {} field_strategies.each do |field_name, field_strategy| field_value = document[field_name] unless field_value.nil? field = DataAnon::Core::Field.new(field_name, field_value, index, document, @name) - document[field.name] = AnonymizeField.new(field, field_strategy, self).anonymize + result = AnonymizeField.new(field, field_strategy, self).anonymize + if !((result.kind_of?(Array) || result.kind_of?(Hash)) && result.size == 0) + anonymized_document[field.name] = result + end + end + end + anonymized_document + end + + def flatten_for_update(object, level = 0, name = "", updates = {}) + path = name.to_s + if object.is_a?(Array) + if level > 0 + path += "." + end + object.each_with_index { |child, idx| flatten_for_update(child, level + 1, path + idx.to_s, updates) } + elsif object.is_a?(Hash) + if level > 0 + path += "." end + object.each { |key, value| flatten_for_update(value, level + 1, path + key, updates) } + else + updates[path] = object.inspect end - document + updates end end From 2d860637a5faa2aeacba2613e629c50f496f75e1 Mon Sep 17 00:00:00 2001 From: Markus Rechtien Date: Thu, 9 Apr 2020 07:46:17 +0200 Subject: [PATCH 2/2] fix: skipped updating with empty document if no anomyzation was applied --- lib/strategy/mongodb/blacklist.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/strategy/mongodb/blacklist.rb b/lib/strategy/mongodb/blacklist.rb index 7300049..1591354 100644 --- a/lib/strategy/mongodb/blacklist.rb +++ b/lib/strategy/mongodb/blacklist.rb @@ -11,6 +11,10 @@ def process_record(index, document) begin anonymized_document = anonymize_document(document, index, @fields) updates = flatten_for_update anonymized_document + # skip empty documents/updates + if ((updates.kind_of?(Array) || updates.kind_of?(Hash)) && updates.size == 0) + return; + end # differential mongodb update via { $set: { 'doc.nested.array.0.attr': 'value' }} source_collection.update_one({ "_id" => id }, { "$set" => updates }) rescue StandardError => e