lib/lockbox/model.rb in lockbox-1.0.0 vs lib/lockbox/model.rb in lockbox-1.1.0
- old
+ new
@@ -224,9 +224,55 @@
end
end
result
end
+
+ if ActiveRecord::VERSION::MAJOR >= 6
+ def self.insert_all(attributes, **options)
+ super(lockbox_map_attributes(attributes), **options)
+ end
+
+ def self.insert_all!(attributes, **options)
+ super(lockbox_map_attributes(attributes), **options)
+ end
+
+ def self.upsert_all(attributes, **options)
+ super(lockbox_map_attributes(attributes, check_readonly: true), **options)
+ end
+
+ # private
+ # does not try to handle :returning option for simplicity
+ def self.lockbox_map_attributes(records, check_readonly: false)
+ return records unless records.is_a?(Array)
+
+ records.map do |attributes|
+ # transform keys like Active Record
+ attributes = attributes.transform_keys do |key|
+ n = key.to_s
+ attribute_aliases[n] || n
+ end
+
+ lockbox_attributes = self.lockbox_attributes.slice(*attributes.keys.map(&:to_sym))
+ lockbox_attributes.each do |key, lockbox_attribute|
+ attribute = key.to_s
+ # check read only
+ # users should mark both plaintext and ciphertext columns
+ if check_readonly && readonly_attributes.include?(attribute) && !readonly_attributes.include?(lockbox_attribute[:encrypted_attribute].to_s)
+ warn "[lockbox] WARNING: Mark attribute as readonly: #{lockbox_attribute[:encrypted_attribute]}"
+ end
+
+ message = attributes[attribute]
+ attributes.delete(attribute) unless lockbox_attribute[:migrating]
+ encrypted_attribute = lockbox_attribute[:encrypted_attribute]
+ ciphertext = send("generate_#{encrypted_attribute}", message)
+ attributes[encrypted_attribute] = ciphertext
+ end
+
+ attributes
+ end
+ end
+ end
else
def reload
self.class.lockbox_attributes.each do |_, v|
instance_variable_set("@#{v[:attribute]}", nil)
end