walletmanager funcs done, now for wallet funcs
This commit is contained in:
parent
8d81c5f0cc
commit
d76746d79e
@ -1,3 +1,6 @@
|
|||||||
https://api.kde.org/frameworks/kwallet/html/index.html
|
https://api.kde.org/frameworks/kwallet/html/index.html
|
||||||
|
https://invent.kde.org/frameworks/kwallet/-/blob/master/src/api/KWallet/kwallet.h
|
||||||
|
|
||||||
|
https://github.com/99designs/keyring/blob/master/kwallet.go
|
||||||
|
|
||||||
Dbus methods etc.: https://invent.kde.org/frameworks/kwallet/-/blob/master/src/api/KWallet/org.kde.KWallet.xml
|
Dbus methods etc.: https://invent.kde.org/frameworks/kwallet/-/blob/master/src/api/KWallet/org.kde.KWallet.xml
|
||||||
|
141
consts.go
141
consts.go
@ -1,5 +1,20 @@
|
|||||||
package gokwallet
|
package gokwallet
|
||||||
|
|
||||||
|
// KwalletD Dbus returns.
|
||||||
|
const (
|
||||||
|
DbusSuccess int32 = 0
|
||||||
|
DbusFailure int32 = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// KwalletD Dbus enums for WalletItem types.
|
||||||
|
const (
|
||||||
|
kwalletdEnumTypeUnknown = iota // UnknownItem
|
||||||
|
kwalletdEnumTypePassword // Password
|
||||||
|
kwalletdEnumTypeStream // Blob
|
||||||
|
kwalletdEnumTypeMap // Map
|
||||||
|
kwalletdEnumTypeUnused = 0xffff // 65535
|
||||||
|
)
|
||||||
|
|
||||||
// KWalletD Dbus interfaces.
|
// KWalletD Dbus interfaces.
|
||||||
const (
|
const (
|
||||||
// DbusService is the Dbus service bus identifier.
|
// DbusService is the Dbus service bus identifier.
|
||||||
@ -14,6 +29,21 @@ const (
|
|||||||
DefaultWalletName string = "kdewallet"
|
DefaultWalletName string = "kdewallet"
|
||||||
// DefaultAppID is the default name for the application (see WalletManager.AppID).
|
// DefaultAppID is the default name for the application (see WalletManager.AppID).
|
||||||
DefaultAppID string = "GoKwallet"
|
DefaultAppID string = "GoKwallet"
|
||||||
|
// DefaultWindowID is 0; we aren't guaranteed to have a window, so we pass 0 (per upstream headers' comments).
|
||||||
|
DefaultWindowID int64 = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
DefaultRecurseOpts *RecurseOpts = &RecurseOpts{
|
||||||
|
All: false,
|
||||||
|
Wallets: true,
|
||||||
|
Folders: true,
|
||||||
|
AllWalletItems: false,
|
||||||
|
Passwords: false,
|
||||||
|
Maps: false,
|
||||||
|
Blobs: false,
|
||||||
|
UnknownItems: false,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// WalletManager interface.
|
// WalletManager interface.
|
||||||
@ -94,10 +124,10 @@ const (
|
|||||||
// DbusWMOpenAsync opens (unlocks) a Wallet asynchronously.
|
// DbusWMOpenAsync opens (unlocks) a Wallet asynchronously.
|
||||||
DbusWMOpenAsync string = DbusInterfaceWM + ".openAsync"
|
DbusWMOpenAsync string = DbusInterfaceWM + ".openAsync"
|
||||||
|
|
||||||
// DbusWMOpenPath opens (unlocks) a Wallet by its filepath.
|
// DbusWMOpenPath opens a Wallet by its filepath.
|
||||||
DbusWMOpenPath string = DbusInterfaceWM + ".openPath"
|
DbusWMOpenPath string = DbusInterfaceWM + ".openPath"
|
||||||
|
|
||||||
// DbusWMOpenPathAsync opens (unlocks) a Wallet by its filepath asynchronously.
|
// DbusWMOpenPathAsync opens a Wallet by its filepath asynchronously.
|
||||||
DbusWMOpenPathAsync string = DbusInterfaceWM + ".openPath"
|
DbusWMOpenPathAsync string = DbusInterfaceWM + ".openPath"
|
||||||
|
|
||||||
// DbusWMPamOpen opens (unlocks) a Wallet via PAM.
|
// DbusWMPamOpen opens (unlocks) a Wallet via PAM.
|
||||||
@ -112,19 +142,31 @@ const (
|
|||||||
// DbusWMReadEntry fetches a WalletItem by its name from a Folder (as a byteslice).
|
// DbusWMReadEntry fetches a WalletItem by its name from a Folder (as a byteslice).
|
||||||
DbusWMReadEntry string = DbusInterfaceWM + ".readEntry"
|
DbusWMReadEntry string = DbusInterfaceWM + ".readEntry"
|
||||||
|
|
||||||
// DbusWMReadEntryList returns a map of WalletItem objects in a Folder.
|
/*
|
||||||
|
DbusWMReadEntryList returns a map of WalletItem objects in a Folder.
|
||||||
|
|
||||||
|
Deprecated: use DbusWMEntriesList instead.
|
||||||
|
*/
|
||||||
DbusWMReadEntryList string = DbusInterfaceWM + ".readEntryList"
|
DbusWMReadEntryList string = DbusInterfaceWM + ".readEntryList"
|
||||||
|
|
||||||
// DbusWMReadMap returns a Map from a Folder (as a byteslice).
|
// DbusWMReadMap returns a Map from a Folder (as a byteslice).
|
||||||
DbusWMReadMap string = DbusInterfaceWM + ".readMap"
|
DbusWMReadMap string = DbusInterfaceWM + ".readMap"
|
||||||
|
|
||||||
// DbusWMReadMapList returns a map of Map objects in a Folder.
|
/*
|
||||||
|
DbusWMReadMapList returns a map of Map objects in a Folder.
|
||||||
|
|
||||||
|
Deprecated: use DbusWMMapList instead.
|
||||||
|
*/
|
||||||
DbusWMReadMapList string = DbusInterfaceWM + ".readMapList"
|
DbusWMReadMapList string = DbusInterfaceWM + ".readMapList"
|
||||||
|
|
||||||
// DbusWMReadPassword returns a Password from a Folder (as a byteslice).
|
// DbusWMReadPassword returns a Password from a Folder (as a byteslice).
|
||||||
DbusWMReadPassword string = DbusInterfaceWM + ".readPassword"
|
DbusWMReadPassword string = DbusInterfaceWM + ".readPassword"
|
||||||
|
|
||||||
// DbusWMReadPasswordList returns a map of Password objects in a Folder.
|
/*
|
||||||
|
DbusWMReadPasswordList returns a map of Password objects in a Folder.
|
||||||
|
|
||||||
|
Deprecated: use DbusWMPasswordList instead.
|
||||||
|
*/
|
||||||
DbusWMReadPasswordList string = DbusInterfaceWM + ".readPasswordList"
|
DbusWMReadPasswordList string = DbusInterfaceWM + ".readPasswordList"
|
||||||
|
|
||||||
// DbusWMReconfigure is [FUNCTION UNKNOWN/UNDOCUMENTED; TODO? NOT IMPLEMENTED.]
|
// DbusWMReconfigure is [FUNCTION UNKNOWN/UNDOCUMENTED; TODO? NOT IMPLEMENTED.]
|
||||||
@ -163,92 +205,3 @@ const (
|
|||||||
// DbusPath is the path for DbusService.
|
// DbusPath is the path for DbusService.
|
||||||
DbusPath string = "/modules/kwalletd5"
|
DbusPath string = "/modules/kwalletd5"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Recursion options.
|
|
||||||
|
|
||||||
/*
|
|
||||||
RecurseNone specifies that no recursion should be done.
|
|
||||||
If present, it takes precedent over all over RecurseOptsFlags present.
|
|
||||||
|
|
||||||
Performed in/from:
|
|
||||||
WalletManager
|
|
||||||
Wallet
|
|
||||||
Folder
|
|
||||||
(WalletItem)
|
|
||||||
*/
|
|
||||||
const RecurseNone RecurseOptsFlag = 0
|
|
||||||
const (
|
|
||||||
/*
|
|
||||||
RecurseWallet indicates that Wallet objects should have Wallet.Update called.
|
|
||||||
|
|
||||||
Performed in/from: WalletManager
|
|
||||||
*/
|
|
||||||
RecurseWallet RecurseOptsFlag = 1 << iota
|
|
||||||
/*
|
|
||||||
RecurseFolder indicates that Folder objects should have Folder.Update called.
|
|
||||||
|
|
||||||
Performed in/from:
|
|
||||||
Wallet
|
|
||||||
|
|
||||||
May be performed in/from (depending on other flags):
|
|
||||||
WalletManager
|
|
||||||
*/
|
|
||||||
RecurseFolder
|
|
||||||
/*
|
|
||||||
RecurseWalletItem indicates that all WalletItem entries should have (WalletItem).Update() called.
|
|
||||||
If present, it takes precedent over all over relevant RecurseOptsFlags present
|
|
||||||
(RecursePassword, RecurseMap, RecurseBlob, RecurseUnknown).
|
|
||||||
|
|
||||||
Performed in/from:
|
|
||||||
Folder
|
|
||||||
|
|
||||||
May be performed in/from (depending on other flags):
|
|
||||||
WalletManager
|
|
||||||
Wallet
|
|
||||||
*/
|
|
||||||
RecurseWalletItem
|
|
||||||
/*
|
|
||||||
RecursePassword indicates that Password objects should have Password.Update() called.
|
|
||||||
|
|
||||||
Performed in/from:
|
|
||||||
Folder
|
|
||||||
|
|
||||||
May be performed in/from (depending on other flags):
|
|
||||||
WalletManager
|
|
||||||
Wallet
|
|
||||||
*/
|
|
||||||
RecursePassword
|
|
||||||
/*
|
|
||||||
RecurseMap indicates that Map objects should have Map.Update() called.
|
|
||||||
|
|
||||||
Performed in/from:
|
|
||||||
Folder
|
|
||||||
|
|
||||||
May be performed in/from (depending on other flags):
|
|
||||||
WalletManager
|
|
||||||
Wallet
|
|
||||||
*/
|
|
||||||
RecurseMap
|
|
||||||
/*
|
|
||||||
RecurseBlob indicates that Blob objects should have Blob.Update() called.
|
|
||||||
|
|
||||||
Performed in/from:
|
|
||||||
Folder
|
|
||||||
|
|
||||||
May be performed in/from (depending on other flags):
|
|
||||||
WalletManager
|
|
||||||
Wallet
|
|
||||||
*/
|
|
||||||
RecurseBlob
|
|
||||||
/*
|
|
||||||
RecurseUnknown indicates that UnknownItem objects should have UnknownItem.Update() called.
|
|
||||||
|
|
||||||
Performed in/from:
|
|
||||||
Folder
|
|
||||||
|
|
||||||
May be performed in/from (depending on other flags):
|
|
||||||
WalletManager
|
|
||||||
Wallet
|
|
||||||
*/
|
|
||||||
RecurseUnknown
|
|
||||||
)
|
|
||||||
|
5
doc.go
5
doc.go
@ -5,7 +5,7 @@ Package gokwallet serves as a Golang interface to KDE's KWallet (https://utils.k
|
|||||||
|
|
||||||
Note that to use this library, the running machine must have both Dbus and kwalletd running.
|
Note that to use this library, the running machine must have both Dbus and kwalletd running.
|
||||||
|
|
||||||
Note that this library interfaces with kwalletd. KWallet is in the process of moving to libsecret/SecretService
|
Relatedly, note also that this library interfaces with kwalletd. KWallet is in the process of moving to libsecret/SecretService
|
||||||
(see https://bugs.kde.org/show_bug.cgi?id=313216 and https://invent.kde.org/frameworks/kwallet/-/merge_requests/11),
|
(see https://bugs.kde.org/show_bug.cgi?id=313216 and https://invent.kde.org/frameworks/kwallet/-/merge_requests/11),
|
||||||
thus replacing kwalletd.
|
thus replacing kwalletd.
|
||||||
While there is a pull request in place, it has not yet been merged in (and it may be a while before downstream
|
While there is a pull request in place, it has not yet been merged in (and it may be a while before downstream
|
||||||
@ -72,5 +72,8 @@ Usage
|
|||||||
|
|
||||||
Full documentation can be found via inline documentation.
|
Full documentation can be found via inline documentation.
|
||||||
Additionally, use either https://pkg.go.dev/r00t2.io/gokwallet or https://pkg.go.dev/golang.org/x/tools/cmd/godoc (or `go doc`) in the source root.
|
Additionally, use either https://pkg.go.dev/r00t2.io/gokwallet or https://pkg.go.dev/golang.org/x/tools/cmd/godoc (or `go doc`) in the source root.
|
||||||
|
|
||||||
|
You most likely do *not* want to call any New<object> function directly;
|
||||||
|
NewWalletManager with its RecurseOpts parameter (`recursion`) should get you everything you want/need.
|
||||||
*/
|
*/
|
||||||
package gokwallet
|
package gokwallet
|
||||||
|
20
errs.go
Normal file
20
errs.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package gokwallet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
/*
|
||||||
|
ErrNotInitialized will be triggered if attempting to interact with an object that has not been properly initialized.
|
||||||
|
Notably, in most/all cases this means that it was not created via a New<object> func (for instance,
|
||||||
|
this would lead to a Wallet missing a handler).
|
||||||
|
It is intended as a safety check (so that you don't accidentally delete a wallet with e.g. a handler of 0 when
|
||||||
|
trying to delete a different wallet).
|
||||||
|
*/
|
||||||
|
ErrNotInitialized error = errors.New("object not properly initialized")
|
||||||
|
/*
|
||||||
|
ErrOperationFailed is a generic failure message that will occur of a Dbus operation returns non-success.
|
||||||
|
*/
|
||||||
|
ErrOperationFailed error = errors.New("a Dbus operation has failed to execute successfully")
|
||||||
|
)
|
56
folder_funcs.go
Normal file
56
folder_funcs.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package gokwallet
|
||||||
|
|
||||||
|
/*
|
||||||
|
NewF returns a Wallet. It requires a RecurseOpts
|
||||||
|
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
|
||||||
|
It also requires a WalletManager and wallet name.
|
||||||
|
*/
|
||||||
|
func NewFolder(w *Wallet, name string, recursion *RecurseOpts) (folder *Folder, err error) {
|
||||||
|
|
||||||
|
if !w.isInit {
|
||||||
|
err = ErrNotInitialized
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
folder = &Folder{
|
||||||
|
DbusObject: w.DbusObject,
|
||||||
|
Name: name,
|
||||||
|
Passwords: nil,
|
||||||
|
Maps: nil,
|
||||||
|
BinaryData: nil,
|
||||||
|
Unknown: nil,
|
||||||
|
Recurse: recursion,
|
||||||
|
wm: w.wm,
|
||||||
|
wallet: w,
|
||||||
|
// handle: 0,
|
||||||
|
isInit: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = folder.folderCheck(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if folder.Recurse.All || folder.Recurse.Wallets {
|
||||||
|
if err = folder.Update(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
folder.isInit = true
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Folder) Update() (err error) {
|
||||||
|
|
||||||
|
// TODO.
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Folder) folderCheck() (err error) {
|
||||||
|
|
||||||
|
// TODO.
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
110
funcs.go
Normal file
110
funcs.go
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
package gokwallet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
NewRecurseOpts returns a RecurseOpts based on the specified options.
|
||||||
|
See the documentation for RecurseOpts for descriptions of the behaviour for each recursion option.
|
||||||
|
warn is a MultiError but should be treated as warnings rather than strictly errors.
|
||||||
|
*/
|
||||||
|
func NewRecurseOpts(recurseAll, wallets, folders, recurseAllWalletItems, passwords, maps, blobs, unknownItems bool) (opts *RecurseOpts, warn error) {
|
||||||
|
|
||||||
|
var err []error = make([]error, 0)
|
||||||
|
|
||||||
|
if recurseAll {
|
||||||
|
if !wallets {
|
||||||
|
err = append(err, errors.New("wallets was specified as false but recurseAll is true; recurseAll overrides wallets to true"))
|
||||||
|
wallets = true
|
||||||
|
}
|
||||||
|
if !folders {
|
||||||
|
err = append(err, errors.New("folders was specified as false but recurseAll is true; recurseAll overrides folders to true"))
|
||||||
|
folders = true
|
||||||
|
}
|
||||||
|
// NOTE: This is commented out because we control these explicitly with recurseAllWalletItems.
|
||||||
|
/*
|
||||||
|
if !passwords {
|
||||||
|
err = append(err, errors.New("passwords was specified as false but recurseAll is true; recurseAll overrides passwords to true"))
|
||||||
|
passwords = true
|
||||||
|
}
|
||||||
|
if !maps {
|
||||||
|
err = append(err, errors.New("maps was specified as false but recurseAll is true; recurseAll overrides maps to true"))
|
||||||
|
maps = true
|
||||||
|
}
|
||||||
|
if !blobs {
|
||||||
|
err = append(err, errors.New("blobs was specified as false but recurseAll is true; recurseAll overrides blobs to true"))
|
||||||
|
blobs = true
|
||||||
|
}
|
||||||
|
if !unknownItems {
|
||||||
|
err = append(err, errors.New("unknownItems was specified as false but recurseAll is true; recurseAll overrides unknownItems to true"))
|
||||||
|
unknownItems = true
|
||||||
|
}
|
||||||
|
if !recurseAllWalletItems {
|
||||||
|
err = append(
|
||||||
|
err,
|
||||||
|
errors.New(
|
||||||
|
"recurseAllWalletItems was specified as false but recurseAll is true; recurseAll overrides recurseAllWalletItems to true",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
recurseAllWalletItems = true
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
if recurseAllWalletItems {
|
||||||
|
if !passwords {
|
||||||
|
err = append(
|
||||||
|
err,
|
||||||
|
errors.New(
|
||||||
|
"passwords was specified as false but recurseAllWalletItems is true; recurseAllWalletItems overrides passwords to true",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
passwords = true
|
||||||
|
}
|
||||||
|
if !maps {
|
||||||
|
err = append(
|
||||||
|
err,
|
||||||
|
errors.New(
|
||||||
|
"maps was specified as false but recurseAllWalletItems is true; recurseAllWalletItems overrides maps to true",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
maps = true
|
||||||
|
}
|
||||||
|
if !blobs {
|
||||||
|
err = append(
|
||||||
|
err,
|
||||||
|
errors.New(
|
||||||
|
"blobs was specified as false but recurseAllWalletItems is true; recurseAllWalletItems overrides blobs to true",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
blobs = true
|
||||||
|
}
|
||||||
|
if !unknownItems {
|
||||||
|
err = append(
|
||||||
|
err,
|
||||||
|
errors.New(
|
||||||
|
"unknownItems was specified as false but recurseAllWalletItems is true; recurseAllWalletItems overrides unknownItems to true",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
unknownItems = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
opts = &RecurseOpts{
|
||||||
|
All: recurseAll,
|
||||||
|
Wallets: wallets,
|
||||||
|
Folders: folders,
|
||||||
|
AllWalletItems: recurseAllWalletItems,
|
||||||
|
Passwords: passwords,
|
||||||
|
Maps: maps,
|
||||||
|
Blobs: blobs,
|
||||||
|
UnknownItems: unknownItems,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil && len(err) > 0 {
|
||||||
|
warn = NewErrors(err...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
2
go.mod
2
go.mod
@ -4,5 +4,5 @@ go 1.17
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/godbus/dbus/v5 v5.0.6
|
github.com/godbus/dbus/v5 v5.0.6
|
||||||
r00t2.io/goutils v1.0.1
|
r00t2.io/goutils v1.1.0
|
||||||
)
|
)
|
||||||
|
4
go.sum
4
go.sum
@ -2,6 +2,6 @@ github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7
|
|||||||
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
|
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
|
||||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/jszwec/csvutil v1.5.0/go.mod h1:Rpu7Uu9giO9subDyMCIQfHVDuLrcaC36UA4YcJjGBkg=
|
github.com/jszwec/csvutil v1.5.0/go.mod h1:Rpu7Uu9giO9subDyMCIQfHVDuLrcaC36UA4YcJjGBkg=
|
||||||
r00t2.io/goutils v1.0.1 h1:f1m2QRBF8XsW3peYf1I2q37npgf+5bmJBbrLzCFtm34=
|
r00t2.io/goutils v1.1.0 h1:vJqEWvdX0TKDyT+hTgws0wA1dc/F8JkQKw5cDHz0wH0=
|
||||||
r00t2.io/goutils v1.0.1/go.mod h1:CMK3RGnMSyjDSfYxeFQl/oJTkkUMS1jhSTdGTkAPpQw=
|
r00t2.io/goutils v1.1.0/go.mod h1:CMK3RGnMSyjDSfYxeFQl/oJTkkUMS1jhSTdGTkAPpQw=
|
||||||
r00t2.io/sysutils v0.0.0-20210224054841-55ac47c86928/go.mod h1:XzJkBF6SHAODEszJlOcjtGoTHwYnZZNmseA6PyOujes=
|
r00t2.io/sysutils v0.0.0-20210224054841-55ac47c86928/go.mod h1:XzJkBF6SHAODEszJlOcjtGoTHwYnZZNmseA6PyOujes=
|
||||||
|
57
multierror_funcs.go
Normal file
57
multierror_funcs.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package gokwallet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
NewErrors returns a new MultiError based on a slice of error.Error (errs).
|
||||||
|
Any nil errors are trimmed. If there are no actual errors after trimming, err will be nil.
|
||||||
|
*/
|
||||||
|
func NewErrors(errs ...error) (err error) {
|
||||||
|
|
||||||
|
if errs == nil || len(errs) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var realErrs []error = make([]error, 0)
|
||||||
|
|
||||||
|
for _, e := range errs {
|
||||||
|
if e == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
realErrs = append(realErrs, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(realErrs) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = &MultiError{
|
||||||
|
Errors: realErrs,
|
||||||
|
ErrorSep: "\n",
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *MultiError) Error() (errStr string) {
|
||||||
|
|
||||||
|
var numErrs int
|
||||||
|
|
||||||
|
if e == nil || len(e.Errors) == 0 {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
numErrs = len(e.Errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, err := range e.Errors {
|
||||||
|
if (idx + 1) < numErrs {
|
||||||
|
errStr += fmt.Sprintf(err.Error(), e.ErrorSep)
|
||||||
|
} else {
|
||||||
|
errStr += err.Error()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
182
types.go
182
types.go
@ -2,7 +2,6 @@ package gokwallet
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/godbus/dbus/v5"
|
"github.com/godbus/dbus/v5"
|
||||||
"r00t2.io/goutils/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -45,8 +44,22 @@ type WalletManager struct {
|
|||||||
/*
|
/*
|
||||||
Wallets is the collection of Wallets accessible in/to this WalletManager.
|
Wallets is the collection of Wallets accessible in/to this WalletManager.
|
||||||
Wallet.Name is the map key.
|
Wallet.Name is the map key.
|
||||||
|
(TODO: When wallet file support is added, the *filename* will be the map key.
|
||||||
|
This is to mitigate namespace conflicts between Dbus and file wallets.)
|
||||||
*/
|
*/
|
||||||
Wallets map[string]*Wallet `json:"wallets"`
|
Wallets map[string]*Wallet `json:"wallets"`
|
||||||
|
// Recurse contains the relevant RecurseOpts.
|
||||||
|
Recurse *RecurseOpts `json:"recurse_opts"`
|
||||||
|
// Enabled is true if KWalletD is enabled/running.
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
// Local is the "local" wallet.
|
||||||
|
Local *Wallet `json:"local_wallet"`
|
||||||
|
// Network is the "network" wallet.
|
||||||
|
Network *Wallet `json:"network_wallet"`
|
||||||
|
// isInit flags whether this is "properly" set up (i.e. was initialized via NewWalletManager).
|
||||||
|
isInit bool
|
||||||
|
// walletFiles are (resolved and vetted) wallet files (kwl, xml).
|
||||||
|
walletFiles []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wallet contains one or more (or none) Folder objects.
|
// Wallet contains one or more (or none) Folder objects.
|
||||||
@ -59,6 +72,22 @@ type Wallet struct {
|
|||||||
Folder.Name is the map key.
|
Folder.Name is the map key.
|
||||||
*/
|
*/
|
||||||
Folders map[string]*Folder `json:"folders"`
|
Folders map[string]*Folder `json:"folders"`
|
||||||
|
// Recurse contains the relevant RecurseOpts.
|
||||||
|
Recurse *RecurseOpts `json:"recurse_opts"`
|
||||||
|
// IsUnlocked specifies if this Wallet is open ("unlocked") or not.
|
||||||
|
IsUnlocked bool `json:"open"`
|
||||||
|
/*
|
||||||
|
FilePath is:
|
||||||
|
- empty if this is an internal Wallet, or
|
||||||
|
- the filepath to the wallet file if this is an on-disk wallet (either .kwl or .xml)
|
||||||
|
*/
|
||||||
|
FilePath string `json:"wallet_file"`
|
||||||
|
// wm is the parent WalletManager this Wallet was fetched from.
|
||||||
|
wm *WalletManager
|
||||||
|
// handle is this Wallet's handler number.
|
||||||
|
handle int32
|
||||||
|
// isInit flags whether this is "properly" set up (i.e. has a handle).
|
||||||
|
isInit bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Folder contains secret object collections of Password, Map, Blob, and UnknownItem objects.
|
// Folder contains secret object collections of Password, Map, Blob, and UnknownItem objects.
|
||||||
@ -86,6 +115,16 @@ type Folder struct {
|
|||||||
Unknown.Name is the map key.
|
Unknown.Name is the map key.
|
||||||
*/
|
*/
|
||||||
Unknown map[string]*UnknownItem `json:"unknown"`
|
Unknown map[string]*UnknownItem `json:"unknown"`
|
||||||
|
// Recurse contains the relevant RecurseOpts.
|
||||||
|
Recurse *RecurseOpts `json:"recurse_opts"`
|
||||||
|
// wm is the parent WalletManager that Folder.wallet was fetched from.
|
||||||
|
wm *WalletManager
|
||||||
|
// wallet is the parent Wallet this Folder was fetched from.
|
||||||
|
wallet *Wallet
|
||||||
|
// handle is this Folder's handler number.
|
||||||
|
handle int32
|
||||||
|
// isInit flags whether this is "properly" set up (i.e. has a handle).
|
||||||
|
isInit bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Password is a straightforward single-value secret of text.
|
// Password is a straightforward single-value secret of text.
|
||||||
@ -95,6 +134,18 @@ type Password struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// Value is this Password's value.
|
// Value is this Password's value.
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
|
// Recurse contains the relevant RecurseOpts.
|
||||||
|
Recurse *RecurseOpts `json:"recurse_opts"`
|
||||||
|
// wm is the parent WalletManager that Password.folder.wallet was fetched from.
|
||||||
|
wm *WalletManager
|
||||||
|
// wallet is the parent Wallet that Password.folder was fetched from.
|
||||||
|
wallet *Wallet
|
||||||
|
// folder is the parent Folder this Password was fetched from.
|
||||||
|
folder *Folder
|
||||||
|
// handle is this Password's handler number.
|
||||||
|
handle int32
|
||||||
|
// isInit flags whether this is "properly" set up (i.e. has a handle).
|
||||||
|
isInit bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map is a dictionary or key/value secret.
|
// Map is a dictionary or key/value secret.
|
||||||
@ -104,6 +155,18 @@ type Map struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// Value is this Map's value.
|
// Value is this Map's value.
|
||||||
Value map[string]string `json:"value"`
|
Value map[string]string `json:"value"`
|
||||||
|
// Recurse contains the relevant RecurseOpts.
|
||||||
|
Recurse *RecurseOpts `json:"recurse_opts"`
|
||||||
|
// wm is the parent WalletManager that Map.folder.wallet was fetched from.
|
||||||
|
wm *WalletManager
|
||||||
|
// wallet is the parent Wallet that Map.folder was fetched from.
|
||||||
|
wallet *Wallet
|
||||||
|
// folder is the parent Folder this Map was fetched from.
|
||||||
|
folder *Folder
|
||||||
|
// handle is this Map's handler number.
|
||||||
|
handle int32
|
||||||
|
// isInit flags whether this is "properly" set up (i.e. has a handle).
|
||||||
|
isInit bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blob (binary large object, typographically BLOB) is secret binary data.
|
// Blob (binary large object, typographically BLOB) is secret binary data.
|
||||||
@ -113,6 +176,18 @@ type Blob struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// Value is this Blob's value.
|
// Value is this Blob's value.
|
||||||
Value []byte `json:"value"`
|
Value []byte `json:"value"`
|
||||||
|
// Recurse contains the relevant RecurseOpts.
|
||||||
|
Recurse *RecurseOpts `json:"recurse_opts"`
|
||||||
|
// wm is the parent WalletManager that Blob.folder.wallet was fetched from.
|
||||||
|
wm *WalletManager
|
||||||
|
// wallet is the parent Wallet that Blob.folder was fetched from.
|
||||||
|
wallet *Wallet
|
||||||
|
// folder is the parent Folder this Blob was fetched from.
|
||||||
|
folder *Folder
|
||||||
|
// handle is this Blob's handler number.
|
||||||
|
handle int32
|
||||||
|
// isInit flags whether this is "properly" set up (i.e. has a handle).
|
||||||
|
isInit bool
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -126,6 +201,18 @@ type UnknownItem struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// Value is the Dbus path of this UnknownItem.
|
// Value is the Dbus path of this UnknownItem.
|
||||||
Value dbus.ObjectPath `json:"value"`
|
Value dbus.ObjectPath `json:"value"`
|
||||||
|
// Recurse contains the relevant RecurseOpts.
|
||||||
|
Recurse *RecurseOpts `json:"recurse_opts"`
|
||||||
|
// wm is the parent WalletManager that UnknownItem.folder.wallet was fetched from.
|
||||||
|
wm *WalletManager
|
||||||
|
// wallet is the parent Wallet that UnknownItem.folder was fetched from.
|
||||||
|
wallet *Wallet
|
||||||
|
// folder is the parent Folder this UnknownItem was fetched from.
|
||||||
|
folder *Folder
|
||||||
|
// handle is this UnknownItem's handler number.
|
||||||
|
handle int32
|
||||||
|
// isInit flags whether this is "properly" set up (i.e. has a handle).
|
||||||
|
isInit bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// WalletItem is an interface to manage wallet objects: Password, Map, Blob, or UnknownItem.
|
// WalletItem is an interface to manage wallet objects: Password, Map, Blob, or UnknownItem.
|
||||||
@ -134,8 +221,93 @@ type WalletItem interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
RecurseOptsFlag is used to determine whether or not to recurse into items and fully populate them.
|
RecurseOpts controls whether recursion should be done on objects when fetching them.
|
||||||
One would use a types.BitMask as a parameter type and do <BitMask>.HasFlag(<RecurseOptsFlag>).
|
E.g. if fetching a WalletManager (via NewWalletManager) and RecurseOpts.Wallet is true,
|
||||||
See consts.go for the actual flags.
|
then WalletManager.Wallets will be populated with Wallet objects.
|
||||||
*/
|
*/
|
||||||
type RecurseOptsFlag types.MaskBit
|
type RecurseOpts struct {
|
||||||
|
/*
|
||||||
|
All, if true, specifies that all possible recursions should be done.
|
||||||
|
If true, it takes precedent over all over RecurseOpts fields (with the exception of RecurseOpts.AllWalletItems).
|
||||||
|
|
||||||
|
Performed in/from:
|
||||||
|
WalletManager
|
||||||
|
Wallet
|
||||||
|
Folder
|
||||||
|
(WalletItem)
|
||||||
|
*/
|
||||||
|
All bool `json:"none"`
|
||||||
|
/*
|
||||||
|
Wallets, if true, indicates that Wallet objects should have Wallet.Update called.
|
||||||
|
|
||||||
|
Performed in/from: WalletManager
|
||||||
|
*/
|
||||||
|
Wallets bool `json:"wallet"`
|
||||||
|
/*
|
||||||
|
Folders, if true, indicates that Folder objects should have Folder.Update called.
|
||||||
|
|
||||||
|
Performed in/from:
|
||||||
|
Wallet
|
||||||
|
|
||||||
|
May be performed in/from (depending on other fields):
|
||||||
|
WalletManager
|
||||||
|
*/
|
||||||
|
Folders bool `json:"folder"`
|
||||||
|
/*
|
||||||
|
AllWalletItems, if true, indicates that all WalletItem entries should have (WalletItem).Update() called.
|
||||||
|
If true, it takes precedent over all over relevant RecurseOpts fields for each WalletItem type
|
||||||
|
(i.e. RecurseOpts.Passwords, RecurseOpts.Maps, RecurseOpts.Blobs, RecurseOpts.UnknownItems).
|
||||||
|
|
||||||
|
Performed in/from:
|
||||||
|
Folder
|
||||||
|
|
||||||
|
May be performed in/from (depending on other fields):
|
||||||
|
WalletManager
|
||||||
|
Wallet
|
||||||
|
*/
|
||||||
|
AllWalletItems bool `json:"wallet_item"`
|
||||||
|
/*
|
||||||
|
Passwords, if true, indicates that Password objects should have Password.Update() called.
|
||||||
|
|
||||||
|
Performed in/from:
|
||||||
|
Folder
|
||||||
|
|
||||||
|
May be performed in/from (depending on other fields):
|
||||||
|
WalletManager
|
||||||
|
Wallet
|
||||||
|
*/
|
||||||
|
Passwords bool `json:"password"`
|
||||||
|
/*
|
||||||
|
Maps, if true, indicates that Map objects should have Map.Update() called.
|
||||||
|
|
||||||
|
Performed in/from:
|
||||||
|
Folder
|
||||||
|
|
||||||
|
May be performed in/from (depending on other fields):
|
||||||
|
WalletManager
|
||||||
|
Wallet
|
||||||
|
*/
|
||||||
|
Maps bool `json:"map"`
|
||||||
|
/*
|
||||||
|
Blobs, if true, indicates that Blob objects should have Blob.Update() called.
|
||||||
|
|
||||||
|
Performed in/from:
|
||||||
|
Folder
|
||||||
|
|
||||||
|
May be performed in/from (depending on other fields):
|
||||||
|
WalletManager
|
||||||
|
Wallet
|
||||||
|
*/
|
||||||
|
Blobs bool `json:"blob"`
|
||||||
|
/*
|
||||||
|
UnknownItems indicates that UnknownItem objects should have UnknownItem.Update() called.
|
||||||
|
|
||||||
|
Performed in/from:
|
||||||
|
Folder
|
||||||
|
|
||||||
|
May be performed in/from (depending on other fields):
|
||||||
|
WalletManager
|
||||||
|
Wallet
|
||||||
|
*/
|
||||||
|
UnknownItems bool `json:"unknown_item"`
|
||||||
|
}
|
||||||
|
35
utils.go
Normal file
35
utils.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package gokwallet
|
||||||
|
|
||||||
|
/*
|
||||||
|
resultCheck checks the result code from a Dbus call and returns an error if not successful.
|
||||||
|
See also resultPassed.
|
||||||
|
*/
|
||||||
|
func resultCheck(result int32) (err error) {
|
||||||
|
|
||||||
|
// This is technically way more complex than it needs to be, but is extendable for future use.
|
||||||
|
switch i := result; i {
|
||||||
|
case DbusSuccess:
|
||||||
|
err = nil
|
||||||
|
case DbusFailure:
|
||||||
|
err = ErrOperationFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
resultPassed checks the result code from a Dbus call and returns a boolean as to whether the result is pass or not.
|
||||||
|
See also resultCheck.
|
||||||
|
*/
|
||||||
|
func resultPassed(result int32) (passed bool) {
|
||||||
|
|
||||||
|
// This is technically way more complex than it needs to be, but is extendable for future use.
|
||||||
|
switch i := result; i {
|
||||||
|
case DbusSuccess:
|
||||||
|
passed = true
|
||||||
|
case DbusFailure:
|
||||||
|
passed = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
189
wallet_funcs.go
189
wallet_funcs.go
@ -1,14 +1,191 @@
|
|||||||
package gokwallet
|
package gokwallet
|
||||||
|
|
||||||
import (
|
/*
|
||||||
"github.com/godbus/dbus/v5"
|
NewWallet returns a Wallet. It requires a RecurseOpts
|
||||||
)
|
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
|
||||||
|
It also requires a WalletManager and wallet name.
|
||||||
|
*/
|
||||||
|
func NewWallet(wm *WalletManager, name string, recursion *RecurseOpts) (wallet *Wallet, err error) {
|
||||||
|
|
||||||
func NewWallet(wm *WalletManager, path dbus.ObjectPath) (wallet *Wallet, err error) {
|
if !wm.isInit {
|
||||||
|
err = ErrNotInitialized
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var open bool
|
wallet = &Wallet{
|
||||||
|
DbusObject: wm.DbusObject,
|
||||||
|
Name: name,
|
||||||
|
Folders: nil,
|
||||||
|
Recurse: recursion,
|
||||||
|
wm: wm,
|
||||||
|
// handle: 0,
|
||||||
|
isInit: false,
|
||||||
|
}
|
||||||
|
|
||||||
_ = open
|
// TODO: remove this and leave to caller, since it might use PamOpen instead? Fail back to it?
|
||||||
|
if err = wallet.walletCheck(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if wallet.Recurse.All || wallet.Recurse.Wallets {
|
||||||
|
if err = wallet.Update(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wallet.isInit = true
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes a Wallet.
|
||||||
|
func (w *Wallet) Close() (err error) {
|
||||||
|
|
||||||
|
var rslt int32
|
||||||
|
|
||||||
|
if !w.isInit {
|
||||||
|
err = ErrNotInitialized
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using a handler allows us to close access for this particular parent WalletManager.
|
||||||
|
if err = w.Dbus.Call(
|
||||||
|
DbusWMClose, 0, w.handle, false, w.wm.AppID,
|
||||||
|
).Store(&rslt); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = resultCheck(rslt)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ForceClose is like Close but will still close a Wallet even if currently in use by the WalletManager.
|
||||||
|
(Despite the insinuation by the name, this should be a relatively safe operation).
|
||||||
|
*/
|
||||||
|
func (w *Wallet) ForceClose() (err error) {
|
||||||
|
|
||||||
|
var rslt int32
|
||||||
|
|
||||||
|
if !w.isInit {
|
||||||
|
err = ErrNotInitialized
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using a handler allows us to close access for this particular parent WalletManager.
|
||||||
|
if err = w.Dbus.Call(
|
||||||
|
DbusWMClose, 0, w.handle, true, w.wm.AppID,
|
||||||
|
).Store(&rslt); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = resultCheck(rslt)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsOpen returns whether a Wallet is open ("unlocked") or not (as well as updates Wallet.IsOpen).
|
||||||
|
func (w *Wallet) IsOpen() (isOpen bool, err error) {
|
||||||
|
|
||||||
|
// We can call the same method with w.handle instead of w.Name. We don't have a handler yet though.
|
||||||
|
if err = w.Dbus.Call(
|
||||||
|
DbusWMIsOpen, 0, w.Name,
|
||||||
|
).Store(&w.IsUnlocked); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isOpen = w.IsUnlocked
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListFolders lists all Folder names in a Wallet.
|
||||||
|
func (w *Wallet) ListFolders() (folderList []string, err error) {
|
||||||
|
|
||||||
|
if err = w.walletCheck(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = w.Dbus.Call(
|
||||||
|
DbusWMFolderList, 0, w.handle, w.wm.AppID,
|
||||||
|
).Store(&folderList); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Open will open ("unlock") a Wallet.
|
||||||
|
It will no-op if the Wallet is already open.
|
||||||
|
*/
|
||||||
|
func (w *Wallet) Open() (err error) {
|
||||||
|
|
||||||
|
if _, err = w.IsOpen(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !w.IsUnlocked {
|
||||||
|
if err = w.Dbus.Call(
|
||||||
|
DbusWMOpen, 0,
|
||||||
|
).Store(&w.handle); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.IsUnlocked = true
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update fetches/updates all Folder objects in a Wallet.
|
||||||
|
func (w *Wallet) Update() (err error) {
|
||||||
|
|
||||||
|
var folderNames []string
|
||||||
|
var errs []error = make([]error, 0)
|
||||||
|
|
||||||
|
if folderNames, err = w.ListFolders(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Folders = make(map[string]*Folder)
|
||||||
|
|
||||||
|
for _, fn := range folderNames {
|
||||||
|
if w.Folders[fn], err = NewFolder(w, fn, w.Recurse); err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
err = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if errs != nil && len(errs) > 0 {
|
||||||
|
err = NewErrors(errs...)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// walletCheck will check if a Wallet is (initialized and) opened and, if not, attempt to open it.
|
||||||
|
func (w *Wallet) walletCheck() (err error) {
|
||||||
|
|
||||||
|
if !w.isInit {
|
||||||
|
err = ErrNotInitialized
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = w.IsOpen(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !w.IsUnlocked {
|
||||||
|
if err = w.Open(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
NewWalletManager returns a WalletManager.
|
NewWalletManager returns a WalletManager. It requires a RecurseOpts
|
||||||
|
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
|
||||||
If appId is empty/nil, DefaultAppID will be used as the app ID.
|
If appId is empty/nil, DefaultAppID will be used as the app ID.
|
||||||
If appId is specified, only the first string is used.
|
If appId is specified, only the first string is used.
|
||||||
*/
|
*/
|
||||||
func NewWalletManager(appID ...string) (wm *WalletManager, err error) {
|
func NewWalletManager(recursion *RecurseOpts, appID ...string) (wm *WalletManager, err error) {
|
||||||
|
|
||||||
var realAppID string
|
var realAppID string
|
||||||
|
|
||||||
@ -19,13 +20,245 @@ func NewWalletManager(appID ...string) (wm *WalletManager, err error) {
|
|||||||
realAppID = DefaultAppID
|
realAppID = DefaultAppID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if wm, err = newWM(realAppID, recursion); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
NewWalletManagerFiles returns a WalletManager from one or more filePaths (*.kwl, *.tar, or *.xml exports).
|
||||||
|
Note that if the wallet file was created via an "encrypted export", it will be a .kwl file
|
||||||
|
inside a .tar.
|
||||||
|
err will contain a MultiError if any filepaths specified do not exist or cannot be opened.
|
||||||
|
It requires a RecurseOpts (you can use DefaultRecurseOpts, call NewRecurseOpts,
|
||||||
|
or provide your own RecurseOpts struct).
|
||||||
|
If appId is empty, DefaultAppID will be used as the app ID.
|
||||||
|
*/
|
||||||
|
/* TODO: POC this before exposing. I have NO idea if it'll work.
|
||||||
|
func NewWalletManagerFiles(recursion *RecurseOpts, appId string, filePaths ...string) (wm *WalletManager, err error) {
|
||||||
|
|
||||||
|
var exist bool
|
||||||
|
var errs []error = make([]error, 0)
|
||||||
|
var realFilePaths []string = make([]string, 0)
|
||||||
|
|
||||||
|
if appId == "" {
|
||||||
|
appId = DefaultAppID
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range filePaths {
|
||||||
|
if f == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if exist, err = paths.RealPathExists(&f); err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
err = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !exist {
|
||||||
|
err = errors.New(fmt.Sprintf("%v does not exist", f))
|
||||||
|
err = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
realFilePaths = append(realFilePaths, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: do the actual newWM here.
|
||||||
|
|
||||||
|
if errs != nil && len(errs) > 0 {
|
||||||
|
err = NewErrors(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
CloseWallet closes a Wallet.
|
||||||
|
Unlike Wallet.Close, this closes access for ALL applications/WalletManagers
|
||||||
|
for the specified Wallet - not just this WalletManager.
|
||||||
|
*/
|
||||||
|
func (wm *WalletManager) CloseWallet(walletName string) (err error) {
|
||||||
|
var rslt int32
|
||||||
|
|
||||||
|
if !wm.isInit {
|
||||||
|
err = ErrNotInitialized
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using a handler allows us to close access for this particular parent WalletManager.
|
||||||
|
if err = wm.Dbus.Call(
|
||||||
|
DbusWMClose, 0, walletName, false,
|
||||||
|
).Store(&rslt); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = resultCheck(rslt)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ForceCloseWallet is like WalletManager.CloseWallet but will still close a Wallet even if currently in use.
|
||||||
|
Unlike Wallet.ForceClose, this closes access for ALL applications/WalletManagers
|
||||||
|
for the specified Wallet - not just this WalletManager.
|
||||||
|
*/
|
||||||
|
func (wm *WalletManager) FprceCloseWallet(walletName string) (err error) {
|
||||||
|
|
||||||
|
var rslt int32
|
||||||
|
|
||||||
|
if !wm.isInit {
|
||||||
|
err = ErrNotInitialized
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using a handler allows us to close access for this particular parent WalletManager.
|
||||||
|
if err = wm.Dbus.Call(
|
||||||
|
DbusWMClose, 0, walletName, false,
|
||||||
|
).Store(&rslt); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = resultCheck(rslt)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloseAllWallets closes all Wallet objects. They do *not* need to be part of WalletManager.Wallets.
|
||||||
|
func (wm *WalletManager) CloseAllWallets() (err error) {
|
||||||
|
|
||||||
|
var call *dbus.Call
|
||||||
|
|
||||||
|
if !wm.isInit {
|
||||||
|
err = ErrNotInitialized
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
call = wm.Dbus.Call(
|
||||||
|
DbusWMCloseAllWallets, 0,
|
||||||
|
)
|
||||||
|
err = call.Err
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEnabled returns whether KWallet is enabled or not (and also updates WalletManager.Enabled).
|
||||||
|
func (wm *WalletManager) IsEnabled() (enabled bool, err error) {
|
||||||
|
|
||||||
|
if !wm.isInit {
|
||||||
|
err = ErrNotInitialized
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = wm.Dbus.Call(
|
||||||
|
DbusWMIsEnabled, 0,
|
||||||
|
).Store(&wm.Enabled); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled = wm.Enabled
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalWallet returns the "local" wallet (and updates WalletManager.Local).
|
||||||
|
func (wm *WalletManager) LocalWallet() (w *Wallet, err error) {
|
||||||
|
|
||||||
|
var wn string
|
||||||
|
|
||||||
|
if err = wm.Dbus.Call(
|
||||||
|
DbusWMLocalWallet, 0,
|
||||||
|
).Store(&wn); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if w, err = NewWallet(wm, wn, wm.Recurse); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
wm.Local = w
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkWallet returns the "network" wallet (and updates WalletManager.Network).
|
||||||
|
func (wm *WalletManager) NetworkWallet() (w *Wallet, err error) {
|
||||||
|
|
||||||
|
var wn string
|
||||||
|
|
||||||
|
if err = wm.Dbus.Call(
|
||||||
|
DbusWMNetWallet, 0,
|
||||||
|
).Store(&wn); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if w, err = NewWallet(wm, wn, wm.Recurse); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
wm.Network = w
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// WalletNames returns a list of available Wallet names.
|
||||||
|
func (wm *WalletManager) WalletNames() (wallets []string, err error) {
|
||||||
|
|
||||||
|
if err = wm.Dbus.Call(
|
||||||
|
DbusWMWallets, 0,
|
||||||
|
).Store(&wallets); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update fetches/updates all Wallet objects in a WalletManager.
|
||||||
|
func (wm *WalletManager) Update() (err error) {
|
||||||
|
|
||||||
|
var walletNames []string
|
||||||
|
var errs []error = make([]error, 0)
|
||||||
|
|
||||||
|
if !wm.isInit {
|
||||||
|
err = ErrNotInitialized
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if walletNames, err = wm.WalletNames(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
wm.Wallets = make(map[string]*Wallet)
|
||||||
|
|
||||||
|
for _, wn := range walletNames {
|
||||||
|
|
||||||
|
if wm.Wallets[wn], err = NewWallet(wm, wn, wm.Recurse); err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
err = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if errs != nil && len(errs) > 0 {
|
||||||
|
err = NewErrors(errs...)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// newWM is what does the heavy lifting behind NewWalletManager and NewWalletManagerFiles.
|
||||||
|
func newWM(appId string, recursion *RecurseOpts, filePaths ...string) (wm *WalletManager, err error) {
|
||||||
|
|
||||||
wm = &WalletManager{
|
wm = &WalletManager{
|
||||||
DbusObject: &DbusObject{
|
DbusObject: &DbusObject{
|
||||||
Conn: nil,
|
Conn: nil,
|
||||||
Dbus: nil,
|
Dbus: nil,
|
||||||
},
|
},
|
||||||
AppID: realAppID,
|
AppID: appId,
|
||||||
Wallets: make(map[string]*Wallet),
|
Wallets: nil,
|
||||||
|
Recurse: recursion,
|
||||||
}
|
}
|
||||||
|
|
||||||
if wm.DbusObject.Conn, err = dbus.SessionBus(); err != nil {
|
if wm.DbusObject.Conn, err = dbus.SessionBus(); err != nil {
|
||||||
@ -33,18 +266,19 @@ func NewWalletManager(appID ...string) (wm *WalletManager, err error) {
|
|||||||
}
|
}
|
||||||
wm.DbusObject.Dbus = wm.DbusObject.Conn.Object(DbusService, dbus.ObjectPath(DbusPath))
|
wm.DbusObject.Dbus = wm.DbusObject.Conn.Object(DbusService, dbus.ObjectPath(DbusPath))
|
||||||
|
|
||||||
return
|
if wm.Recurse.All || wm.Recurse.Wallets {
|
||||||
}
|
if err = wm.Update(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err = wm.LocalWallet(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err = wm.NetworkWallet(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
wm.isInit = true
|
||||||
Update fetches/updates all Wallet objects in a WalletManager.
|
|
||||||
*/
|
|
||||||
func (wm *WalletManager) Update() (err error) {
|
|
||||||
|
|
||||||
var wallets []*Wallet
|
|
||||||
|
|
||||||
// TODO.
|
|
||||||
_ = wallets
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user