lib/symmetric_encryption/mongoid.rb in symmetric-encryption-3.2 vs lib/symmetric_encryption/mongoid.rb in symmetric-encryption-3.3

- old
+ new

@@ -15,12 +15,19 @@ # class Person # include Mongoid::Document # # field :name, :type => String # field :encrypted_social_security_number, :type => String, :encrypted => true -# field :age, :type => Integer +# field :date_of_birth, :type => Date # field :encrypted_life_history, :type => String, :encrypted => {:compress => true, :random_iv => true} +# +# # Encrypted fields are _always_ stored in Mongo as a String +# # To get the result back as an Integer, Symmetric Encryption can do the +# # necessary conversions by specifying the internal type as an option +# # to :encrypted +# # #see SymmetricEncryption::COERCION_TYPES for full list of types +# field :encrypted_age, :type => String, :encrypted => {:type => :integer, :random_iv => true} # end # # The above document results in the following document in the Mongo collection 'persons': # { # "name" : "Joe", @@ -65,14 +72,18 @@ # # @param [ Symbol ] name The name of the field. # @param [ Hash ] options The options to pass to the field. # # @option options [ Boolean | Hash ] :encrypted If the field contains encrypted data. -# @option options [ Symbol ] :decrypt_as Name of the getters and setters to generate to access the decrypted value of this field. -# @option options [ Boolean ] :compress Whether to compress this encrypted field -# @option options [ Boolean ] :random_iv Whether the encrypted value should use a random IV every time the field is encrypted. +# When :encrypted is a Hash it consists of: +# @option options [ Symbol ] :type The type for this field, #see SymmetricEncryption::COERCION_TYPES +# @option options [ Boolean ] :random_iv Whether the encrypted value should use a random IV every time the field is encrypted. +# @option options [ Boolean ] :compress Whether to compress this encrypted field +# @option options [ Symbol ] :decrypt_as Name of the getters and setters to generate to access the decrypted value of this field. # +# Some of the other regular Mongoid options: +# # @option options [ Class ] :type The type of the field. # @option options [ String ] :label The label for the field. # @option options [ Object, Proc ] :default The fields default # # @return [ Field ] The generated field @@ -88,26 +99,37 @@ raise "SymmetricEncryption for Mongoid. Encryption enabled for field #{encrypted_field_name}. It must either start with 'encrypted_' or the option :decrypt_as must be supplied" end random_iv = options.delete(:random_iv) || false compress = options.delete(:compress) || false + type = options.delete(:type) || :string + raise "Invalid type: #{type.inspect}. Valid types: #{SymmetricEncryption::COERCION_TYPES.inspect}" unless SymmetricEncryption::COERCION_TYPES.include?(type) + options.each {|option| warn "Ignoring unknown option #{option.inspect} supplied to Mongoid :encrypted for #{model}##{field}"} + + if model.const_defined?(:EncryptedAttributes, _search_ancestors = false) + mod = model.const_get(:EncryptedAttributes) + else + mod = model.const_set(:EncryptedAttributes, Module.new) + model.send(:include, mod) + end + # Generate getter and setter methods - model.class_eval(<<-EOS, __FILE__, __LINE__ + 1) + mod.module_eval(<<-EOS, __FILE__, __LINE__ + 1) # Set the un-encrypted field # Also updates the encrypted field with the encrypted value # Freeze the decrypted field value so that it is not modified directly def #{decrypted_field_name}=(value) - self.#{encrypted_field_name} = @stored_#{encrypted_field_name} = ::SymmetricEncryption.encrypt(value,#{random_iv},#{compress}) + self.#{encrypted_field_name} = @stored_#{encrypted_field_name} = ::SymmetricEncryption.encrypt(value,#{random_iv},#{compress},:#{type}) @#{decrypted_field_name} = value.freeze end # Returns the decrypted value for the encrypted field # The decrypted value is cached and is only decrypted if the encrypted value has changed # If this method is not called, then the encrypted value is never decrypted def #{decrypted_field_name} if @stored_#{encrypted_field_name} != self.#{encrypted_field_name} - @#{decrypted_field_name} = ::SymmetricEncryption.decrypt(self.#{encrypted_field_name}).freeze + @#{decrypted_field_name} = ::SymmetricEncryption.decrypt(self.#{encrypted_field_name},version=nil,:#{type}).freeze @stored_#{encrypted_field_name} = self.#{encrypted_field_name} end @#{decrypted_field_name} end EOS