diff --git a/internal/config/config.go b/internal/config/config.go index 02756dad5..bf14a1aa0 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -4,9 +4,9 @@ import ( "os" "path/filepath" + "github.com/cli/cli/v2/internal/keyring" ghAuth "github.com/cli/go-gh/v2/pkg/auth" ghConfig "github.com/cli/go-gh/v2/pkg/config" - "github.com/zalando/go-keyring" ) const ( diff --git a/internal/keyring/keyring.go b/internal/keyring/keyring.go new file mode 100644 index 000000000..afb5025e6 --- /dev/null +++ b/internal/keyring/keyring.go @@ -0,0 +1,68 @@ +// Package keyring is a simple wrapper that adds timeouts to the zalando/go-keyring package. +package keyring + +import ( + "time" + + "github.com/zalando/go-keyring" +) + +type TimeoutError struct { + message string +} + +func (e *TimeoutError) Error() string { + return e.message +} + +// Set secret in keyring for user. +func Set(service, user, secret string) error { + ch := make(chan error, 1) + go func() { + defer close(ch) + ch <- keyring.Set(service, user, secret) + }() + select { + case err := <-ch: + return err + case <-time.After(3 * time.Second): + return &TimeoutError{"timeout while trying to set secret in keyring"} + } +} + +// Get secret from keyring given service and user name. +func Get(service, user string) (string, error) { + ch := make(chan struct { + val string + err error + }, 1) + go func() { + defer close(ch) + val, err := keyring.Get(service, user) + ch <- struct { + val string + err error + }{val, err} + }() + select { + case res := <-ch: + return res.val, res.err + case <-time.After(3 * time.Second): + return "", &TimeoutError{"timeout while trying to get secret from keyring"} + } +} + +// Delete secret from keyring. +func Delete(service, user string) error { + ch := make(chan error, 1) + go func() { + defer close(ch) + ch <- keyring.Delete(service, user) + }() + select { + case err := <-ch: + return err + case <-time.After(3 * time.Second): + return &TimeoutError{"timeout while trying to delete secret from keyring"} + } +}