Class: KeeperSecretsManager::Dto::KeeperRecord

Inherits:
Object
  • Object
show all
Defined in:
lib/keeper_secrets_manager/dto.rb

Overview

Base class for dynamic record handling

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs = {}) ⇒ KeeperRecord

Returns a new instance of KeeperRecord.



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
# File 'lib/keeper_secrets_manager/dto.rb', line 12

def initialize(attrs = {})
  if attrs.is_a?(Hash)
    # Support both raw API response and user-friendly creation
    @uid = attrs['recordUid'] || attrs['uid'] || attrs[:uid]
    @folder_uid = attrs['folderUid'] || attrs['folder_uid'] || attrs[:folder_uid]
    @revision = attrs['revision'] || attrs[:revision] || 0

    # Handle encrypted data or direct attributes
    if attrs['data']
      data = attrs['data'].is_a?(String) ? JSON.parse(attrs['data']) : attrs['data']
      @title = data['title'] || ''
      @type = data['type'] || 'login'
      @fields = data['fields'] || []
      @custom = data['custom'] || []
      @notes = data['notes'] || ''
    else
      @title = attrs['title'] || attrs[:title] || ''
      @type = attrs['type'] || attrs[:type] || 'login'
      @fields = attrs['fields'] || attrs[:fields] || []
      @custom = attrs['custom'] || attrs[:custom] || []
      @notes = attrs['notes'] || attrs[:notes] || ''
    end

    @files = attrs['files'] || attrs[:files] || []
    @data = attrs
  end

  # Ensure fields are always arrays of hashes
  normalize_fields!
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object

Dynamic field access methods



112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/keeper_secrets_manager/dto.rb', line 112

def method_missing(method, *args, &block)
  method_name = method.to_s

  # Handle setters
  if method_name.end_with?('=')
    field_name = method_name.chomp('=')
    set_field(field_name, args.first)
  # Handle getters
  elsif common_field_types.include?(method_name)
    get_field_value_single(method_name)
  else
    super
  end
end

Instance Attribute Details

#customObject

Returns the value of attribute custom.



9
10
11
# File 'lib/keeper_secrets_manager/dto.rb', line 9

def custom
  @custom
end

#dataObject

Returns the value of attribute data.



9
10
11
# File 'lib/keeper_secrets_manager/dto.rb', line 9

def data
  @data
end

#fieldsObject

Returns the value of attribute fields.



9
10
11
# File 'lib/keeper_secrets_manager/dto.rb', line 9

def fields
  @fields
end

#filesObject

Returns the value of attribute files.



9
10
11
# File 'lib/keeper_secrets_manager/dto.rb', line 9

def files
  @files
end

#folder_uidObject

Returns the value of attribute folder_uid.



9
10
11
# File 'lib/keeper_secrets_manager/dto.rb', line 9

def folder_uid
  @folder_uid
end

#notesObject

Returns the value of attribute notes.



9
10
11
# File 'lib/keeper_secrets_manager/dto.rb', line 9

def notes
  @notes
end

#record_keyObject (readonly)

Internal - stores decrypted record key (bytes) for file upload operations



10
11
12
# File 'lib/keeper_secrets_manager/dto.rb', line 10

def record_key
  @record_key
end

#revisionObject

Returns the value of attribute revision.



9
10
11
# File 'lib/keeper_secrets_manager/dto.rb', line 9

def revision
  @revision
end

#titleObject

Returns the value of attribute title.



9
10
11
# File 'lib/keeper_secrets_manager/dto.rb', line 9

def title
  @title
end

#typeObject

Returns the value of attribute type.



9
10
11
# File 'lib/keeper_secrets_manager/dto.rb', line 9

def type
  @type
end

#uidObject

Returns the value of attribute uid.



9
10
11
# File 'lib/keeper_secrets_manager/dto.rb', line 9

def uid
  @uid
end

Instance Method Details

#get_field(type_or_label) ⇒ Object

Find field by type or label (searches both fields and custom arrays)



63
64
65
66
67
68
69
70
# File 'lib/keeper_secrets_manager/dto.rb', line 63

def get_field(type_or_label)
  # Search in fields first
  field = fields.find { |f| f['type'] == type_or_label || f['label'] == type_or_label }
  return field if field

  # Search in custom fields
  custom.find { |f| f['type'] == type_or_label || f['label'] == type_or_label }
end

#get_field_value(type_or_label) ⇒ Object

Get field value (always returns array)



73
74
75
76
# File 'lib/keeper_secrets_manager/dto.rb', line 73

def get_field_value(type_or_label)
  field = get_field(type_or_label)
  field ? field['value'] || [] : []
end

#get_field_value_single(type_or_label) ⇒ Object

Get single field value (first element)



79
80
81
82
# File 'lib/keeper_secrets_manager/dto.rb', line 79

def get_field_value_single(type_or_label)
  values = get_field_value(type_or_label)
  values.first
end

#respond_to_missing?(method, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


127
128
129
130
# File 'lib/keeper_secrets_manager/dto.rb', line 127

def respond_to_missing?(method, include_private = false)
  method_name = method.to_s.chomp('=')
  common_field_types.include?(method_name) || super
end

#set_field(type, value, label = nil) ⇒ Object

Add or update field



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/keeper_secrets_manager/dto.rb', line 85

def set_field(type, value, label = nil)
  # Ensure value is an array
  value = [value] unless value.is_a?(Array)

  # Find existing field in both arrays
  existing = @fields.find { |f| f['type'] == type || (label && f['label'] == label) }
  existing ||= @custom.find { |f| f['type'] == type || (label && f['label'] == label) }

  if existing
    existing['value'] = value
    existing['label'] = label if label
  else
    new_field = { 'type' => type, 'value' => value }
    new_field['label'] = label if label

    # Decide which array to add to:
    # - If it has a label, it's a custom field
    # - If it's not a common field type, it's likely custom
    if label || !common_field_types.include?(type)
      @custom << new_field
    else
      @fields << new_field
    end
  end
end

#to_hObject

Convert to hash for API submission This should match the structure of the decrypted ‘data’ field from server (does NOT include uid, revision, folder_uid - those are in the outer payload)



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/keeper_secrets_manager/dto.rb', line 46

def to_h
  result = {
    'title' => title,
    'type' => type,
    'fields' => fields
  }

  # Only include custom if it has entries (server doesn't send empty arrays)
  result['custom'] = custom if custom && !custom.empty?

  # Only include notes if present
  result['notes'] = notes if notes && !notes.empty?

  result
end