package main import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "os" "gitea.kleinsense.nl/DariusKlein/kleinTodo/client/todo/clientCommon/config" "gitea.kleinsense.nl/DariusKlein/kleinTodo/client/todo/httpClient" "gitea.kleinsense.nl/DariusKlein/kleinTodo/common" "github.com/BurntSushi/toml" "github.com/urfave/cli/v3" ) // Login Command func Login() *cli.Command { return &cli.Command{ Name: "login", Usage: "Login to kleinTodo server", Action: loginAction, Flags: loginFlags(), } } // loginFlags Register cli flags func loginFlags() []cli.Flag { return []cli.Flag{ &cli.StringFlag{ Name: usernameFlagName, Aliases: []string{"u"}, Required: false, Value: cfg.Server.Credentials.Username, }, &cli.StringFlag{ Name: passwordFlagName, Aliases: []string{"p"}, Required: false, Value: cfg.Server.Credentials.Password, }, &cli.StringFlag{ Name: serverUrlFlagName, Aliases: []string{"url"}, Required: false, Value: cfg.Server.Url, }, } } // loginAction logic for Template func loginAction(context context.Context, c *cli.Command) error { var username = c.String(usernameFlagName) var password = c.String(passwordFlagName) var serverUrl = c.String(serverUrlFlagName) token, err := loginAndGetToken(serverUrl, username, password) if err != nil { return err } cfg.Server.Token = token if (cfg.Server.Credentials.Username != username || cfg.Server.Credentials.Password != password) && common.AskUserBool("Do you wish to save your credentials? (WARNING: stored in plaintext)") { cfg.Server.Credentials.Username = username cfg.Server.Credentials.Password = password } if cfg.Server.Url != serverUrl && common.AskUserBool("Do you wish to save your chosen server url?") { cfg.Server.Url = serverUrl } path, configPath, err := config.GetConfigPath() if err != nil { return err } if err = os.MkdirAll(path, 0770); err != nil { return err } configBytes, err := toml.Marshal(cfg) err = os.WriteFile(configPath, configBytes, 0644) return nil } func loginAndGetToken(url, username, password string) (string, error) { credentials := common.Credentials{ Username: username, Password: password, } payload, err := json.Marshal(credentials) if err != nil { return "", fmt.Errorf("error marshaling credentials: %w", err) } req, err := http.NewRequest("POST", url, bytes.NewBuffer(payload)) if err != nil { return "", fmt.Errorf("error creating request: %w", err) } req.Header.Set("Content-Type", "application/json") resp, err := httpClient.GetHttpClient("").Do(req) if err != nil { return "", fmt.Errorf("error sending request: %w", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) return "", fmt.Errorf("login failed with status %d: %s", resp.StatusCode, string(body)) } token := resp.Header.Get(common.AuthHeader) if token == "" { return "", fmt.Errorf("auth token not found in response header") } return token, nil }