diff --git a/CHANGELOG.md b/CHANGELOG.md index 8daa0ae..2ad5062 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,31 +1,52 @@ -[//]: # (START/LATEST) +[//]: # "START/LATEST" + # Latest +## Features + +- A user-friendly description of a new feature. {issue-number} + +## Fixes + +- A user-friendly description of a fix. {issue-number} + +## Security + +- A user-friendly description of a security fix. {issue-number} + +--- + +[//]: # "START/v1.0.0" + +# v1.0.0 + +Use the 1Password Connect SDK to leverage 1Password Secrets Automation in your Go applications. + ## Features: -* -## Fixes: -* -## Security: -* + +- Add GetValue method for accessing the value of a field on an item by its label + --- -[//]: # (START/v0.0.2) +[//]: # "START/v0.0.2" # v0.0.2 ## Features: -* Add method for retrieving all items or vaults with a given title (#1) + +- Add method for retrieving all items or vaults with a given title (#1) --- -[//]: # (START/v0.0.1) +[//]: # "START/v0.0.1" # v0.0.1 ## Features: -* 1Password Connect API Client -* 1Password Connect API Models -* Automatic Item field unmarshalling through struct tags -* Integrates with existing open tracing implementations + +- 1Password Connect API Client +- 1Password Connect API Models +- Automatic Item field unmarshalling through struct tags +- Integrates with existing open tracing implementations --- diff --git a/connect/version.go b/connect/version.go index 8996306..ed06b79 100644 --- a/connect/version.go +++ b/connect/version.go @@ -2,4 +2,4 @@ package connect // SDKVersion is the latest Semantic Version of the library // Do not rename this variable without changing the regex in the Makefile -const SDKVersion = "v0.0.2" +const SDKVersion = "1.0.0" diff --git a/onepassword/items.go b/onepassword/items.go index 0e248d5..71bc409 100644 --- a/onepassword/items.go +++ b/onepassword/items.go @@ -2,6 +2,7 @@ package onepassword import ( "encoding/json" + "strings" "time" ) @@ -104,3 +105,54 @@ type ItemField struct { Recipe *GeneratorRecipe `json:"recipe,omitempty"` Entropy float64 `json:"entropy,omitempty"` } + +// Get Retrieve the value of a field on the item by its label. To specify a +// field from a specific section pass in
.. If +// no field matching the selector is found return "". +func (i *Item) GetValue(field string) string { + if i == nil || len(i.Fields) == 0 { + return "" + } + + sectionFilter := false + sectionLabel := "" + fieldLabel := field + if strings.Contains(field, ".") { + parts := strings.Split(field, ".") + + // Test to make sure the . isn't the last character + if len(parts) == 2 { + sectionFilter = true + sectionLabel = parts[0] + fieldLabel = parts[1] + } + } + + for _, f := range i.Fields { + if sectionFilter { + if f.Section != nil { + if sectionLabel != i.SectionLabelForID(f.Section.ID) { + continue + } + } + } + + if fieldLabel == f.Label { + return f.Value + } + } + + return "" +} + +func (i *Item) SectionLabelForID(id string) string { + if i != nil || len(i.Sections) > 0 { + for _, s := range i.Sections { + if s.ID == id { + return s.Label + } + } + } + + return "" +} diff --git a/onepassword/items_test.go b/onepassword/items_test.go new file mode 100644 index 0000000..16830a9 --- /dev/null +++ b/onepassword/items_test.go @@ -0,0 +1,99 @@ +package onepassword + +import ( + "testing" + + "github.com/google/uuid" +) + +var testUsernmae = "user123" +var testPassword = "Password2!" +var testOther = "Test Value" + +func TestItemGetValuePassword(t *testing.T) { + login := testLogin() + + value := login.GetValue("password") + if value != testPassword { + t.Logf("Expected password %q, found %q", testPassword, value) + t.FailNow() + } + + value = login.GetValue(".password") + if value != testPassword { + t.Logf("Expected password %q, found %q", testPassword, value) + t.FailNow() + } +} + +func TestItemGetValueOther(t *testing.T) { + login := testLogin() + + value := login.GetValue("other") + if value != testOther { + t.Logf("Expected other value %q, found %q", testOther, value) + t.FailNow() + } + + value = login.GetValue("example.other") + if value != testOther { + t.Logf("Expected other value %q, found %q", testOther, value) + t.FailNow() + } +} + +func TestItemGetValueMissingField(t *testing.T) { + login := testLogin() + + value := login.GetValue("missing") + if value != "" { + t.Logf("Expected other value %q, found %q", "", value) + t.FailNow() + } +} + +func testLogin() *Item { + sectionUUID := uuid.New().String() + return &Item{ + ID: uuid.New().String(), + Title: "Example Login", + URLs: []ItemURL{ + { + URL: "example.com", + Primary: true, + }, + }, + Category: Login, + Sections: []*ItemSection{ + { + ID: sectionUUID, + Label: "example", + }, + }, + Fields: []*ItemField{ + { + ID: "username", + Type: "STRING", + Purpose: "USERNAME", + Label: "username", + Value: testUsernmae, + }, + { + ID: "password", + Type: "CONCEALED", + Purpose: "PASSWORD", + Label: "password", + Value: testPassword, + }, + { + ID: uuid.New().String(), + Section: &ItemSection{ + ID: sectionUUID, + }, + Type: "STRING", + Label: "other", + Value: testOther, + }, + }, + } +}