102 lines
1.8 KiB
Go
102 lines
1.8 KiB
Go
package clipboard
|
|
|
|
import (
|
|
"errors"
|
|
|
|
systemclipboard "github.com/atotto/clipboard"
|
|
|
|
"git.julianfamily.org/keepassgo/vault"
|
|
)
|
|
|
|
var ErrUnsupportedTarget = errors.New("unsupported clipboard target")
|
|
var ErrWriteFailed = errors.New("clipboard write failed")
|
|
|
|
type Target string
|
|
|
|
const (
|
|
TargetUsername Target = "username"
|
|
TargetPassword Target = "password"
|
|
TargetURL Target = "url"
|
|
)
|
|
|
|
type Writer interface {
|
|
WriteText(text string) error
|
|
}
|
|
|
|
type Service struct {
|
|
Writer Writer
|
|
}
|
|
|
|
func (s Service) Copy(model vault.Model, entryID string, target Target) error {
|
|
entry, err := findEntry(model, entryID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
content, err := contentForTarget(entry, target)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := s.writer().WriteText(content); err != nil {
|
|
return writeError{err: err}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s Service) writer() Writer {
|
|
if s.Writer != nil {
|
|
return s.Writer
|
|
}
|
|
return systemWriter{}
|
|
}
|
|
|
|
func WriteText(text string) error {
|
|
return systemWriter{}.WriteText(text)
|
|
}
|
|
|
|
func findEntry(model vault.Model, entryID string) (vault.Entry, error) {
|
|
for _, entry := range model.Entries {
|
|
if entry.ID == entryID {
|
|
return entry, nil
|
|
}
|
|
}
|
|
return vault.Entry{}, vault.ErrEntryNotFound
|
|
}
|
|
|
|
func contentForTarget(entry vault.Entry, target Target) (string, error) {
|
|
switch target {
|
|
case TargetUsername:
|
|
return entry.Username, nil
|
|
case TargetPassword:
|
|
return entry.Password, nil
|
|
case TargetURL:
|
|
return entry.URL, nil
|
|
default:
|
|
return "", ErrUnsupportedTarget
|
|
}
|
|
}
|
|
|
|
type systemWriter struct{}
|
|
|
|
func (systemWriter) WriteText(text string) error {
|
|
return systemclipboard.WriteAll(text)
|
|
}
|
|
|
|
type writeError struct {
|
|
err error
|
|
}
|
|
|
|
func (e writeError) Error() string {
|
|
return ErrWriteFailed.Error()
|
|
}
|
|
|
|
func (e writeError) Unwrap() error {
|
|
return e.err
|
|
}
|
|
|
|
func (e writeError) Is(target error) bool {
|
|
return target == ErrWriteFailed
|
|
}
|