Module: Ribbon::EncryptedStore::Mixins::ActiveRecordMixin

Defined in:
lib/ribbon/encrypted_store/mixins/active_record_mixin.rb,
lib/ribbon/encrypted_store/mixins/active_record_mixin/encryption_key.rb,
lib/ribbon/encrypted_store/mixins/active_record_mixin/encryption_key_salt.rb

Defined Under Namespace

Modules: ClassMethods Classes: EncryptionKey, EncryptionKeySalt

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.descendantsObject



15
16
17
18
# File 'lib/ribbon/encrypted_store/mixins/active_record_mixin.rb', line 15

def descendants
  Rails.application.eager_load! if defined?(Rails) && Rails.application
  ActiveRecord::Base.descendants.select { |model| model < Mixins::ActiveRecordMixin }
end

.descendants?Boolean

Returns:

  • (Boolean)


20
21
22
# File 'lib/ribbon/encrypted_store/mixins/active_record_mixin.rb', line 20

def descendants?
  !descendants.empty?
end

.included(base) ⇒ Object



10
11
12
13
# File 'lib/ribbon/encrypted_store/mixins/active_record_mixin.rb', line 10

def included(base)
  base.before_save(:_encrypted_store_save)
  base.extend(ClassMethods)
end

.preload_keys(amount) ⇒ Object

Preloads the most recent ‘amount` keys.



26
27
28
# File 'lib/ribbon/encrypted_store/mixins/active_record_mixin.rb', line 26

def preload_keys(amount)
  EncryptionKey.preload(amount) if descendants?
end

Instance Method Details

#_crypto_hashObject



68
69
70
# File 'lib/ribbon/encrypted_store/mixins/active_record_mixin.rb', line 68

def _crypto_hash
  @_crypto_hash ||= CryptoHash.decrypt(_decrypted_key, self.encrypted_store)
end

#_decrypted_keyObject



72
73
74
# File 'lib/ribbon/encrypted_store/mixins/active_record_mixin.rb', line 72

def _decrypted_key
  EncryptedStore.retrieve_dek(EncryptionKey, _encryption_key_id)
end

#_encrypted_store_dataObject



60
61
62
# File 'lib/ribbon/encrypted_store/mixins/active_record_mixin.rb', line 60

def _encrypted_store_data
  self.class._encrypted_store_data
end

#_encrypted_store_get(field) ⇒ Object



76
77
78
# File 'lib/ribbon/encrypted_store/mixins/active_record_mixin.rb', line 76

def _encrypted_store_get(field)
  _crypto_hash[field]
end

#_encrypted_store_saveObject



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/ribbon/encrypted_store/mixins/active_record_mixin.rb', line 85

def _encrypted_store_save
  if !(self.changed.map(&:to_sym) & _encrypted_store_data[:encrypted_attributes]).empty? || @_reencrypting
    # Obtain a lock without overriding attribute values for this record.
    record = self.class.unscoped { self.class.lock.find(id) } unless new_record?

    unless @_reencrypting
      self.encryption_key_id = record.encryption_key_id if record && record.encryption_key_id
    end

    iter_mag = Ribbon::EncryptedStore.config.iteration_magnitude? ?
               Ribbon::EncryptedStore.config.iteration_magnitude  :
               -1

    @_reencrypting = false
    self.encrypted_store = _crypto_hash.encrypt(
      _decrypted_key,
      EncryptionKeySalt.generate_salt(_encryption_key_id),
      iter_mag
    )
  end
end

#_encrypted_store_set(field, value) ⇒ Object



80
81
82
83
# File 'lib/ribbon/encrypted_store/mixins/active_record_mixin.rb', line 80

def _encrypted_store_set(field, value)
  attribute_will_change!(field)
  _crypto_hash[field] = value
end

#_encryption_key_idObject



64
65
66
# File 'lib/ribbon/encrypted_store/mixins/active_record_mixin.rb', line 64

def _encryption_key_id
  self.encryption_key_id ||= EncryptionKey.primary_encryption_key.id
end

#reencrypt(encryption_key) ⇒ Object

Instance Methods



50
51
52
53
54
# File 'lib/ribbon/encrypted_store/mixins/active_record_mixin.rb', line 50

def reencrypt(encryption_key)
  _crypto_hash
  self.encryption_key_id = encryption_key.id
  @_reencrypting = true
end

#reencrypt!(encryption_key) ⇒ Object



56
57
58
# File 'lib/ribbon/encrypted_store/mixins/active_record_mixin.rb', line 56

def reencrypt!(encryption_key)
  reencrypt(encryption_key).tap { save! }
end