Class: ActiveRecord::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/symmetric_encryption/extensions/active_record/base.rb

Class Method Summary collapse

Class Method Details

.attr_encrypted(*params) ⇒ Object

Much lighter weight encryption for Rails attributes matching the attr_encrypted interface using SymmetricEncryption

The regular attr_encrypted gem uses Encryptor that adds encryption to every Ruby object which is a complete overkill for this simple use-case

Params:

  • symbolic names of each method to create which has a corresponding method already defined in rails starting with: encrypted_

  • Followed by an option hash:

    :marshal => Whether this element should be converted to YAML before encryption
                true or false
                Default: false
    


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
# File 'lib/symmetric_encryption/extensions/active_record/base.rb', line 19

def attr_encrypted(*params)
  # Ensure ActiveRecord has created all its methods first
  # Ignore failures since the table may not yet actually exist
  define_attribute_methods rescue nil

  options = params.last.is_a?(Hash) ? params.pop : {}

  params.each do |attribute|
    # Generate unencrypted attribute with getter and setter
    class_eval(<<-UNENCRYPTED, __FILE__, __LINE__ + 1)
      # Returns the decrypted value for the encrypted attribute
      # 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 #{attribute}
        if @stored_encrypted_#{attribute} != self.encrypted_#{attribute}
          @#{attribute} = ::SymmetricEncryption.decrypt(self.encrypted_#{attribute})
          @stored_encrypted_#{attribute} = self.encrypted_#{attribute}
        end
        @#{attribute}
      end

      # Set the un-encrypted attribute
      # Also updates the encrypted field with the encrypted value
      def #{attribute}=(value)
        self.encrypted_#{attribute} = @stored_encrypted_#{attribute} = ::SymmetricEncryption.encrypt(value#{".to_yaml" if options[:marshal]})
        @#{attribute} = value
      end
    UNENCRYPTED

    encrypted_attributes[attribute.to_sym] = "encrypted_#{attribute}".to_sym
  end
end

.encrypted_attribute?(attribute) ⇒ Boolean

Returns whether an attribute has been configured to be encrypted

Example

class User < ActiveRecord::Base
  attr_accessor :name
  attr_encrypted :email
end

User.encrypted_attribute?(:name) # false
User.encrypted_attribute?(:email) # true

Returns:

  • (Boolean)


89
90
91
# File 'lib/symmetric_encryption/extensions/active_record/base.rb', line 89

def encrypted_attribute?(attribute)
  encrypted_keys.include?(attribute)
end

.encrypted_attributesObject

Contains a hash of encrypted attributes with virtual attribute names as keys and real attribute names as values

Example

class User < ActiveRecord::Base
  attr_encrypted :email
end

User.encrypted_attributes # { :email => :encrypted_email }


62
63
64
# File 'lib/symmetric_encryption/extensions/active_record/base.rb', line 62

def encrypted_attributes
  @encrypted_attributes ||= superclass.respond_to?(:encrypted_attributes) ? superclass.encrypted_attributes.dup : {}
end

.encrypted_column?(attribute) ⇒ Boolean

Returns whether the attribute is the database column to hold the encrypted data for a matching encrypted attribute

Example

class User < ActiveRecord::Base
  attr_accessor :name
  attr_encrypted :email
end

User.encrypted_column?(:encrypted_name) # false
User.encrypted_column?(:encrypted_email) # true

Returns:

  • (Boolean)


105
106
107
# File 'lib/symmetric_encryption/extensions/active_record/base.rb', line 105

def encrypted_column?(attribute)
  encrypted_columns.include?(attribute)
end

.encrypted_columnsObject

Return the name of all encrypted columns as an Array of symbols Example: [:encrypted_email, :encrypted_password]



74
75
76
# File 'lib/symmetric_encryption/extensions/active_record/base.rb', line 74

def encrypted_columns
  @encrypted_columns ||= encrypted_attributes.values
end

.encrypted_keysObject

Return the name of all encrypted virtual attributes as an Array of symbols Example: [:email, :password]



68
69
70
# File 'lib/symmetric_encryption/extensions/active_record/base.rb', line 68

def encrypted_keys
  @encrypted_keys ||= encrypted_attributes.keys
end