Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.16.0
0.17.0
36 changes: 36 additions & 0 deletions entry_credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
)

var ErrEntryNotFound = errors.New("entry not found")
var ErrMultipleEntriesFound = errors.New("multiple entries found")

const (
EntryCredentialType string = "Credential"

Expand Down Expand Up @@ -476,3 +480,35 @@ func (c *EntryCredentialService) GetEntriesWithContext(ctx context.Context, vaul

return credentials, nil
}

// GetByName retrieves a single credential entry by name, path, and subType.
// Returns ErrMultipleEntriesFound if more than one match exists.
func (c *EntryCredentialService) GetByName(vaultId, name, path, subType string) (Entry, error) {
return c.GetByNameWithContext(context.Background(), vaultId, name, path, subType)
}

// GetByNameWithContext retrieves a single credential entry by name, path, and subType.
// Returns ErrMultipleEntriesFound if more than one match exists.
// The provided context can be used to cancel the request.
func (c *EntryCredentialService) GetByNameWithContext(ctx context.Context, vaultId, name, path, subType string) (Entry, error) {
entries, err := c.GetEntriesWithContext(ctx, vaultId, name, path)
if err != nil {
return Entry{}, err
}

var matches []Entry
for _, e := range entries {
if e.SubType == subType {
matches = append(matches, e)
}
}

switch len(matches) {
case 0:
return Entry{}, ErrEntryNotFound
case 1:
return c.GetByIdWithContext(ctx, vaultId, matches[0].Id)
default:
return Entry{}, ErrMultipleEntriesFound
}
}
46 changes: 46 additions & 0 deletions entry_credential_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dvls

import (
"errors"
"strings"
"testing"

Expand Down Expand Up @@ -264,3 +265,48 @@ func Test_GetEntries_Filters(t *testing.T) {
}
t.Log("Cleanup complete")
}

func Test_GetByName(t *testing.T) {
vault := createTestVault(t, "getbyname")
testPath := "go-dvls\\getbyname"

entry := Entry{
VaultId: vault.Id,
Name: "MyCredential",
Path: testPath,
Type: EntryCredentialType,
SubType: EntryCredentialSubTypeDefault,
Data: &EntryCredentialDefaultData{Username: "user", Password: "pass"},
}

id, err := testClient.Entries.Credential.New(entry)
require.NoError(t, err)

// Single match
t.Log("Test: single match by name")
got, err := testClient.Entries.Credential.GetByName(vault.Id, "MyCredential", testPath, EntryCredentialSubTypeDefault)
require.NoError(t, err)
assert.Equal(t, id, got.Id)
assert.Equal(t, "MyCredential", got.Name)

// Not found
t.Log("Test: not found")
_, err = testClient.Entries.Credential.GetByName(vault.Id, "NonExistent", testPath, EntryCredentialSubTypeDefault)
assert.Error(t, err)
assert.False(t, errors.Is(err, ErrMultipleEntriesFound))

// Multiple entries found
t.Log("Test: multiple entries found")
_, err = testClient.Entries.Credential.New(Entry{
VaultId: vault.Id,
Name: "MyCredential",
Path: testPath,
Type: EntryCredentialType,
SubType: EntryCredentialSubTypeDefault,
Data: &EntryCredentialDefaultData{Username: "user2", Password: "pass2"},
})
require.NoError(t, err)

_, err = testClient.Entries.Credential.GetByName(vault.Id, "MyCredential", testPath, EntryCredentialSubTypeDefault)
assert.True(t, errors.Is(err, ErrMultipleEntriesFound))
}