module AttrVault::InstanceMethods

Public Instance Methods

before_save() click to toggle source
Calls superclass method
# File lib/attr_vault.rb, line 15
def before_save
  keyring = self.class.vault_keys
  current_key = keyring.current_key
  key_id = self[self.class.vault_key_field]
  record_key = self.class.vault_keys.fetch(key_id) unless key_id.nil?

  @vault_dirty_attrs ||= {}
  if !record_key.nil? && current_key != record_key
    # If the record key is not nil and not current, flag *all*
    # attrs as dirty, since we want to rewrite them all in order
    # to use the latest key. Note that when the record key is nil,
    # we're dealing with a new record, so there are no existing
    # vault attributes to rewrite. We only write these out when
    # they're set explicitly in a new record, in which case they
    # will be in the dirty attrs already and are handled below.
    self.class.vault_attrs.each do |attr|
      @vault_dirty_attrs[attr.name] ||= self.send(attr.name)
    end
  end
  # If any attr has migrate_from_field and the plaintext field
  # has a value set, flag the attr as dirty using the plaintext
  # source value, then nil out the plaintext field. Skip any
  # attributes that are already dirty.
  self.class.vault_attrs.reject { |attr| attr.migrate_from_field.nil? }.each do |attr|
    unless self[attr.migrate_from_field].nil?
      @vault_dirty_attrs[attr.name] ||= self[attr.migrate_from_field]
      self[attr.migrate_from_field] = nil
    end
  end
  self.class.vault_attrs.each do |attr|
    next unless @vault_dirty_attrs.has_key? attr.name

    value = @vault_dirty_attrs[attr.name]
    encrypted = Cryptor.encrypt(value, current_key.value)

    self[attr.encrypted_field] = encrypted
    unless attr.digest_field.nil?
      if value.nil?
        self[attr.digest_field] = nil
      else
        self[attr.digest_field] =
          Sequel.blob(Encryption.hmac_digest(current_key.value, value))
      end
    end
  end
  self[self.class.vault_key_field] = current_key.id
  @vault_dirty_attrs = {}
  super
end