2021-11-21 23:05:13 -05:00
package gosecret
2021-11-21 18:07:52 -05:00
import (
2021-12-04 19:38:26 -05:00
` strings `
2021-11-30 02:33:07 -05:00
"time"
2021-11-27 02:24:22 -05:00
2021-12-06 03:24:55 -05:00
` github.com/godbus/dbus/v5 `
2021-11-21 18:07:52 -05:00
)
2021-11-27 02:24:22 -05:00
/ *
2021-12-04 19:38:26 -05:00
NewCollection returns a pointer to a Collection based on a Service and a Dbus path .
You will almost always want to use Service . GetCollection instead .
2021-11-27 02:24:22 -05:00
* /
2021-12-04 19:38:26 -05:00
func NewCollection ( service * Service , path dbus . ObjectPath ) ( coll * Collection , err error ) {
2021-11-27 02:24:22 -05:00
2021-12-04 19:38:26 -05:00
var splitPath [ ] string
2021-11-27 02:24:22 -05:00
2021-12-04 19:38:26 -05:00
if service == nil {
2021-11-21 23:12:25 -05:00
err = ErrNoDbusConn
}
2021-12-04 19:38:26 -05:00
if _ , err = validConnPath ( service . Conn , path ) ; err != nil {
2021-11-21 23:12:25 -05:00
return
}
2021-11-21 18:07:52 -05:00
coll = & Collection {
2021-11-30 02:33:07 -05:00
DbusObject : & DbusObject {
2021-12-04 19:38:26 -05:00
Conn : service . Conn ,
Dbus : service . Conn . Object ( DbusService , path ) ,
2021-11-30 02:33:07 -05:00
} ,
2021-12-06 03:24:55 -05:00
service : service ,
2021-11-27 02:24:22 -05:00
// lastModified: time.Now(),
2021-11-21 18:07:52 -05:00
}
2021-12-06 03:24:55 -05:00
splitPath = strings . Split ( string ( coll . Dbus . Path ( ) ) , "/" )
2021-12-04 19:38:26 -05:00
coll . name = splitPath [ len ( splitPath ) - 1 ]
2021-11-27 02:24:22 -05:00
_ , _ , err = coll . Modified ( )
2021-11-21 18:07:52 -05:00
return
}
2021-12-12 02:29:29 -05:00
// CreateItem returns a pointer to an Item based on a label, some attributes, a Secret, and whether any existing secret with the same label should be replaced or not.
func ( c * Collection ) CreateItem ( label string , attrs map [ string ] string , secret * Secret , replace bool ) ( item * Item , err error ) {
2021-11-21 18:07:52 -05:00
2021-12-12 02:29:29 -05:00
var prompt * Prompt
var path dbus . ObjectPath
var promptPath dbus . ObjectPath
var variant * dbus . Variant
var props map [ string ] dbus . Variant = make ( map [ string ] dbus . Variant )
2021-11-21 18:07:52 -05:00
2021-12-12 02:29:29 -05:00
props [ DbusItemLabel ] = dbus . MakeVariant ( label )
props [ DbusItemAttributes ] = dbus . MakeVariant ( attrs )
if err = c . Dbus . Call (
DbusCollectionCreateItem , 0 , props , secret , replace ,
) . Store ( & path , & promptPath ) ; err != nil {
2021-11-21 18:07:52 -05:00
return
}
2021-12-12 02:29:29 -05:00
if isPrompt ( promptPath ) {
prompt = NewPrompt ( c . Conn , promptPath )
2021-11-21 18:07:52 -05:00
2021-12-12 02:29:29 -05:00
if variant , err = prompt . Prompt ( ) ; err != nil {
return
2021-12-04 19:38:26 -05:00
}
2021-12-12 02:29:29 -05:00
path = variant . Value ( ) . ( dbus . ObjectPath )
2021-11-21 18:07:52 -05:00
}
2021-12-12 02:29:29 -05:00
item , err = NewItem ( c , path )
2021-11-21 18:07:52 -05:00
return
}
2021-12-12 02:29:29 -05:00
/ *
Delete removes a Collection .
While * technically * not necessary , it is recommended that you iterate through
Collection . Items and do an Item . Delete for each item * before * calling Collection . Delete ;
the item paths are cached as "orphaned paths" in Dbus otherwise if not deleted before deleting
their Collection . They should clear on a reboot or restart of Dbus ( but rebooting Dbus on a system in use is ... troublesome ) .
* /
2021-11-21 18:07:52 -05:00
func ( c * Collection ) Delete ( ) ( err error ) {
var promptPath dbus . ObjectPath
var prompt * Prompt
2021-11-21 23:12:25 -05:00
if err = c . Dbus . Call ( DbusCollectionDelete , 0 ) . Store ( & promptPath ) ; err != nil {
2021-11-21 18:07:52 -05:00
return
}
if isPrompt ( promptPath ) {
prompt = NewPrompt ( c . Conn , promptPath )
if _ , err = prompt . Prompt ( ) ; err != nil {
return
}
}
return
}
2021-12-12 02:29:29 -05:00
// Items returns a slice of Item pointers in the Collection.
func ( c * Collection ) Items ( ) ( items [ ] * Item , err error ) {
2021-11-21 18:07:52 -05:00
var paths [ ] dbus . ObjectPath
2021-12-12 02:29:29 -05:00
var item * Item
var variant dbus . Variant
2021-12-04 19:38:26 -05:00
var errs [ ] error = make ( [ ] error , 0 )
2021-11-21 18:07:52 -05:00
2021-12-12 02:29:29 -05:00
if variant , err = c . Dbus . GetProperty ( DbusCollectionItems ) ; err != nil {
2021-11-21 18:07:52 -05:00
return
}
2021-12-12 02:29:29 -05:00
paths = variant . Value ( ) . ( [ ] dbus . ObjectPath )
2021-12-04 19:38:26 -05:00
items = make ( [ ] * Item , len ( paths ) )
2021-11-21 18:07:52 -05:00
for idx , path := range paths {
2021-12-12 02:29:29 -05:00
if item , err = NewItem ( c , path ) ; err != nil {
2021-12-04 19:38:26 -05:00
errs = append ( errs , err )
err = nil
continue
}
2021-12-12 02:29:29 -05:00
items [ idx ] = item
2021-11-21 18:07:52 -05:00
}
2021-12-04 19:38:26 -05:00
err = NewErrors ( err )
2021-11-21 18:07:52 -05:00
return
}
2021-12-12 02:29:29 -05:00
// Label returns the Collection label (name).
func ( c * Collection ) Label ( ) ( label string , err error ) {
2021-11-21 18:07:52 -05:00
2021-12-12 02:29:29 -05:00
var variant dbus . Variant
2021-11-21 18:07:52 -05:00
2021-12-12 02:29:29 -05:00
if variant , err = c . Dbus . GetProperty ( DbusCollectionLabel ) ; err != nil {
2021-11-21 18:07:52 -05:00
return
}
2021-12-12 02:29:29 -05:00
label = variant . Value ( ) . ( string )
2021-11-21 18:07:52 -05:00
2021-12-12 02:29:29 -05:00
if label != c . name {
c . name = label
2021-11-21 18:07:52 -05:00
}
return
}
2021-11-27 02:24:22 -05:00
// Locked indicates if a Collection is locked (true) or unlocked (false).
2021-11-21 18:07:52 -05:00
func ( c * Collection ) Locked ( ) ( isLocked bool , err error ) {
var variant dbus . Variant
2021-12-04 19:38:26 -05:00
if variant , err = c . Dbus . GetProperty ( DbusCollectionLocked ) ; err != nil {
2021-11-21 18:07:52 -05:00
isLocked = true
return
}
isLocked = variant . Value ( ) . ( bool )
return
}
2021-11-27 02:24:22 -05:00
2021-12-12 02:29:29 -05:00
// Relabel modifies the Collection's label in Dbus.
func ( c * Collection ) Relabel ( newLabel string ) ( err error ) {
2021-11-27 02:24:22 -05:00
2021-12-12 02:29:29 -05:00
var variant dbus . Variant = dbus . MakeVariant ( newLabel )
2021-12-04 19:38:26 -05:00
2021-12-12 02:29:29 -05:00
if err = c . Dbus . SetProperty ( DbusCollectionLabel , variant ) ; err != nil {
2021-12-04 19:38:26 -05:00
return
}
2021-11-27 02:24:22 -05:00
return
}
2021-12-12 02:29:29 -05:00
/ *
SearchItems searches a Collection for a matching profile string .
It ' s mostly a carry - over from go - libsecret , and is here for convenience .
I promise it ' s not useful for any other implementation / storage of SecretService whatsoever .
* /
func ( c * Collection ) SearchItems ( profile string ) ( items [ ] * Item , err error ) {
2021-12-07 02:56:15 -05:00
2021-12-12 02:29:29 -05:00
var paths [ ] dbus . ObjectPath
var errs [ ] error = make ( [ ] error , 0 )
var attrs map [ string ] string = make ( map [ string ] string , 0 )
attrs [ "profile" ] = profile
2021-12-07 02:56:15 -05:00
2021-12-12 02:29:29 -05:00
if err = c . Dbus . Call (
DbusCollectionSearchItems , 0 , attrs ,
) . Store ( & paths ) ; err != nil {
2021-12-07 02:56:15 -05:00
return
}
2021-12-12 02:29:29 -05:00
items = make ( [ ] * Item , len ( paths ) )
for idx , path := range paths {
if items [ idx ] , err = NewItem ( c , path ) ; err != nil {
errs = append ( errs , err )
err = nil
continue
}
}
err = NewErrors ( err )
2021-12-07 02:56:15 -05:00
return
}
2021-11-27 02:24:22 -05:00
// Created returns the time.Time of when a Collection was created.
func ( c * Collection ) Created ( ) ( created time . Time , err error ) {
2021-12-04 19:38:26 -05:00
var variant dbus . Variant
var timeInt uint64
if variant , err = c . Dbus . GetProperty ( DbusCollectionCreated ) ; err != nil {
return
}
timeInt = variant . Value ( ) . ( uint64 )
created = time . Unix ( int64 ( timeInt ) , 0 )
2021-11-27 02:24:22 -05:00
return
}
/ *
Modified returns the time . Time of when a Collection was last modified along with a boolean
that indicates if the collection has changed since the last call of Collection . Modified .
Note that when calling NewCollection , the internal library - tracked modification
2021-12-04 19:38:26 -05:00
time ( Collection . lastModified ) will be set to the latest modification time of the Collection
itself as reported by Dbus rather than the time that NewCollection was called .
2021-11-27 02:24:22 -05:00
* /
func ( c * Collection ) Modified ( ) ( modified time . Time , isChanged bool , err error ) {
2021-12-04 19:38:26 -05:00
var variant dbus . Variant
var timeInt uint64
if variant , err = c . Dbus . GetProperty ( DbusCollectionModified ) ; err != nil {
return
}
timeInt = variant . Value ( ) . ( uint64 )
2021-11-27 02:24:22 -05:00
2021-12-04 19:38:26 -05:00
modified = time . Unix ( int64 ( timeInt ) , 0 )
if ! c . lastModifiedSet {
// It's "nil", so set it to modified. We can't check for a zero-value in case Dbus has it as a zero-value.
2021-11-27 02:24:22 -05:00
c . lastModified = modified
2021-12-04 19:38:26 -05:00
c . lastModifiedSet = true
2021-11-27 02:24:22 -05:00
}
2021-12-04 19:38:26 -05:00
isChanged = modified . After ( c . lastModified )
c . lastModified = modified
2021-11-27 02:24:22 -05:00
return
}
2021-12-12 02:29:29 -05:00
2021-12-12 03:23:51 -05:00
/ *
PathName returns the "real" name of a Collection .
In some cases , the Collection . Label may not be the actual * name * of the collection
( i . e . the label is different from the name used in the Dbus path ) .
This is a thin wrapper around simply extracting the last item from
the Collection . Dbus . Path ( ) .
* /
func ( c * Collection ) PathName ( ) ( realName string ) {
var pathSplit [ ] string = strings . Split ( string ( c . Dbus . Path ( ) ) , "/" )
realName = pathSplit [ len ( pathSplit ) - 1 ]
return
}
2021-12-12 02:29:29 -05:00
/ *
setModify updates the Collection ' s modification time ( as specified by Collection . Modified ) .
It seems that this does not update automatically .
* /
func ( c * Collection ) setModify ( ) ( err error ) {
err = c . Dbus . SetProperty ( DbusCollectionModified , uint64 ( time . Now ( ) . Unix ( ) ) )
return
}