From 88b5b941dfe73b2942f3c64551e34bad22cd182d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torjus=20H=C3=A5kestad?= Date: Wed, 19 Jan 2022 22:44:00 +0100 Subject: [PATCH] Add login to client --- cmd/client/client.go | 89 ++++++++++++++++++++++++++++++++++++++++---- go.mod | 1 + go.sum | 2 + http.go | 8 ++++ 4 files changed, 93 insertions(+), 7 deletions(-) diff --git a/cmd/client/client.go b/cmd/client/client.go index ce4c6b8..c805dd1 100644 --- a/cmd/client/client.go +++ b/cmd/client/client.go @@ -9,10 +9,13 @@ import ( "mime/multipart" "net/http" "os" + "strings" + "syscall" "time" "github.com/google/uuid" "github.com/urfave/cli/v2" + "golang.org/x/term" ) var ( @@ -32,19 +35,23 @@ func main() { Name: "config", Usage: "Path to config-file.", }, + &cli.StringFlag{ + Name: "url", + Usage: "Base url of gpaste server", + }, }, Commands: []*cli.Command{ { Name: "upload", Usage: "Upload file(s)", ArgsUsage: "FILE [FILE]...", - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "url", - Usage: "Base url of gpaste server", - }, - }, - Action: ActionUpload, + Action: ActionUpload, + }, + { + Name: "login", + Usage: "Login to gpaste server", + ArgsUsage: "USERNAME", + Action: ActionLogin, }, }, } @@ -105,3 +112,71 @@ func ActionUpload(c *cli.Context) error { } return nil } + +func ActionLogin(c *cli.Context) error { + username := c.Args().First() + if username == "" { + return cli.Exit("USERNAME not supplied.", 1) + } + password, err := readPassword() + if err != nil { + return fmt.Errorf("error reading password: %w", err) + } + + url := fmt.Sprintf("%s/api/login", c.String("url")) + client := &http.Client{} + // TODO: Change timeout + ctx, cancel := context.WithTimeout(c.Context, 10*time.Second) + defer cancel() + + body := new(bytes.Buffer) + requestData := struct { + Username string `json:"username"` + Password string `json:"password"` + }{ + Username: username, + Password: password, + } + encoder := json.NewEncoder(body) + if err := encoder.Encode(&requestData); err != nil { + return fmt.Errorf("error encoding response: %w", err) + } + req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, body) + if err != nil { + return fmt.Errorf("error creating request: %w", err) + } + + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("unable to perform request: %s", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return cli.Exit("got non-ok response from server", 0) + } + + responseData := struct { + Token string `json:"token"` + }{} + + decoder := json.NewDecoder(resp.Body) + if err := decoder.Decode(&responseData); err != nil { + return fmt.Errorf("unable to parse response: %s", err) + } + + fmt.Printf("Token: %s", responseData.Token) + + return nil +} + +func readPassword() (string, error) { + fmt.Print("Enter Password: ") + bytePassword, err := term.ReadPassword(int(syscall.Stdin)) + if err != nil { + return "", err + } + + password := string(bytePassword) + return strings.TrimSpace(password), nil +} diff --git a/go.mod b/go.mod index cad0232..49e2f3c 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( go.etcd.io/bbolt v1.3.6 go.uber.org/zap v1.20.0 golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 ) require ( diff --git a/go.sum b/go.sum index 8d8abd7..bb70fbd 100644 --- a/go.sum +++ b/go.sum @@ -71,6 +71,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/http.go b/http.go index 0580a6b..e4dc9ad 100644 --- a/http.go +++ b/http.go @@ -32,6 +32,12 @@ func NewHTTPServer(cfg *ServerConfig) *HTTPServer { srv.Users = NewMemoryUserStore() srv.Auth = NewAuthService(srv.Users, []byte(srv.config.SigningSecret)) + // Create initial user + // TODO: Do properly + user := &User{Username: "admin"} + user.SetPassword("admin") + srv.Users.Store(user) + r := chi.NewRouter() r.Use(middleware.RealIP) r.Use(middleware.RequestID) @@ -174,6 +180,8 @@ func (s *HTTPServer) HandlerAPILogin(w http.ResponseWriter, r *http.Request) { Token: token, } + s.Logger.Infow("User logged in.", "req_id", reqID, "username", expectedRequest.Username) + encoder := json.NewEncoder(w) if err := encoder.Encode(&response); err != nil { s.Logger.Infow("Error encoding json response to client.", "req_id", reqID, "error", err, "remote_addr", r.RemoteAddr)