package cmd import ( "fmt" "os" "github.com/spf13/cobra" "golang.org/x/term" "github.com/kanootoko/codevault/internal/runcmd" ) var addUserCmd = &cobra.Command{ Use: "add-user", Short: "Add or update a user in the database", Long: `Add or update a user in the database. Does not read the application config - only a database path is needed; if the database file does not exist it is created together with its schema.`, RunE: runAddUser, } func init() { addUserCmd.Flags().String("db-path", "./codevault.db", "Path to the SQLite database file") addUserCmd.Flags().String("login", "", "Login of the user to add or update") addUserCmd.Flags().String("password", "", "Password for the user (if omitted, prompted interactively; "+ "passing it as a flag can leak the password via shell history)") _ = addUserCmd.MarkFlagRequired("login") rootCmd.AddCommand(addUserCmd) } func runAddUser(cmd *cobra.Command, args []string) error { dbPath, err := cmd.Flags().GetString("db-path") if err != nil { return fmt.Errorf("error on getting db-path option: %w", err) } login, err := cmd.Flags().GetString("login") if err != nil { return fmt.Errorf("error on getting login option: %w", err) } password, err := cmd.Flags().GetString("password") if err != nil { return fmt.Errorf("error on getting password option: %w", err) } if password == "" { password, err = readPasswordWithConfirmation(cmd) if err != nil { return fmt.Errorf("error on reading password: %w", err) } } if err := runcmd.AddUser(dbPath, login, password); err != nil { return fmt.Errorf("error on adding user: %w", err) } cmd.Println("user saved successfully") return nil } func readPasswordWithConfirmation(cmd *cobra.Command) (string, error) { fd := int(os.Stdin.Fd()) cmd.Print("Password: ") password, err := term.ReadPassword(fd) cmd.Println() if err != nil { return "", fmt.Errorf("error on reading password: %w", err) } cmd.Print("Confirm password: ") confirmation, err := term.ReadPassword(fd) cmd.Println() if err != nil { return "", fmt.Errorf("error on reading password confirmation: %w", err) } if string(password) != string(confirmation) { return "", fmt.Errorf("passwords do not match") } return string(password), nil }