Module: BlindIndex::Model
- Defined in:
- lib/blind_index/model.rb
Defined Under Namespace
Modules: InstanceMethods
Instance Method Summary collapse
Instance Method Details
#blind_index(*attributes, rotate: false, migrating: false, **opts) ⇒ Object
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/blind_index/model.rb', line 3 def blind_index(*attributes, rotate: false, migrating: false, **opts) indexes = attributes.map { |a| [a, opts.dup] } indexes.concat(attributes.map { |a| [a, rotate.merge(rotate: true)] }) if rotate indexes.each do |name, | rotate = .delete(:rotate) # check here so we validate rotate options as well unknown_keywords = .keys - [:algorithm, :attribute, :bidx_attribute, :callback, :cost, :encode, :expression, :insecure_key, :iterations, :key, :key_attribute, :key_table, :legacy, :master_key, :size, :slow, :version] raise ArgumentError, "unknown keywords: #{unknown_keywords.join(", ")}" if unknown_keywords.any? attribute = [:attribute] || name version = ([:version] || 1).to_i callback = [:callback].nil? ? true : [:callback] if [:bidx_attribute] bidx_attribute = [:bidx_attribute] else bidx_attribute = name bidx_attribute = "encrypted_#{bidx_attribute}" if [:legacy] bidx_attribute = "#{bidx_attribute}_bidx" bidx_attribute = "#{bidx_attribute}_v#{version}" if version != 1 end name = "migrated_#{name}" if name = "rotated_#{name}" if rotate name = name.to_sym attribute = attribute.to_sym method_name = :"compute_#{name}_bidx" class_method_name = :"generate_#{name}_bidx" key = [:key] key ||= -> { BlindIndex.index_key(table: [:key_table] || try(:table_name) || collection_name.to_s, bidx_attribute: [:key_attribute] || bidx_attribute, master_key: [:master_key], encode: false) } class_eval do activerecord = defined?(ActiveRecord) && self < ActiveRecord::Base if activerecord # blind index value isn't really sensitive # but don't need to show it in the Rails console self.filter_attributes += [/\A#{Regexp.escape(bidx_attribute)}\z/] end @blind_indexes ||= {} unless respond_to?(:blind_indexes) def self.blind_indexes parent_indexes = if superclass.respond_to?(:blind_indexes) superclass.blind_indexes else {} end parent_indexes.merge(@blind_indexes || {}) end end raise BlindIndex::Error, "Duplicate blind index: #{name}" if blind_indexes[name] @blind_indexes[name] = .merge( key: key, attribute: attribute, bidx_attribute: bidx_attribute, migrating: ) define_singleton_method class_method_name do |value| BlindIndex.generate_bidx(value, **blind_indexes[name]) end define_method method_name do send("#{bidx_attribute}=", self.class.send(class_method_name, send(attribute))) end if callback # TODO reuse module m = Module.new do define_method "#{attribute}=" do |value| result = super(value) send(method_name) result end unless activerecord define_method "reset_#{attribute}!" do result = super() send(method_name) result end end end prepend m end # use include so user can override include InstanceMethods if blind_indexes.size == 1 end end end |