From e6f814952dfb4e8f5127220fd98e7d531cf27e8b Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 22 Mar 2019 22:35:10 +0200 Subject: [PATCH] Store everything in XDG_CONFIG_HOME, add `status` command --- auth/auth.go | 30 +++++++++++++++++++++++++++--- cmd/hydroxide/hydroxide.go | 14 ++++++++++++++ config/config.go | 27 +++++++++++++++++++++++++++ imap/database/user.go | 10 ++++++++-- 4 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 config/config.go diff --git a/auth/auth.go b/auth/auth.go index 26079e5..6d5c770 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -13,10 +13,13 @@ import ( "golang.org/x/crypto/nacl/secretbox" "golang.org/x/crypto/openpgp" + "github.com/emersion/hydroxide/config" "github.com/emersion/hydroxide/protonmail" ) -const authFile = "auth.json" +func authFilePath() (string, error) { + return config.Path("auth.json") +} type CachedAuth struct { protonmail.Auth @@ -26,7 +29,11 @@ type CachedAuth struct { } func readCachedAuths() (map[string]string, error) { - f, err := os.Open(authFile) + p, err := authFilePath() + if err != nil { + return nil, err + } + f, err := os.Open(p) if os.IsNotExist(err) { return nil, nil } else if err != nil { @@ -40,7 +47,11 @@ func readCachedAuths() (map[string]string, error) { } func saveAuths(auths map[string]string) error { - f, err := os.Create(authFile) + p, err := authFilePath() + if err != nil { + return err + } + f, err := os.Create(p) if err != nil { return err } @@ -123,6 +134,19 @@ func authenticate(c *protonmail.Client, cachedAuth *CachedAuth, username string) return c.Unlock(auth, cachedAuth.MailboxPassword) } +func ListUsernames() ([]string, error) { + auths, err := readCachedAuths() + if err != nil { + return nil, err + } + + l := make([]string, 0, len(auths)) + for username, _ := range auths { + l = append(l, username) + } + return l, nil +} + func GeneratePassword() (secretKey *[32]byte, password string, err error) { var key [32]byte if _, err = io.ReadFull(rand.Reader, key[:]); err != nil { diff --git a/cmd/hydroxide/hydroxide.go b/cmd/hydroxide/hydroxide.go index 7e29a7e..9dfb48e 100644 --- a/cmd/hydroxide/hydroxide.go +++ b/cmd/hydroxide/hydroxide.go @@ -138,6 +138,20 @@ func main() { } fmt.Println("Bridge password:", bridgePassword) + case "status": + usernames, err := auth.ListUsernames() + if err != nil { + log.Fatal(err) + } + + if len(usernames) == 0 { + fmt.Printf("No logged in user.\n") + } else { + fmt.Printf("%v logged in user(s):\n", len(usernames)) + for _, u := range usernames { + fmt.Printf("- %v\n", u) + } + } case "smtp": port := os.Getenv("PORT") if port == "" { diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..d1a2c19 --- /dev/null +++ b/config/config.go @@ -0,0 +1,27 @@ +package config + +import ( + "errors" + "os" + "path/filepath" +) + +func Path(filename string) (string, error) { + configHome := os.Getenv("XDG_CONFIG_HOME") + if configHome == "" { + home := os.Getenv("HOME") + if home == "" { + return "", errors.New("HOME not set") + } + configHome = filepath.Join(home, ".config") + } + + p := filepath.Join(configHome, "hydroxide", filename) + + dirname, _ := filepath.Split(p) + if err := os.MkdirAll(dirname, 0700); err != nil { + return "", err + } + + return p, nil +} diff --git a/imap/database/user.go b/imap/database/user.go index ada0cd8..bc3e8b2 100644 --- a/imap/database/user.go +++ b/imap/database/user.go @@ -6,6 +6,7 @@ import ( "github.com/boltdb/bolt" + "github.com/emersion/hydroxide/config" "github.com/emersion/hydroxide/protonmail" ) @@ -223,8 +224,13 @@ func (u *User) Close() error { return u.db.Close() } -func Open(path string) (*User, error) { - db, err := bolt.Open(path, 0700, nil) +func Open(filename string) (*User, error) { + p, err := config.Path(filename) + if err != nil { + return nil, err + } + + db, err := bolt.Open(p, 0700, nil) if err != nil { return nil, err }