mirror of
https://github.com/tinyauthapp/tinyauth.git
synced 2026-08-29 09:23:32 +08:00
feat: unified config (#533)
* chore: add yaml config ref * feat: add initial implementation of a traefik like cli * refactor: remove dependency on traefik * chore: update example env * refactor: update build * chore: remove unused code * fix: fix translations not loading * feat: add experimental config file support * chore: mod tidy * fix: review comments * refactor: move tinyauth to separate package * chore: add quotes to all env variables * chore: resolve go mod and sum conflicts * chore: go mod tidy * fix: review comments
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/charmbracelet/huh"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/traefik/paerser/cli"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type CreateUserConfig struct {
|
||||
Interactive bool `description:"Create a user interactively."`
|
||||
Docker bool `description:"Format output for docker."`
|
||||
Username string `description:"Username."`
|
||||
Password string `description:"Password."`
|
||||
}
|
||||
|
||||
func NewCreateUserConfig() *CreateUserConfig {
|
||||
return &CreateUserConfig{
|
||||
Interactive: false,
|
||||
Docker: false,
|
||||
Username: "",
|
||||
Password: "",
|
||||
}
|
||||
}
|
||||
|
||||
func createUserCmd() *cli.Command {
|
||||
tCfg := NewCreateUserConfig()
|
||||
|
||||
loaders := []cli.ResourceLoader{
|
||||
&cli.FlagLoader{},
|
||||
}
|
||||
|
||||
return &cli.Command{
|
||||
Name: "create",
|
||||
Description: "Create a user",
|
||||
Configuration: tCfg,
|
||||
Resources: loaders,
|
||||
Run: func(_ []string) error {
|
||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).With().Caller().Logger().Level(zerolog.InfoLevel)
|
||||
|
||||
if tCfg.Interactive {
|
||||
form := huh.NewForm(
|
||||
huh.NewGroup(
|
||||
huh.NewInput().Title("Username").Value(&tCfg.Username).Validate((func(s string) error {
|
||||
if s == "" {
|
||||
return errors.New("username cannot be empty")
|
||||
}
|
||||
return nil
|
||||
})),
|
||||
huh.NewInput().Title("Password").Value(&tCfg.Password).Validate((func(s string) error {
|
||||
if s == "" {
|
||||
return errors.New("password cannot be empty")
|
||||
}
|
||||
return nil
|
||||
})),
|
||||
huh.NewSelect[bool]().Title("Format the output for Docker?").Options(huh.NewOption("Yes", true), huh.NewOption("No", false)).Value(&tCfg.Docker),
|
||||
),
|
||||
)
|
||||
|
||||
var baseTheme *huh.Theme = huh.ThemeBase()
|
||||
|
||||
err := form.WithTheme(baseTheme).Run()
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to run interactive prompt: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if tCfg.Username == "" || tCfg.Password == "" {
|
||||
return errors.New("username and password cannot be empty")
|
||||
}
|
||||
|
||||
log.Info().Str("username", tCfg.Username).Msg("Creating user")
|
||||
|
||||
passwd, err := bcrypt.GenerateFromPassword([]byte(tCfg.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to hash password: %w", err)
|
||||
}
|
||||
|
||||
// If docker format is enabled, escape the dollar sign
|
||||
passwdStr := string(passwd)
|
||||
if tCfg.Docker {
|
||||
passwdStr = strings.ReplaceAll(passwdStr, "$", "$$")
|
||||
}
|
||||
|
||||
log.Info().Str("user", fmt.Sprintf("%s:%s", tCfg.Username, passwdStr)).Msg("User created")
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user