adding convenience function to check (in a very basic manner) if an API spec is legacy.

This commit is contained in:
brent s. 2022-01-09 17:11:50 -05:00
parent d13b263222
commit aa8aef4ccf
Signed by: bts
GPG Key ID: 8C004C2F93481F6B
4 changed files with 92 additions and 1 deletions

View File

@ -153,3 +153,56 @@ func NameFromPath(path dbus.ObjectPath) (name string, err error) {

return
}

/*
CheckErrIsFromLegacy takes an error.Error from e.g.:

Service.SearchItems
Collection.CreateItem
NewItem
Item.ChangeItemType
Item.Type

and (in order) attempt to typeswitch to a *multierr.MultiError, then iterate through
the *multierr.MultiError.Errors, attempt to typeswitch each of them to a Dbus.Error, and then finally
check if it is regarding a missing Type property.

This is *very explicitly* only useful for the above functions/methods. If used anywhere else,
it's liable to return an incorrect isLegacy even if parsed == true.

It is admittedly convoluted and obtuse, but this saves a lot of boilerplate for users.
It wouldn't be necessary if projects didn't insist on using the legacy draft SecretService specification.
But here we are.

isLegacy is true if this Service's API destination is legacy spec. Note that this is checking for
very explicit conditions; isLegacy may return false but it is in fact running on a legacy API.
Don't rely on this too much.

parsed is true if we found an error type we were able to perform logic of determination on.
*/
func CheckErrIsFromLegacy(err error) (isLegacy, parsed bool) {

switch e := err.(type) {
case *multierr.MultiError:
parsed = true
for _, i := range e.Errors {
switch e2 := i.(type) {
case dbus.Error:
if e2.Name == "org.freedesktop.DBus.Error.UnknownProperty" {
isLegacy = true
return
}
default:
continue
}
}
case dbus.Error:
parsed = true
if e.Name == "org.freedesktop.DBus.Error.UnknownProperty" {
isLegacy = true
return
}
}

return
}

View File

@ -85,6 +85,11 @@ func (i *Item) ChangeItemType(newItemType string) (err error) {

var variant dbus.Variant

// Legacy spec.
if i.collection.service.Legacy {
return
}

if strings.TrimSpace(newItemType) == "" {
newItemType = DbusDefaultItemType
}

View File

@ -257,6 +257,27 @@ func (s *Service) GetSession() (ssn *Session, err error) {
return
}

// Scrapping this idea for now; it would require introspection on a known Item path.
/*
IsLegacy indicates with a decent likelihood of accuracy if this Service is
connected to a legacy spec Secret Service (true) or if the spec is current (false).

It also returns a confidence indicator as a float, which indicates how accurate
the guess (because it is a guess) may/is likely to be (as a percentage). For example,
if confidence is expressed as 0.25, the result of legacyAPI has a 25% of being accurate.
*/
/*
func (s *Service) IsLegacy() (legacyAPI bool, confidence int) {

var maxCon int

// Test 1, property introspection on Item. We're looking for a Type property.
DbusInterfaceItem

return
}
*/

// Lock locks an Unlocked Collection or Item (LockableObject).
func (s *Service) Lock(objects ...LockableObject) (err error) {


View File

@ -74,7 +74,19 @@ type Service struct {
when performing a Service.SearchItems, you probably need to enable this field on the
Service returned by NewService. The coverage of this field may expand in the future, but
currently it only prevents/suppresses the (non-existent, in legacy spec) Type property
from being read or written on Items during NewItem and Collection.CreateItem respectively.
from being read or written on Items during e.g.:

Service.SearchItems
Collection.CreateItem
NewItem
Item.ChangeItemType
Item.Type

It will perform a no-op if enabled in the above contexts to maintain cross-compatability
in codebase between legacy and proper current spec systems, avoiding an error return.

You can use CheckErrIsFromLegacy if Service.Legacy is false and Service.SearchItems returns
a non-nil err to determine if this Service is (probably) interfacing with a legacy spec API.
*/
Legacy bool `json:"is_legacy"`
}