File: properties.rb

package info (click to toggle)
rails 2%3A7.2.2.1%2Bdfsg-7
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 43,352 kB
  • sloc: ruby: 349,799; javascript: 30,703; yacc: 46; sql: 43; sh: 29; makefile: 27
file content (76 lines) | stat: -rw-r--r-- 2,355 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# frozen_string_literal: true

module ActiveRecord
  module Encryption
    # This is a wrapper for a hash of encryption properties. It is used by
    # +Key+ (public tags) and +Message+ (headers).
    #
    # Since properties are serialized in messages, it is important for storage
    # efficiency to keep their keys as short as possible. It defines accessors
    # for common properties that will keep these keys very short while exposing
    # a readable name.
    #
    #   message.headers.encrypted_data_key # instead of message.headers[:k]
    #
    # See +Properties::DEFAULT_PROPERTIES+, Key, Message
    class Properties
      ALLOWED_VALUE_CLASSES = [String, ActiveRecord::Encryption::Message, Numeric, Integer, Float, BigDecimal, TrueClass, FalseClass, Symbol, NilClass]

      delegate_missing_to :data
      delegate :==, :[], :each, :key?, to: :data

      # For each entry it generates an accessor exposing the full name
      DEFAULT_PROPERTIES = {
        encrypted_data_key: "k",
        encrypted_data_key_id: "i",
        compressed: "c",
        iv: "iv",
        auth_tag: "at",
        encoding: "e"
      }

      DEFAULT_PROPERTIES.each do |name, key|
        define_method name do
          self[key.to_sym]
        end

        define_method "#{name}=" do |value|
          self[key.to_sym] = value
        end
      end

      def initialize(initial_properties = {})
        @data = {}
        add(initial_properties)
      end

      # Set a value for a given key
      #
      # It will raise an +EncryptedContentIntegrity+ if the value exists
      def []=(key, value)
        raise Errors::EncryptedContentIntegrity, "Properties can't be overridden: #{key}" if key?(key)
        validate_value_type(value)
        data[key] = value
      end

      def validate_value_type(value)
        unless ALLOWED_VALUE_CLASSES.include?(value.class) || ALLOWED_VALUE_CLASSES.any? { |klass| value.is_a?(klass) }
          raise ActiveRecord::Encryption::Errors::ForbiddenClass, "Can't store a #{value.class}, only properties of type #{ALLOWED_VALUE_CLASSES.inspect} are allowed"
        end
      end

      def add(other_properties)
        other_properties.each do |key, value|
          self[key.to_sym] = value
        end
      end

      def to_h
        data
      end

      private
        attr_reader :data
    end
  end
end