adding some funcs for Service. still need two or three more, then Service is done (but untested).

This commit is contained in:
brent s. 2021-11-30 02:33:07 -05:00
parent 3cab98e584
commit 1d9145bcf2
Signed by: bts
GPG Key ID: 8C004C2F93481F6B
5 changed files with 186 additions and 98 deletions

View File

@ -1,10 +1,10 @@
package gosecret

import (
`strings`
`time`
"strings"
"time"

`github.com/godbus/dbus`
"github.com/godbus/dbus"
)

/*
@ -38,8 +38,10 @@ func NewCollection(conn *dbus.Conn, path dbus.ObjectPath) (coll *Collection, err
}

coll = &Collection{
Conn: conn,
Dbus: conn.Object(DbusService, path),
DbusObject: &DbusObject{
Conn: conn,
Dbus: conn.Object(DbusService, path),
},
// lastModified: time.Now(),
}


View File

@ -27,13 +27,13 @@ const (
// DbusServiceCreateCollection is used to create a new Collection via Service.CreateCollection.
DbusServiceCreateCollection string = DbusInterfaceService + ".CreateCollection"

// DbusServiceGetSecrets is used to fetch all Secret / Item items in a given Collection (via Service.GetSecrets).
// DbusServiceGetSecrets is used to fetch multiple Secret values from multiple Item items in a given Collection (via Service.GetSecrets).
DbusServiceGetSecrets string = DbusInterfaceService + ".GetSecrets"

// DbusServiceLock is used by Service.Lock.
DbusServiceLock string = DbusInterfaceService + ".Lock"

// DbusServiceLockService is [FUNCTION UNKNOWN; TODO.]
// DbusServiceLockService is [FUNCTION UNKNOWN/UNDOCUMENTED; TODO.]
DbusServiceLockService string = DbusInterfaceService + ".LockService"

// DbusServiceOpenSession is used by Service.Open.

View File

@ -12,6 +12,8 @@ var (
ErrInvalidProperty error = errors.New("invalid variant type; cannot convert")
// ErrNoDbusConn gets triggered if a connection to Dbus can't be detected.
ErrNoDbusConn error = errors.New("no valid dbus connection")
// ErrMissingPaths gets triggered if one or more Dbus object paths are expected but non/not enough are received.
ErrMissingPaths error = errors.New("one or more Dbus object paths were expected but an insufficient amount were received")
)

/*

View File

@ -14,7 +14,7 @@ func NewService() (service *Service, err error) {
}
svc.Dbus = service.Conn.Object(DbusService, dbus.ObjectPath(DbusPath))

if svc.Session, err = svc.Open(); err != nil {
if svc.Session, _, err = svc.Open(); err != nil {
return
}

@ -23,6 +23,152 @@ func NewService() (service *Service, err error) {
return
}

// Collections returns a slice of Collection items accessible to this Service.
func (s *Service) Collections() (collections []Collection, err error) {

var paths []dbus.ObjectPath
var variant dbus.Variant
var coll *Collection
var errs []error = make([]error, 0)

if variant, err = s.Dbus.GetProperty(DbusServiceCollections); err != nil {
return
}

paths = variant.Value().([]dbus.ObjectPath)

collections = make([]Collection, len(paths))

for idx, path := range paths {
if coll, err = NewCollection(s.Conn, path); err != nil {
// return
errs = append(errs, err)
err = nil
}
collections[idx] = *coll
}
err = NewErrors(err)

return
}

/*
CreateAliasedCollection creates a new Collection (keyring) via a Service with the name specified by label,
aliased to the name specified by alias, and returns the new Collection.
*/
func (s *Service) CreateAliasedCollection(label, alias string) (collection *Collection, err error) {

var variant *dbus.Variant
var path dbus.ObjectPath
var promptPath dbus.ObjectPath
var prompt *Prompt
var props map[string]dbus.Variant = make(map[string]dbus.Variant)

props[DbusCollectionLabel] = dbus.MakeVariant(label)

if err = s.Dbus.Call(
DbusServiceCreateCollection, 0, props, alias,
).Store(&path, &promptPath); err != nil {
return
}

if isPrompt(promptPath) {

prompt = NewPrompt(s.Conn, promptPath)

if variant, err = prompt.Prompt(); err != nil {
return
}

path = variant.Value().(dbus.ObjectPath)
}

collection, err = NewCollection(s.Conn, path)

return
}

/*
CreateCollection creates a new Collection (keyring) via a Service with the name specified by label and returns the new Collection.
It is a *very* thin wrapper around Service.CreateAliasedCollection, but with a blank alias.
*/
func (s *Service) CreateCollection(label string) (collection *Collection, err error) {

collection, err = s.CreateAliasedCollection(label, "")

return
}

/*
GetSecrets allows you to fetch values (Secret) from multiple Item object paths using this Service's Session.
An ErrMissingPaths will be returned for err if itemPaths is nil or empty.
The returned secrets is a map with itemPaths as the keys and their corresponding Secret as the value.
*/
func (s *Service) GetSecrets(itemPaths ...dbus.ObjectPath) (secrets map[dbus.ObjectPath]*Secret, err error) {

if itemPaths == nil || len(itemPaths) == 0 {
err = ErrMissingPaths
return
}

secrets = make(map[dbus.ObjectPath]*Secret, len(itemPaths))

// TODO: trigger a Service.Unlock for any locked items?
/*
// TODO: make any errs in here a MultiError instead.
for _, secretPath := range itemPaths {
if err = s.Dbus.Call(
DbusServiceGetSecrets, 0, secretPath,
).Store(&result); err != nil {
return
}
}
*/
if err = s.Dbus.Call(
DbusServiceGetSecrets, 0, itemPaths,
).Store(&secrets); err != nil {
return
}

return
}

/*
Lock locks an Unlocked Service, Collection, etc.
You can usually get objectPath for the object(s) to unlock via <object>.Dbus.Path().
If objectPaths is nil or empty, the Service's own path will be used.
*/
func (s *Service) Lock(objectPaths ...dbus.ObjectPath) (err error) {

var locked []dbus.ObjectPath
var prompt *Prompt
var resultPath dbus.ObjectPath

if objectPaths == nil || len(objectPaths) == 0 {
objectPaths = []dbus.ObjectPath{s.Dbus.Path()}
}

// TODO: make any errs in here a MultiError instead.
for _, p := range objectPaths {
if err = s.Dbus.Call(
DbusServiceLock, 0, p,
).Store(&locked, &resultPath); err != nil {
return
}

if isPrompt(resultPath) {

prompt = NewPrompt(s.Conn, resultPath)

if _, err = prompt.Prompt(); err != nil {
return
}
}
}

return
}

// Open returns a pointer to a Session from the Service.
func (s *Service) Open() (session *Session, output dbus.Variant, err error) {

@ -43,101 +189,37 @@ func (s *Service) Open() (session *Session, output dbus.Variant, err error) {
return
}

// Collections returns a slice of Collection items accessible to this Service.
func (s *Service) Collections() (collections []Collection, err error) {

var paths []dbus.ObjectPath
var variant dbus.Variant

if variant, err = s.Dbus.GetProperty("org.freedesktop.Secret.Service.Collections"); err != nil {
return
}

paths = variant.Value().([]dbus.ObjectPath)

collections = make([]Collection, len(paths))

for idx, path := range paths {
collections[idx] = *NewCollection(s.Conn, path)
}

return
}

// CreateCollection creates a new Collection (keyring) via a Service with the name specified by label and returns the new Collection.
func (s *Service) CreateCollection(label string) (collection *Collection, err error) {

var variant *dbus.Variant
var path dbus.ObjectPath
var promptPath dbus.ObjectPath
var prompt *Prompt
var props map[string]dbus.Variant = make(map[string]dbus.Variant)

props["org.freedesktop.Secret.Collection.Label"] = dbus.MakeVariant(label)

if err = s.Dbus.Call("org.freedesktop.Secret.Service.CreateCollection", 0, props, "").Store(&path, &promptPath); err != nil {
return
}

if isPrompt(promptPath) {

prompt = NewPrompt(s.Conn, promptPath)

if variant, err = prompt.Prompt(); err != nil {
return
}

path = variant.Value().(dbus.ObjectPath)
}

collection = NewCollection(s.Conn, path)

return
}

// Unlock unlocks a Locked Service.
func (s *Service) Unlock(object DBusObject) (err error) {
/*
Unlock unlocks a Locked Service, Collection, etc.
You can usually get objectPath for the object(s) to unlock via <object>.Dbus.Path().
If objectPaths is nil or empty, the Service's own path will be used.
*/
func (s *Service) Unlock(objectPaths ...dbus.ObjectPath) (err error) {

var unlocked []dbus.ObjectPath
var prompt *Prompt
var promptPath dbus.ObjectPath
var paths []dbus.ObjectPath = []dbus.ObjectPath{object.Path()}
var resultPath dbus.ObjectPath

if err = s.Dbus.Call("org.freedesktop.Secret.Service.Unlock", 0, paths).Store(&unlocked, &promptPath); err != nil {
return
if objectPaths == nil || len(objectPaths) == 0 {
objectPaths = []dbus.ObjectPath{s.Dbus.Path()}
}

if isPrompt(promptPath) {

prompt = NewPrompt(s.Conn, promptPath)

if _, err = prompt.Prompt(); err != nil {
return
}
}

return
}

// Lock locks an Unlocked Service.
func (s *Service) Lock(object DBusObject) (err error) {

var locked []dbus.ObjectPath
var prompt *Prompt
var promptPath dbus.ObjectPath
var paths []dbus.ObjectPath = []dbus.ObjectPath{object.Path()}

if err = s.Dbus.Call("org.freedesktop.Secret.Service.Lock", 0, paths).Store(&locked, &promptPath); err != nil {
return
}

if isPrompt(promptPath) {

prompt = NewPrompt(s.Conn, promptPath)

if _, err = prompt.Prompt(); err != nil {
// TODO: make any errs in here a MultiError instead.
for _, p := range objectPaths {
if err = s.Dbus.Call(
DbusServiceUnlock, 0, p,
).Store(&unlocked, &resultPath); err != nil {
return
}

if isPrompt(resultPath) {

prompt = NewPrompt(s.Conn, resultPath)

if _, err = prompt.Prompt(); err != nil {
return
}
}
}

return

View File

@ -1,15 +1,17 @@
package gosecret

import (
`github.com/godbus/dbus`
"github.com/godbus/dbus"
)

// NewSession returns a pointer to a new Session based on a Dbus connection and a Dbus path.
func NewSession(conn *dbus.Conn, path dbus.ObjectPath) (session *Session) {

session = &Session{
Conn: conn,
Dbus: conn.Object(DbusService, path),
&DbusObject{
Conn: conn,
Dbus: conn.Object(DbusService, path),
},
}

return