Class: Opdotenv::ConnectApiClient

Inherits:
Object
  • Object
show all
Defined in:
lib/opdotenv/connect_api_client.rb

Defined Under Namespace

Classes: ConnectApiError

Constant Summary collapse

NOTES_PLAIN_FIELD =
"notesPlain"
NOTES_PURPOSE =
"NOTES"
SECURE_NOTE_CATEGORY =
"SECURE_NOTE"
LOGIN_CATEGORY =
"LOGIN"

Instance Method Summary collapse

Constructor Details

#initialize(base_url:, access_token:, env: ENV) ⇒ ConnectApiClient

Returns a new instance of ConnectApiClient.



13
14
15
16
17
18
19
# File 'lib/opdotenv/connect_api_client.rb', line 13

def initialize(base_url:, access_token:, env: ENV)
  validate_url(base_url)
  validate_token(access_token)
  @base_url = base_url.chomp("/")
  @access_token = access_token
  @env = env
end

Instance Method Details

#find_item_in_all_vaults(item_title) ⇒ Object



54
55
56
57
58
59
60
61
# File 'lib/opdotenv/connect_api_client.rb', line 54

def find_item_in_all_vaults(item_title)
  vaults = list_vaults
  vaults.each do |v|
    item = item_by_title_in_vault(v["id"], item_title)
    return item if item
  end
  nil
end

#item_create_note(vault:, title:, notes:) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/opdotenv/connect_api_client.rb', line 63

def item_create_note(vault:, title:, notes:)
  vault_id = vault_name_to_id(vault)

  payload = {
    "vault" => {"id" => vault_id},
    "title" => title,
    "category" => SECURE_NOTE_CATEGORY,
    "fields" => [
      {
        "purpose" => NOTES_PURPOSE,
        "value" => notes
      }
    ]
  }

  response = api_request(:post, "/v1/vaults/#{vault_id}/items", payload)
  JSON.pretty_generate(response)
end

#item_create_or_update_fields(vault:, item:, fields: {}) ⇒ Object



82
83
84
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
110
# File 'lib/opdotenv/connect_api_client.rb', line 82

def item_create_or_update_fields(vault:, item:, fields: {})
  vault_id = vault_name_to_id(vault)

  # Try to find existing item by title
  existing = item_by_title_in_vault(vault_id, item)

  if existing
    fields_array = build_patch_fields(existing, fields)
    api_request(:patch, "/v1/vaults/#{vault_id}/items/#{existing["id"]}", fields_array)
  else
    # Create new item
    fields_array = fields.map do |k, v|
      {
        "type" => "CONCEALED",
        "label" => k.to_s,
        "value" => v.to_s
      }
    end

    payload = {
      "vault" => {"id" => vault_id},
      "title" => item,
      "category" => LOGIN_CATEGORY,
      "fields" => fields_array
    }

    api_request(:post, "/v1/vaults/#{vault_id}/items", payload)
  end
end

#item_get(item_title, vault: nil) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/opdotenv/connect_api_client.rb', line 40

def item_get(item_title, vault: nil)
  # If vault not provided, search all vaults (requires listing vaults)
  if vault.nil?
    item = find_item_in_all_vaults(item_title)
    raise ConnectApiError, "Item '#{item_title}' not found" unless item
  else
    vault_id = vault_name_to_id(vault)
    item = item_by_title_in_vault(vault_id, item_title)
    raise ConnectApiError, "Item '#{item_title}' not found in vault '#{vault}'" unless item
  end

  JSON.pretty_generate(item)
end

#read(path) ⇒ Object

Parse op:// style path or connect:// style path op://Vault/Item -> "Vault", item: "Item", field: nil op://Vault/Item/notesPlain -> "Vault", item: "Item", field: "notesPlain" op://Vault/Item/Section/Field -> "Vault", item: "Item", field: "Field"



25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/opdotenv/connect_api_client.rb', line 25

def read(path)
  parsed = parse_path(path)
  item = get_item(parsed[:vault], parsed[:item])

  if parsed[:field]
    # Read specific field
    field = find_field(item, parsed[:field])
    field ? field["value"] : ""
  else
    # Read notesPlain for secure notes
    notes_field = item["fields"]&.find { |f| f["purpose"] == NOTES_PURPOSE || f["label"] == NOTES_PLAIN_FIELD }
    notes_field ? notes_field["value"] : ""
  end
end