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.17.0
0.18.0
17 changes: 9 additions & 8 deletions entries.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,16 @@ type entryListRawResponse struct {
}

// getEntriesOptions contains optional filters for listing entries.
type getEntriesOptions struct {
Name string
Path string
// A nil value means the filter is not applied.
type GetEntriesOptions struct {
Name *string
Path *string
}

// getEntries returns a list of entries from a vault with optional filters.
// Entries with unsupported types are skipped.
// This function handles pagination automatically and returns all entries across all pages.
func (c *Client) getEntries(ctx context.Context, vaultId string, opts getEntriesOptions) ([]Entry, error) {
func (c *Client) getEntries(ctx context.Context, vaultId string, opts GetEntriesOptions) ([]Entry, error) {
if vaultId == "" {
return nil, fmt.Errorf("vaultId is required")
}
Expand All @@ -202,11 +203,11 @@ func (c *Client) getEntries(ctx context.Context, vaultId string, opts getEntries

for {
q := parsedUrl.Query()
if opts.Name != "" {
q.Set("name", opts.Name)
if opts.Name != nil {
q.Set("name", *opts.Name)
}
if opts.Path != "" {
q.Set("path", opts.Path)
if opts.Path != nil {
q.Set("path", *opts.Path)
}
q.Set("page", fmt.Sprintf("%d", currentPage))
parsedUrl.RawQuery = q.Encode()
Expand Down
36 changes: 22 additions & 14 deletions entry_credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,19 +452,19 @@ func (c *EntryCredentialService) DeleteByIdWithContext(ctx context.Context, vaul
return nil
}

// GetEntries returns a list of credential entries from a vault with optional name and path filters.
// GetEntries returns a list of credential entries from a vault with optional filters.
// Note: The API does not support filtering by entry type, so all entries are fetched and filtered client-side.
func (c *EntryCredentialService) GetEntries(vaultId, name, path string) ([]Entry, error) {
return c.GetEntriesWithContext(context.Background(), vaultId, name, path)
func (c *EntryCredentialService) GetEntries(vaultId string, opts GetEntriesOptions) ([]Entry, error) {
return c.GetEntriesWithContext(context.Background(), vaultId, opts)
}
Comment on lines +455 to 459

Copilot AI Feb 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetEntriesOptions is a package-level exported type and is also consumed by EntryFolderService, but it’s declared in entry_credential.go. To improve API discoverability (GoDoc) and keep shared types in a neutral place, consider moving it to entries.go or a dedicated shared options file (e.g., entries_options.go).

Copilot uses AI. Check for mistakes.

// GetEntriesWithContext returns a list of credential entries from a vault with optional name and path filters.
// GetEntriesWithContext returns a list of credential entries from a vault with optional filters.
// The provided context can be used to cancel the request.
// Note: The API does not support filtering by entry type, so all entries are fetched and filtered client-side.
func (c *EntryCredentialService) GetEntriesWithContext(ctx context.Context, vaultId, name, path string) ([]Entry, error) {
entries, err := c.client.getEntries(ctx, vaultId, getEntriesOptions{
Name: name,
Path: path,
func (c *EntryCredentialService) GetEntriesWithContext(ctx context.Context, vaultId string, opts GetEntriesOptions) ([]Entry, error) {
entries, err := c.client.getEntries(ctx, vaultId, GetEntriesOptions{
Name: opts.Name,
Path: opts.Path,
})
if err != nil {
return nil, err
Expand All @@ -481,17 +481,25 @@ func (c *EntryCredentialService) GetEntriesWithContext(ctx context.Context, vaul
return credentials, nil
}

// GetByName retrieves a single credential entry by name, path, and subType.
// GetByNameOptions contains optional filters for GetByName.
// A nil field means the filter is not applied.
type GetByNameOptions struct {
Path *string
}

// GetByName retrieves a single credential entry by name, subType, and optional filters.
// Returns ErrEntryNotFound if no match exists.
// 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)
func (c *EntryCredentialService) GetByName(vaultId, name, subType string, opts GetByNameOptions) (Entry, error) {
return c.GetByNameWithContext(context.Background(), vaultId, name, subType, opts)
}

// GetByNameWithContext retrieves a single credential entry by name, path, and subType.
// GetByNameWithContext retrieves a single credential entry by name, subType, and optional filters.
// Returns ErrEntryNotFound if no match exists.
// 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)
func (c *EntryCredentialService) GetByNameWithContext(ctx context.Context, vaultId, name, subType string, opts GetByNameOptions) (Entry, error) {
entries, err := c.GetEntriesWithContext(ctx, vaultId, GetEntriesOptions{Name: &name, Path: opts.Path})
if err != nil {
return Entry{}, err
}
Expand Down
18 changes: 11 additions & 7 deletions entry_credential_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,16 +226,20 @@ func Test_GetEntries_Filters(t *testing.T) {
t.Logf("Created entry %q with ID: %s", entry.Name, id)
}

serverName := "Server"
serverBackupName := "Server Backup"
nonExistentName := "Non Existent Entry"

// Test 1: GetEntries with path filter should return all 3 entries
t.Log("Test 1: GetEntries with path filter")
entries, err := testClient.Entries.Credential.GetEntries(vault.Id, "", testPath)
entries, err := testClient.Entries.Credential.GetEntries(vault.Id, GetEntriesOptions{Path: &testPath})
require.NoError(t, err, "GetEntries failed")
assert.Len(t, entries, 3, "Expected 3 entries with path filter")
t.Logf("Found %d entries in path %q", len(entries), testPath)

// Test 2: GetEntries with exact name match - should return only "Server", not "Server Backup" or "Server Production"
t.Log("Test 2: GetEntries with exact name match")
entries, err = testClient.Entries.Credential.GetEntries(vault.Id, "Server", "")
entries, err = testClient.Entries.Credential.GetEntries(vault.Id, GetEntriesOptions{Name: &serverName})
require.NoError(t, err, "GetEntries with exact name failed")
assert.Len(t, entries, 1, "Expected 1 entry with exact name match")
if len(entries) > 0 {
Expand All @@ -245,14 +249,14 @@ func Test_GetEntries_Filters(t *testing.T) {

// Test 3: GetEntries with name and path filter
t.Log("Test 3: GetEntries with name and path filter")
entries, err = testClient.Entries.Credential.GetEntries(vault.Id, "Server Backup", testPath)
entries, err = testClient.Entries.Credential.GetEntries(vault.Id, GetEntriesOptions{Name: &serverBackupName, Path: &testPath})
require.NoError(t, err, "GetEntries with name and path filter failed")
assert.Len(t, entries, 1, "Expected 1 entry with name and path filter")
t.Logf("Found %d entry with combined filters", len(entries))

// Test 4: GetEntries with non-existent name should return empty
t.Log("Test 4: GetEntries with non-existent name")
entries, err = testClient.Entries.Credential.GetEntries(vault.Id, "Non Existent Entry", testPath)
entries, err = testClient.Entries.Credential.GetEntries(vault.Id, GetEntriesOptions{Name: &nonExistentName, Path: &testPath})
require.NoError(t, err, "GetEntries with non-existent name failed")
assert.Empty(t, entries, "Expected 0 entries for non-existent name")
t.Logf("Correctly returned %d entries for non-existent name", len(entries))
Expand Down Expand Up @@ -284,14 +288,14 @@ func Test_GetByName(t *testing.T) {

// Single match
t.Log("Test: single match by name")
got, err := testClient.Entries.Credential.GetByName(vault.Id, "MyCredential", testPath, EntryCredentialSubTypeDefault)
got, err := testClient.Entries.Credential.GetByName(vault.Id, "MyCredential", EntryCredentialSubTypeDefault, GetByNameOptions{Path: &testPath})
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)
_, err = testClient.Entries.Credential.GetByName(vault.Id, "NonExistent", EntryCredentialSubTypeDefault, GetByNameOptions{Path: &testPath})
assert.Error(t, err)
assert.False(t, errors.Is(err, ErrMultipleEntriesFound))

Expand All @@ -307,6 +311,6 @@ func Test_GetByName(t *testing.T) {
})
require.NoError(t, err)

_, err = testClient.Entries.Credential.GetByName(vault.Id, "MyCredential", testPath, EntryCredentialSubTypeDefault)
_, err = testClient.Entries.Credential.GetByName(vault.Id, "MyCredential", EntryCredentialSubTypeDefault, GetByNameOptions{Path: &testPath})
assert.True(t, errors.Is(err, ErrMultipleEntriesFound))
}
16 changes: 8 additions & 8 deletions entry_folder.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,19 +266,19 @@ func (c *EntryFolderService) DeleteByIdWithContext(ctx context.Context, vaultId
return nil
}

// GetEntries returns a list of folder entries from a vault with optional name and path filters.
// GetEntries returns a list of folder entries from a vault with optional filters.

Copilot AI Feb 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetEntriesOptions is used by both EntryCredentialService and EntryFolderService, but the type is declared in entry_credential.go. That makes the Folder API harder to discover in GoDoc and can confuse readers who only look at entry_folder.go. Consider moving GetEntriesOptions to a more neutral/shared location (e.g., entries.go or a new entries_options.go) and/or referencing it explicitly in the Folder GetEntries doc comment so the public API is self-describing.

Suggested change
// GetEntries returns a list of folder entries from a vault with optional filters.
// GetEntries returns a list of folder entries from a vault with optional filters.
// See GetEntriesOptions for the available filter fields.

Copilot uses AI. Check for mistakes.
// Note: The API does not support filtering by entry type, so all entries are fetched and filtered client-side.
func (c *EntryFolderService) GetEntries(vaultId, name, path string) ([]Entry, error) {
return c.GetEntriesWithContext(context.Background(), vaultId, name, path)
func (c *EntryFolderService) GetEntries(vaultId string, opts GetEntriesOptions) ([]Entry, error) {
return c.GetEntriesWithContext(context.Background(), vaultId, opts)
}

// GetEntriesWithContext returns a list of folder entries from a vault with optional name and path filters.
// GetEntriesWithContext returns a list of folder entries from a vault with optional filters.
// The provided context can be used to cancel the request.
// Note: The API does not support filtering by entry type, so all entries are fetched and filtered client-side.
func (c *EntryFolderService) GetEntriesWithContext(ctx context.Context, vaultId, name, path string) ([]Entry, error) {
entries, err := c.client.getEntries(ctx, vaultId, getEntriesOptions{
Name: name,
Path: path,
func (c *EntryFolderService) GetEntriesWithContext(ctx context.Context, vaultId string, opts GetEntriesOptions) ([]Entry, error) {
entries, err := c.client.getEntries(ctx, vaultId, GetEntriesOptions{
Name: opts.Name,
Path: opts.Path,
})
if err != nil {
return nil, err
Expand Down
12 changes: 8 additions & 4 deletions entry_folder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,14 @@ func Test_GetFolderEntries_Filters(t *testing.T) {
t.Logf("Created folder entry %q with ID: %s", entry.Name, id)
}

databaseName := "Database"
databaseBackupName := "Database Backup"
nonExistentName := "Non Existent Folder"

// Test 1: GetEntries with path filter should return at least our 3 folders
// Note: DVLS may auto-create parent folders, so we check for >= 3
t.Log("Test 1: GetEntries with path filter")
entries, err := testClient.Entries.Folder.GetEntries(vault.Id, "", testPath)
entries, err := testClient.Entries.Folder.GetEntries(vault.Id, GetEntriesOptions{Path: &testPath})
require.NoError(t, err, "GetEntries failed")
assert.GreaterOrEqual(t, len(entries), 3, "Expected at least 3 folder entries with path filter")

Expand All @@ -260,7 +264,7 @@ func Test_GetFolderEntries_Filters(t *testing.T) {

// Test 2: GetEntries with exact name match - should return only "Database"
t.Log("Test 2: GetEntries with exact name match")
entries, err = testClient.Entries.Folder.GetEntries(vault.Id, "Database", "")
entries, err = testClient.Entries.Folder.GetEntries(vault.Id, GetEntriesOptions{Name: &databaseName})
require.NoError(t, err, "GetEntries with exact name failed")
assert.Len(t, entries, 1, "Expected 1 folder entry with exact name match")
if len(entries) > 0 {
Expand All @@ -270,14 +274,14 @@ func Test_GetFolderEntries_Filters(t *testing.T) {

// Test 3: GetEntries with name and path filter
t.Log("Test 3: GetEntries with name and path filter")
entries, err = testClient.Entries.Folder.GetEntries(vault.Id, "Database Backup", testPath)
entries, err = testClient.Entries.Folder.GetEntries(vault.Id, GetEntriesOptions{Name: &databaseBackupName, Path: &testPath})
require.NoError(t, err, "GetEntries with name and path filter failed")
assert.Len(t, entries, 1, "Expected 1 folder entry with name and path filter")
t.Logf("Found %d folder entry with combined filters", len(entries))

// Test 4: GetEntries with non-existent name should return empty
t.Log("Test 4: GetEntries with non-existent name")
entries, err = testClient.Entries.Folder.GetEntries(vault.Id, "Non Existent Folder", testPath)
entries, err = testClient.Entries.Folder.GetEntries(vault.Id, GetEntriesOptions{Name: &nonExistentName, Path: &testPath})
require.NoError(t, err, "GetEntries with non-existent name failed")
assert.Empty(t, entries, "Expected 0 folder entries for non-existent name")
t.Logf("Correctly returned %d folder entries for non-existent name", len(entries))
Expand Down