From 8b3fd9b2402fb0853192b5a2e5c585cba774c56a Mon Sep 17 00:00:00 2001 From: Umar Getagazov Date: Sat, 20 Aug 2022 15:33:05 +0300 Subject: [PATCH] Fix -create-admin not working on non-POSIX systems --- flag.go | 67 ++++++++++++++++++++++++++++++++--------------------- user/net.go | 5 +++- 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/flag.go b/flag.go index d6b7bb3..a6901c9 100644 --- a/flag.go +++ b/flag.go @@ -1,6 +1,7 @@ package main import ( + "bufio" _ "embed" "flag" "fmt" @@ -8,13 +9,13 @@ import ( "log" "os" "path/filepath" - "syscall" + + "golang.org/x/term" "github.com/bouncepaw/mycorrhiza/cfg" "github.com/bouncepaw/mycorrhiza/files" "github.com/bouncepaw/mycorrhiza/user" "github.com/bouncepaw/mycorrhiza/version" - "golang.org/x/term" ) // CLI options are read and parsed here. @@ -64,38 +65,50 @@ func parseCliArgs() { } func createAdminCommand(name string) { - wr := log.Writer() - log.SetFlags(0) - if err := files.PrepareWikiRoot(); err != nil { - log.Fatal("error: ", err) + log.Fatal(err) } cfg.UseAuth = true cfg.AllowRegistration = true - - log.SetOutput(io.Discard) user.InitUserDatabase() - log.SetOutput(wr) - handle /*rug*/ := syscall.Stdin - if !term.IsTerminal(handle) { - log.Fatal("error: not a terminal") - } - - fmt.Print("Password: ") - passwordBytes, err := term.ReadPassword(handle) - fmt.Print("\n") + password, err := askPass("Password") if err != nil { - log.Fatal("error: ", err) + log.Fatal(err) } - - password := string(passwordBytes) - - log.SetOutput(io.Discard) - err = user.Register(name, password, "admin", "local", true) - log.SetOutput(wr) - - if err != nil { - log.Fatal("error: ", err) + if err := user.Register(name, password, "admin", "local", true); err != nil { + log.Fatal(err) } } + +func askPass(prompt string) (string, error) { + var password []byte + var err error + fd := int(os.Stdin.Fd()) + + if term.IsTerminal(fd) { + fmt.Printf("%s: ", prompt) + password, err = term.ReadPassword(int(os.Stdin.Fd())) + if err != nil { + return "", err + } + fmt.Println() + } else { + fmt.Fprintf(os.Stderr, "Warning: Reading password from stdin.\n") + // TODO: the buffering messes up repeated calls to readPassword + scanner := bufio.NewScanner(os.Stdin) + if !scanner.Scan() { + if err := scanner.Err(); err != nil { + return "", err + } + return "", io.ErrUnexpectedEOF + } + password = scanner.Bytes() + + if len(password) == 0 { + return "", fmt.Errorf("zero length password") + } + } + + return string(password), nil +} diff --git a/user/net.go b/user/net.go index d1799a3..61f65ff 100644 --- a/user/net.go +++ b/user/net.go @@ -12,9 +12,10 @@ import ( "strings" "time" + "golang.org/x/crypto/bcrypt" + "github.com/bouncepaw/mycorrhiza/cfg" "github.com/bouncepaw/mycorrhiza/util" - "golang.org/x/crypto/bcrypt" ) // CanProceed returns `true` if the user in `rq` has enough rights to access `route`. @@ -58,6 +59,8 @@ func Register(username, password, group, source string, force bool) error { return fmt.Errorf("username ā€˜%sā€™ is already taken", username) case !force && cfg.RegistrationLimit > 0 && Count() >= cfg.RegistrationLimit: return fmt.Errorf("reached the limit of registered users (%d)", cfg.RegistrationLimit) + case password == "": + return fmt.Errorf("password must not be empty") } hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)