Class: ActiveJsonModel::ActiveRecordEncryptedType

Inherits:
ActiveRecordType
  • Object
show all
Defined in:
lib/active_json_model/active_record_encrypted_type.rb

Overview

Allows instances of ActiveJsonModels to be serialized JSONB columns for ActiveRecord models.

class Credentials < ::ActiveJsonModel
  def self.encrypted_attribute_type
    ActiveRecordEncryptedType.new(Credentials)
  end
end

class User < ActiveRecord::Base
  attribute :credentials, Credentials.encrypted_attribute_type
end

Alternatively, the type can be registered ahead of time:

# config/initializers/types.rb
ActiveRecord::Type.register(:credentials_encrypted_type, Credentials.encrypted_attribute_type)

Then the custom type can be used as:

class User < ActiveRecord::Base
  attribute :credentials, :credentials_encrypted_type
end

Instance Method Summary collapse

Methods inherited from ActiveRecordType

#cast, #initialize

Constructor Details

This class inherits a constructor from ActiveJsonModel::ActiveRecordType

Instance Method Details

#changed_in_place?(raw_old_value, new_value) ⇒ Boolean

Override to handle issues comparing hashes encoded as strings, where the actual order doesn’t matter.

Returns:

  • (Boolean)


69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/active_json_model/active_record_encrypted_type.rb', line 69

def changed_in_place?(raw_old_value, new_value)
  if raw_old_value.nil? || new_value.nil?
    raw_old_value == new_value
  else
    # Decode is necessary because postgres can change the order of hashes. Round-tripping on the new value side
    # is to handle any dates that might be rendered as strings.
    decoded_raw = ::ActiveSupport::JSON.decode(raw_old_value)
    round_tripped_new = ::ActiveSupport::JSON.decode(new_value.class.dump(new_value))

    decoded_raw != round_tripped_new
  end
end

#deserialize(value) ⇒ Object



41
42
43
44
45
46
47
48
# File 'lib/active_json_model/active_record_encrypted_type.rb', line 41

def deserialize(value)
  if String === value
    decoded = SymmetricEncryption.decrypt(value, type: :json) rescue nil
    @clazz.load(decoded)
  else
    super
  end
end

#serialize(value) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/active_json_model/active_record_encrypted_type.rb', line 50

def serialize(value)
  if value.respond_to?(:dump_to_json)
    SymmetricEncryption.encrypt(
      value.dump_to_json,
      random_iv: true,
      type: :json
    )
  elsif ::Hash === value ||  ::HashWithIndifferentAccess === value || ::Array === value
    SymmetricEncryption.encrypt(
      value,
      random_iv: true,
      type: :json
    )
  else
    super
  end
end

#typeObject



37
38
39
# File 'lib/active_json_model/active_record_encrypted_type.rb', line 37

def type
  :string
end