class ActiveRecord::Encryption::MessageSerializer
A message serializer that serializes Messages
with JSON.
The generated structure is pretty simple:
{ p: <payload>, h: { header1: value1, header2: value2, ... } }
Both the payload and the header values are encoded with Base64 to prevent JSON parsing errors and encoding issues when storing the resulting serialized data.
Public Instance Methods
dump(message)
click to toggle source
# File lib/active_record/encryption/message_serializer.rb, line 29 def dump(message) raise ActiveRecord::Encryption::Errors::ForbiddenClass unless message.is_a?(ActiveRecord::Encryption::Message) JSON.dump message_to_json(message) end
load(serialized_content)
click to toggle source
# File lib/active_record/encryption/message_serializer.rb, line 22 def load(serialized_content) data = JSON.parse(serialized_content) parse_message(data, 1) rescue JSON::ParserError raise ActiveRecord::Encryption::Errors::Encoding end
Private Instance Methods
decode_if_needed(value)
click to toggle source
# File lib/active_record/encryption/message_serializer.rb, line 79 def decode_if_needed(value) if value.is_a?(String) ::Base64.strict_decode64(value) else value end rescue ArgumentError, TypeError raise Errors::Encoding end
encode_if_needed(value)
click to toggle source
# File lib/active_record/encryption/message_serializer.rb, line 71 def encode_if_needed(value) if value.is_a?(String) ::Base64.strict_encode64 value else value end end
headers_to_json(headers)
click to toggle source
# File lib/active_record/encryption/message_serializer.rb, line 65 def headers_to_json(headers) headers.transform_values do |value| value.is_a?(ActiveRecord::Encryption::Message) ? message_to_json(value) : encode_if_needed(value) end end
message_to_json(message)
click to toggle source
# File lib/active_record/encryption/message_serializer.rb, line 58 def message_to_json(message) { p: encode_if_needed(message.payload), h: headers_to_json(message.headers) } end
parse_message(data, level)
click to toggle source
# File lib/active_record/encryption/message_serializer.rb, line 35 def parse_message(data, level) validate_message_data_format(data, level) ActiveRecord::Encryption::Message.new(payload: decode_if_needed(data["p"]), headers: parse_properties(data["h"], level)) end
parse_properties(headers, level)
click to toggle source
# File lib/active_record/encryption/message_serializer.rb, line 50 def parse_properties(headers, level) ActiveRecord::Encryption::Properties.new.tap do |properties| headers&.each do |key, value| properties[key] = value.is_a?(Hash) ? parse_message(value, level + 1) : decode_if_needed(value) end end end
validate_message_data_format(data, level)
click to toggle source
# File lib/active_record/encryption/message_serializer.rb, line 40 def validate_message_data_format(data, level) if level > 2 raise ActiveRecord::Encryption::Errors::Decryption, "More than one level of hash nesting in headers is not supported" end unless data.is_a?(Hash) && data.has_key?("p") raise ActiveRecord::Encryption::Errors::Decryption, "Invalid data format: hash without payload" end end