Class: ActiveRecord::Encryption::EncryptedAttributeType
| Relationships & Source Files | |
| Super Chains via Extension / Inclusion / Inheritance | |
|
Class Chain:
|
|
|
Instance Chain:
|
|
| Inherits: |
ActiveModel::Type::Value
|
| Defined in: | activerecord/lib/active_record/encryption/encrypted_attribute_type.rb |
Overview
An ::ActiveModel::Type::Value that encrypts/decrypts strings of text.
This is the central piece that connects the encryption system with encrypts declarations in the
model classes. Whenever you declare an attribute as encrypted, it configures an EncryptedAttributeType
for that attribute.
Class Method Summary
-
.new(scheme:, cast_type: ActiveModel::Type::String.new, previous_type: false, default: nil) ⇒ EncryptedAttributeType
constructor
Options.
::ActiveModel::Type::Value - Inherited
| .new | Initializes a type with three basic configuration settings: precision, limit, and scale. |
Instance Attribute Summary
- #accessor readonly
- #cast_type readonly
- #key_provider readonly
- #previous_schemes readonly
- #scheme readonly
- #support_unencrypted_data? ⇒ Boolean readonly
- #type readonly
- #with_context readonly
- #previous_type? ⇒ Boolean readonly private
- #serialize_with_oldest? ⇒ Boolean readonly private
::ActiveModel::Type::Helpers::Mutable - Included
::ActiveModel::Type::Value - Inherited
| #limit, #precision, #scale, | |
| #binary? | These predicates are not documented, as I need to look further into their use, and see if they can be removed entirely. |
| #mutable?, #serialized? | |
Instance Method Summary
- #cast(value)
- #changed_in_place?(raw_old_value, new_value) ⇒ Boolean
- #deserialize(value)
- #deterministic? ⇒ Boolean
- #downcase? ⇒ Boolean
- #encrypted?(value) ⇒ Boolean
- #fixed? ⇒ Boolean
- #freeze
- #serialize(value)
- #build_previous_types_for(schemes) private
- #clean_text_scheme private
- #database_type_to_text(value) private
- #decrypt(value) private
- #decrypt_as_text(value) private
- #decryption_options private
- #encrypt(value) private
- #encrypt_as_text(value) private
- #encryption_options private
- #encryptor private
- #handle_deserialize_error(error, value) private
- #previous_schemes_including_clean_text private
- #previous_types_without_clean_text private
- #serialize_with_current(value) private
- #serialize_with_oldest(value) readonly private
- #text_to_database_type(value) private
- #try_to_deserialize_with_previous_encrypted_types(value) private
- #previous_types Internal use only
::ActiveModel::Type::Helpers::Mutable - Included
| #cast, | |
| #changed_in_place? |
|
::ActiveModel::Type::Value - Inherited
| #==, #as_json, #as_schema_json, #assert_valid_value, | |
| #cast |
|
| #changed? | Determines whether a value has changed for dirty checking. |
| #changed_in_place? | Determines whether the mutable value has been modified since it was read. |
| #deserialize | Converts a value from database input to the appropriate ruby type. |
| #eql? | Alias for ActiveModel::Type::Value#==. |
| #hash, #init_from_schema_json, | |
| #serializable? | Returns true if this type can convert |
| #serialize | Casts a value from the ruby type to a type that the database knows how to understand. |
| #type | Returns the unique type name as a |
| #cast_value | Convenience method for types which do not need separate type casting behavior for user and database inputs. |
| #force_equality?, #map, | |
| #type_cast_for_schema |
|
| #value_constructed_by_mass_assignment? | |
::ActiveModel::Type::SerializeCastValue - Included
Constructor Details
.new(scheme:, cast_type: ActiveModel::Type::String.new, previous_type: false, default: nil) ⇒ EncryptedAttributeType
Options
:scheme- ASchemewith the encryption properties for this attribute.:cast_type- A type that will be used to serialize (before encrypting) and deserialize (after decrypting). ActiveModel::Type::String by default.
Instance Attribute Details
#accessor (readonly)
[ GitHub ]#cast_type (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 14
attr_reader :scheme, :cast_type
#key_provider (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 16
delegate :key_provider, :downcase?, :deterministic?, :previous_schemes, :with_context, :fixed?, to: :scheme
#previous_schemes (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 16
delegate :key_provider, :downcase?, :deterministic?, :previous_schemes, :with_context, :fixed?, to: :scheme
#previous_type? ⇒ Boolean (readonly, private)
[ GitHub ]
# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 93
def previous_type? @previous_type end
#scheme (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 14
attr_reader :scheme, :cast_type
#serialize_with_oldest? ⇒ Boolean (readonly, private)
[ GitHub ]
# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 135
def serialize_with_oldest? return @serialize_with_oldest if defined?(@serialize_with_oldest) @serialize_with_oldest = fixed? && previous_types_without_clean_text.present? end
#support_unencrypted_data? ⇒ Boolean (readonly)
[ GitHub ]
# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 65
def support_unencrypted_data? scheme.support_unencrypted_data? && !previous_type? end
#type (readonly)
[ GitHub ]#with_context (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 16
delegate :key_provider, :downcase?, :deterministic?, :previous_schemes, :with_context, :fixed?, to: :scheme
Instance Method Details
#build_previous_types_for(schemes) (private)
[ GitHub ]#cast(value)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 32
def cast(value) cast_type.cast(value) end
#changed_in_place?(raw_old_value, new_value) ⇒ Boolean
# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 52
def changed_in_place?(raw_old_value, new_value) old_value = raw_old_value.nil? ? nil : deserialize(raw_old_value) old_value != new_value end
#clean_text_scheme (private)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 177
def clean_text_scheme @clean_text_scheme ||= ActiveRecord::Encryption::Scheme.new(downcase: downcase?, encryptor: ActiveRecord::Encryption::NullEncryptor.new) end
#database_type_to_text(value) (private)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 189
def database_type_to_text(value) if value && cast_type.binary? binary_cast_type = cast_type.serialized? ? cast_type.subtype : cast_type binary_cast_type.deserialize(value) else value end end
#decrypt(value) (private)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 115
def decrypt(value) text_to_database_type decrypt_as_text(database_type_to_text(value)) end
#decrypt_as_text(value) (private)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 97
def decrypt_as_text(value) with_context do unless value.nil? if @default && @default == value value else encryptor.decrypt(value, **) end end end rescue ActiveRecord::Encryption::Errors::Base => error if previous_types_without_clean_text.blank? handle_deserialize_error(error, value) else try_to_deserialize_with_previous_encrypted_types(value) end end
#decryption_options (private)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 173
def { key_provider: key_provider }.compact end
#deserialize(value)
[ GitHub ]
#deterministic? ⇒ Boolean
# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 16
delegate :key_provider, :downcase?, :deterministic?, :previous_schemes, :with_context, :fixed?, to: :scheme
#downcase? ⇒ Boolean
# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 16
delegate :key_provider, :downcase?, :deterministic?, :previous_schemes, :with_context, :fixed?, to: :scheme
#encrypt(value) (private)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 161
def encrypt(value) text_to_database_type encrypt_as_text(value) end
#encrypt_as_text(value) (private)
[ GitHub ]
#encrypted?(value) ⇒ Boolean
# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 48
def encrypted?(value) with_context { encryptor.encrypted? value } end
#encryption_options (private)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 169
def { key_provider: key_provider, cipher_options: { deterministic: deterministic? } }.compact end
#encryptor (private)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 165
def encryptor ActiveRecord::Encryption.encryptor end
#fixed? ⇒ Boolean
# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 16
delegate :key_provider, :downcase?, :deterministic?, :previous_schemes, :with_context, :fixed?, to: :scheme
#freeze
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 69
def freeze serialize_with_oldest? previous_types_without_clean_text previous_types clean_text_scheme super end
#handle_deserialize_error(error, value) (private)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 127
def handle_deserialize_error(error, value) if error.is_a?(Errors::Decryption) && support_unencrypted_data? value else raise error end end
#previous_schemes_including_clean_text (private)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 79
def previous_schemes_including_clean_text previous_schemes.including((clean_text_scheme if support_unencrypted_data?)).compact end
#previous_types
# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 57
def previous_types # :nodoc: @previous_types ||= { support_unencrypted_data? => build_previous_types_for(previous_schemes_including_clean_text), } @previous_types[support_unencrypted_data?] || build_previous_types_for(previous_schemes_including_clean_text) end
#previous_types_without_clean_text (private)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 83
def previous_types_without_clean_text @previous_types_without_clean_text ||= build_previous_types_for(previous_schemes) end
#serialize(value)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 40
def serialize(value) if serialize_with_oldest? serialize_with_oldest(value) else serialize_with_current(value) end end
#serialize_with_current(value) (private)
[ GitHub ]#serialize_with_oldest(value) (readonly, private)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 141
def serialize_with_oldest(value) previous_types.first.serialize(value) end
#text_to_database_type(value) (private)
[ GitHub ]#try_to_deserialize_with_previous_encrypted_types(value) (private)
[ GitHub ]# File 'activerecord/lib/active_record/encryption/encrypted_attribute_type.rb', line 119
def try_to_deserialize_with_previous_encrypted_types(value) previous_types.each.with_index do |type, index| break type.deserialize(value) rescue ActiveRecord::Encryption::Errors::Base => error handle_deserialize_error(error, value) if index == previous_types.length - 1 end end