Initial commit. In working condition

This commit is contained in:
Goran Sterjov 2016-10-01 18:13:38 +10:00
commit 8c0993ba70
7 changed files with 462 additions and 0 deletions

22
LICENSE Normal file
View File

@ -0,0 +1,22 @@
The MIT License (MIT)

Copyright (c) 2016 Goran Sterjov

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

124
collection.go Normal file
View File

@ -0,0 +1,124 @@
package libsecret

import "github.com/godbus/dbus"


type Collection struct {
conn *dbus.Conn
dbus dbus.BusObject
}


func NewCollection(conn *dbus.Conn, path dbus.ObjectPath) *Collection {
return &Collection{
conn: conn,
dbus: conn.Object(DBUS_SERVICE_NAME, path),
}
}


func (collection Collection) Path() dbus.ObjectPath {
return collection.dbus.Path()
}


// READ Array<ObjectPath> Items;
func (collection *Collection) Items() ([]Item, error) {
val, err := collection.dbus.GetProperty("org.freedesktop.Secret.Collection.Items")
if err != nil {
return []Item{}, err
}

items := []Item{}
for _, path := range val.Value().([]dbus.ObjectPath) {
items = append(items, *NewItem(collection.conn, path))
}

return items, nil
}


// Delete (OUT ObjectPath prompt);
func (collection *Collection) Delete() error {
var prompt dbus.ObjectPath

err := collection.dbus.Call("org.freedesktop.Secret.Collection.Delete", 0).Store(&prompt)
if err != nil {
return err
}

if isPrompt(prompt) {
prompt := NewPrompt(collection.conn, prompt)

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

return nil
}


// SearchItems (IN Dict<String,String> attributes, OUT Array<ObjectPath> results);
func (collection *Collection) SearchItems(profile string) ([]Item, error) {
attributes := make(map[string]string)
attributes["profile"] = profile

var paths []dbus.ObjectPath

err := collection.dbus.Call("org.freedesktop.Secret.Collection.SearchItems", 0, attributes).Store(&paths)
if err != nil {
return []Item{}, err
}

items := []Item{}
for _, path := range paths {
items = append(items, *NewItem(collection.conn, path))
}

return items, nil
}


// CreateItem (IN Dict<String,Variant> properties, IN Secret secret, IN Boolean replace, OUT ObjectPath item, OUT ObjectPath prompt);
func (collection *Collection) CreateItem(label string, secret *Secret, replace bool) (*Item, error) {
properties := make(map[string]dbus.Variant)
attributes := make(map[string]string)

attributes["profile"] = label
properties["org.freedesktop.Secret.Item.Label"] = dbus.MakeVariant(label)
properties["org.freedesktop.Secret.Item.Attributes"] = dbus.MakeVariant(attributes)

var path dbus.ObjectPath
var prompt dbus.ObjectPath

err := collection.dbus.Call("org.freedesktop.Secret.Collection.CreateItem", 0, properties, secret, replace).Store(&path, &prompt)
if err != nil {
return &Item{}, err
}

if isPrompt(prompt) {
prompt := NewPrompt(collection.conn, prompt)

result, err := prompt.Prompt()
if err != nil {
return &Item{}, err
}

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

return NewItem(collection.conn, path), nil
}


// READ Boolean Locked;
func (collection *Collection) Locked() (bool, error) {
val, err := collection.dbus.GetProperty("org.freedesktop.Secret.Collection.Locked")
if err != nil {
return true, err
}

return val.Value().(bool), nil
}

77
item.go Normal file
View File

@ -0,0 +1,77 @@
package libsecret

import "github.com/godbus/dbus"


type Item struct {
conn *dbus.Conn
dbus dbus.BusObject
}


func NewItem(conn *dbus.Conn, path dbus.ObjectPath) *Item {
return &Item{
conn: conn,
dbus: conn.Object(DBUS_SERVICE_NAME, path),
}
}


func (item Item) Path() dbus.ObjectPath {
return item.dbus.Path()
}


// READWRITE String Label;
func (item *Item) Label() (string, error) {
val, err := item.dbus.GetProperty("org.freedesktop.Secret.Item.Label")
if err != nil {
return "", err
}

return val.Value().(string), nil
}


// READ Boolean Locked;
func (item *Item) Locked() (bool, error) {
val, err := item.dbus.GetProperty("org.freedesktop.Secret.Item.Locked")
if err != nil {
return true, err
}

return val.Value().(bool), nil
}


// GetSecret (IN ObjectPath session, OUT Secret secret);
func (item *Item) GetSecret(session *Session) (*Secret, error) {
secret := Secret{}

err := item.dbus.Call("org.freedesktop.Secret.Item.GetSecret", 0, session.Path()).Store(&secret)
if err != nil {
return &Secret{}, err
}

return &secret, nil
}


// Delete (OUT ObjectPath Prompt);
func (item *Item) Delete() error {
var prompt dbus.ObjectPath

err := item.dbus.Call("org.freedesktop.Secret.Item.Delete", 0).Store(&prompt)
if err != nil {
return err
}

if isPrompt(prompt) {
prompt := NewPrompt(item.conn, prompt)
if _, err := prompt.Prompt(); err != nil {
return err
}
}

return nil
}

55
prompt.go Normal file
View File

@ -0,0 +1,55 @@
package libsecret

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


type Prompt struct {
conn *dbus.Conn
dbus dbus.BusObject
}


func NewPrompt(conn *dbus.Conn, path dbus.ObjectPath) *Prompt {
return &Prompt{
conn: conn,
dbus: conn.Object(DBUS_SERVICE_NAME, path),
}
}


func (prompt Prompt) Path() dbus.ObjectPath {
return prompt.dbus.Path()
}


func isPrompt(path dbus.ObjectPath) bool {
promptPath := DBUS_PATH + "/prompt/"
return strings.HasPrefix(string(path), promptPath)
}


// Prompt (IN String window-id);
func (prompt *Prompt) Prompt() (*dbus.Variant, error) {
// prompts are asynchronous so we connect to the signal
// and block with a channel until we get a response
c := make(chan *dbus.Signal, 10)
defer close(c)

prompt.conn.Signal(c)
defer prompt.conn.RemoveSignal(c)

err := prompt.dbus.Call("org.freedesktop.Secret.Prompt.Prompt", 0, "").Store()
if err != nil {
return &dbus.Variant{}, err
}

for {
if result := <-c; result.Path == prompt.Path() {
value := result.Body[1].(dbus.Variant)
return &value, nil
}
}
}

21
secret.go Normal file
View File

@ -0,0 +1,21 @@
package libsecret

import "github.com/godbus/dbus"


type Secret struct {
Session dbus.ObjectPath
Parameters []byte
Value []byte
ContentType string
}


func NewSecret(session *Session, params []byte, value []byte, contentType string) *Secret {
return &Secret{
Session: session.Path(),
Parameters: params,
Value: value,
ContentType: contentType,
}
}

141
service.go Normal file
View File

@ -0,0 +1,141 @@
package libsecret

import "github.com/godbus/dbus"


const (
DBUS_SERVICE_NAME = "org.freedesktop.secrets"
DBUS_PATH = "/org/freedesktop/secrets"
)

type DBusObject interface {
Path() dbus.ObjectPath
}


type Service struct {
conn *dbus.Conn
dbus dbus.BusObject
}


func NewService() (*Service, error) {
conn, err := dbus.SessionBus()
if err != nil {
return &Service{}, err
}

return &Service{
conn: conn,
dbus: conn.Object(DBUS_SERVICE_NAME, DBUS_PATH),
}, nil
}


func (service Service) Path() dbus.ObjectPath {
return service.dbus.Path()
}


// OpenSession (IN String algorithm, IN Variant input, OUT Variant output, OUT ObjectPath result);
func (service *Service) Open() (*Session, error) {
var output dbus.Variant
var path dbus.ObjectPath

err := service.dbus.Call("org.freedesktop.Secret.Service.OpenSession", 0, "plain", dbus.MakeVariant("")).Store(&output, &path)
if err != nil {
return &Session{}, err
}

return NewSession(service.conn, path), nil
}


// READ Array<ObjectPath> Collections;
func (service *Service) Collections() ([]Collection, error) {
val, err := service.dbus.GetProperty("org.freedesktop.Secret.Service.Collections")
if err != nil {
return []Collection{}, err
}

collections := []Collection{}
for _, path := range val.Value().([]dbus.ObjectPath) {
collections = append(collections, *NewCollection(service.conn, path))
}

return collections, nil
}


// CreateCollection (IN Dict<String,Variant> properties, IN String alias, OUT ObjectPath collection, OUT ObjectPath prompt);
func (service *Service) CreateCollection(label string) (*Collection, error) {
properties := make(map[string]dbus.Variant)
properties["org.freedesktop.Secret.Collection.Label"] = dbus.MakeVariant(label)

var path dbus.ObjectPath
var prompt dbus.ObjectPath

err := service.dbus.Call("org.freedesktop.Secret.Service.CreateCollection", 0, properties, "").Store(&path, &prompt)
if err != nil {
return &Collection{}, err
}

if isPrompt(prompt) {
prompt := NewPrompt(service.conn, prompt)

result, err := prompt.Prompt()
if err != nil {
return &Collection{}, err
}

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

return NewCollection(service.conn, path), nil
}


// Unlock (IN Array<ObjectPath> objects, OUT Array<ObjectPath> unlocked, OUT ObjectPath prompt);
func (service *Service) Unlock(object DBusObject) error {
objects := []dbus.ObjectPath{object.Path()}

var unlocked []dbus.ObjectPath
var prompt dbus.ObjectPath

err := service.dbus.Call("org.freedesktop.Secret.Service.Unlock", 0, objects).Store(&unlocked, &prompt)
if err != nil {
return err
}

if isPrompt(prompt) {
prompt := NewPrompt(service.conn, prompt)
if _, err := prompt.Prompt(); err != nil {
return err
}
}

return nil
}


// Lock (IN Array<ObjectPath> objects, OUT Array<ObjectPath> locked, OUT ObjectPath Prompt);
func (service *Service) Lock(object DBusObject) error {
objects := []dbus.ObjectPath{object.Path()}

var locked []dbus.ObjectPath
var prompt dbus.ObjectPath

err := service.dbus.Call("org.freedesktop.Secret.Service.Lock", 0, objects).Store(&locked, &prompt)
if err != nil {
return err
}

if isPrompt(prompt) {
prompt := NewPrompt(service.conn, prompt)
if _, err := prompt.Prompt(); err != nil {
return err
}
}

return nil
}

22
session.go Normal file
View File

@ -0,0 +1,22 @@
package libsecret

import "github.com/godbus/dbus"


type Session struct {
conn *dbus.Conn
dbus dbus.BusObject
}


func NewSession(conn *dbus.Conn, path dbus.ObjectPath) *Session {
return &Session{
conn: conn,
dbus: conn.Object(DBUS_SERVICE_NAME, path),
}
}


func (session Session) Path() dbus.ObjectPath {
return session.dbus.Path()
}