mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2025-10-28 12:45:47 +00:00
feat: allow users config from file
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -5,4 +5,7 @@ internal/assets/dist
|
|||||||
tinyauth
|
tinyauth
|
||||||
|
|
||||||
# dev docker compose
|
# dev docker compose
|
||||||
docker-compose.dev.yml
|
docker-compose.dev.yml
|
||||||
|
|
||||||
|
# users file
|
||||||
|
users.txt
|
||||||
31
cmd/root.go
31
cmd/root.go
@@ -2,6 +2,7 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"tinyauth/internal/api"
|
"tinyauth/internal/api"
|
||||||
"tinyauth/internal/assets"
|
"tinyauth/internal/assets"
|
||||||
@@ -36,10 +37,30 @@ var rootCmd = &cobra.Command{
|
|||||||
validateErr := validator.Struct(config)
|
validateErr := validator.Struct(config)
|
||||||
HandleError(validateErr, "Invalid config")
|
HandleError(validateErr, "Invalid config")
|
||||||
|
|
||||||
// Create users list
|
// Parse users
|
||||||
log.Info().Msg("Creating users list")
|
log.Info().Msg("Parsing users")
|
||||||
userList, createErr := utils.CreateUsersList(config.Users)
|
|
||||||
HandleError(createErr, "Failed to create users list")
|
if config.UsersFile == "" && config.Users == "" {
|
||||||
|
log.Fatal().Msg("No users provided")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
users := config.Users
|
||||||
|
|
||||||
|
if config.UsersFile != "" {
|
||||||
|
log.Info().Msg("Reading users from file")
|
||||||
|
usersFromFile, readErr := utils.GetUsersFromFile(config.UsersFile)
|
||||||
|
HandleError(readErr, "Failed to read users from file")
|
||||||
|
usersFromFileParsed := strings.Join(strings.Split(usersFromFile, "\n"), ",")
|
||||||
|
if users != "" {
|
||||||
|
users = users + "," + usersFromFileParsed
|
||||||
|
} else {
|
||||||
|
users = usersFromFileParsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
userList, createErr := utils.ParseUsers(users)
|
||||||
|
HandleError(createErr, "Failed to parse users")
|
||||||
|
|
||||||
// Start server
|
// Start server
|
||||||
log.Info().Msg("Starting server")
|
log.Info().Msg("Starting server")
|
||||||
@@ -68,10 +89,12 @@ func init() {
|
|||||||
rootCmd.Flags().String("secret", "", "Secret to use for the cookie.")
|
rootCmd.Flags().String("secret", "", "Secret to use for the cookie.")
|
||||||
rootCmd.Flags().String("app-url", "", "The tinyauth URL.")
|
rootCmd.Flags().String("app-url", "", "The tinyauth URL.")
|
||||||
rootCmd.Flags().String("users", "", "Comma separated list of users in the format username:bcrypt-hashed-password.")
|
rootCmd.Flags().String("users", "", "Comma separated list of users in the format username:bcrypt-hashed-password.")
|
||||||
|
rootCmd.Flags().String("users-file", "", "Path to a file containing users in the format username:bcrypt-hashed-password.")
|
||||||
viper.BindEnv("port", "PORT")
|
viper.BindEnv("port", "PORT")
|
||||||
viper.BindEnv("address", "ADDRESS")
|
viper.BindEnv("address", "ADDRESS")
|
||||||
viper.BindEnv("secret", "SECRET")
|
viper.BindEnv("secret", "SECRET")
|
||||||
viper.BindEnv("app-url", "APP_URL")
|
viper.BindEnv("app-url", "APP_URL")
|
||||||
viper.BindEnv("users", "USERS")
|
viper.BindEnv("users", "USERS")
|
||||||
|
viper.BindEnv("users-file", "USERS_FILE")
|
||||||
viper.BindPFlags(rootCmd.Flags())
|
viper.BindPFlags(rootCmd.Flags())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ type Config struct {
|
|||||||
Address string `mapstructure:"address, ip4_addr"`
|
Address string `mapstructure:"address, ip4_addr"`
|
||||||
Secret string `validate:"required,len=32" mapstructure:"secret"`
|
Secret string `validate:"required,len=32" mapstructure:"secret"`
|
||||||
AppURL string `validate:"required,url" mapstructure:"app-url"`
|
AppURL string `validate:"required,url" mapstructure:"app-url"`
|
||||||
Users string `validate:"required" mapstructure:"users"`
|
Users string `mapstructure:"users"`
|
||||||
|
UsersFile string `mapstructure:"users-file"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserContext struct {
|
type UserContext struct {
|
||||||
|
|||||||
@@ -3,16 +3,17 @@ package utils
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"tinyauth/internal/types"
|
"tinyauth/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateUsersList(users string) (types.UserList, error) {
|
func ParseUsers(users string) (types.UserList, error) {
|
||||||
var userList types.UserList
|
var userList types.UserList
|
||||||
userListString := strings.Split(users, ",")
|
userListString := strings.Split(users, ",")
|
||||||
|
|
||||||
if len(userListString) == 0 {
|
if len(userListString) == 0 {
|
||||||
return types.UserList{}, errors.New("no users found")
|
return types.UserList{}, errors.New("invalid user format")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, user := range userListString {
|
for _, user := range userListString {
|
||||||
@@ -41,4 +42,20 @@ func GetRootURL(urlSrc string) (string, error) {
|
|||||||
urlFinal := urlSplitted[len(urlSplitted)-2] + "." + urlSplitted[len(urlSplitted)-1]
|
urlFinal := urlSplitted[len(urlSplitted)-2] + "." + urlSplitted[len(urlSplitted)-1]
|
||||||
|
|
||||||
return urlFinal, nil
|
return urlFinal, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetUsersFromFile(usersFile string) (string, error) {
|
||||||
|
_, statErr := os.Stat(usersFile)
|
||||||
|
|
||||||
|
if statErr != nil {
|
||||||
|
return "", statErr
|
||||||
|
}
|
||||||
|
|
||||||
|
data, readErr := os.ReadFile(usersFile)
|
||||||
|
|
||||||
|
if readErr != nil {
|
||||||
|
return "", readErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(data), nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user