diff --git a/.gitignore b/.gitignore index b6643a6..79a0a55 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ # The binaries. chasquid -chasquid-userdb +cmd/chasquid-util/chasquid-util # Exclude any .pem files, to prevent accidentally including test keys and # certificates. diff --git a/cmd/chasquid-util/chasquid-util.go b/cmd/chasquid-util/chasquid-util.go index eca4aaf..9ec05e4 100644 --- a/cmd/chasquid-util/chasquid-util.go +++ b/cmd/chasquid-util/chasquid-util.go @@ -11,6 +11,7 @@ import ( "blitiri.com.ar/go/chasquid/internal/aliases" "blitiri.com.ar/go/chasquid/internal/config" + "blitiri.com.ar/go/chasquid/internal/envelope" "blitiri.com.ar/go/chasquid/internal/normalize" "blitiri.com.ar/go/chasquid/internal/userdb" @@ -22,23 +23,36 @@ import ( // Usage, which doubles as parameter definitions thanks to docopt. const usage = ` Usage: - chasquid-util adduser [--password=] - chasquid-util removeuser - chasquid-util authenticate [--password=] - chasquid-util check-userdb - chasquid-util aliases-resolve
- chasquid-util print-config + chasquid-util [options] user-add [--password=] + chasquid-util [options] user-remove + chasquid-util [options] authenticate [--password=] + chasquid-util [options] check-userdb + chasquid-util [options] aliases-resolve
+ chasquid-util [options] print-config + +Options: + -C --configdir= Configuration directory ` // Command-line arguments. var args map[string]interface{} +// Globals, loaded from top-level options. +var ( + configDir = "/etc/chasquid" +) + func main() { args, _ = docopt.Parse(usage, nil, true, "", false) + // Load globals. + if d, ok := args["--configdir"].(string); ok { + configDir = d + } + commands := map[string]func(){ - "adduser": AddUser, - "removeuser": RemoveUser, + "user-add": UserAdd, + "user-remove": UserRemove, "authenticate": Authenticate, "check-userdb": CheckUserDB, "aliases-resolve": AliasesResolve, @@ -57,9 +71,37 @@ func Fatalf(s string, arg ...interface{}) { os.Exit(1) } -// chasquid-util check-userdb +func userDBForDomain(domain string) string { + if domain == "" { + domain = args[""].(string) + } + return configDir + "/domains/" + domain + "/users" +} + +func userDBFromArgs(create bool) (string, string, *userdb.DB) { + username := args[""].(string) + user, domain := envelope.Split(username) + + db, err := userdb.Load(userDBForDomain(domain)) + if err != nil { + if create && os.IsNotExist(err) { + fmt.Println("Creating database") + } else { + Fatalf("Error loading database: %v", err) + } + } + + user, err = normalize.User(user) + if err != nil { + Fatalf("Error normalizing user: %v", err) + } + + return user, domain, db +} + +// chasquid-util check-userdb func CheckUserDB() { - _, err := userdb.Load(args[""].(string)) + _, err := userdb.Load(userDBForDomain("")) if err != nil { Fatalf("Error loading database: %v", err) } @@ -67,25 +109,12 @@ func CheckUserDB() { fmt.Println("Database loaded") } -// chasquid-util adduser [--password=] -func AddUser() { - db, err := userdb.Load(args[""].(string)) - if err != nil { - if os.IsNotExist(err) { - fmt.Println("Creating database") - } else { - Fatalf("Error loading database: %v", err) - } - } - - user, err := normalize.User(args[""].(string)) - if err != nil { - Fatalf("Error normalizing user: %v", err) - } - +// chasquid-util user-add [--password=] +func UserAdd() { + user, _, db := userDBFromArgs(true) password := getPassword() - err = db.AddUser(user, password) + err := db.AddUser(user, password) if err != nil { Fatalf("Error adding user: %v", err) } @@ -98,15 +127,12 @@ func AddUser() { fmt.Println("Added user") } -// chasquid-util authenticate [--password=] +// chasquid-util authenticate [--password=] func Authenticate() { - db, err := userdb.Load(args[""].(string)) - if err != nil { - Fatalf("Error loading database: %v", err) - } + user, _, db := userDBFromArgs(false) password := getPassword() - ok := db.Authenticate(args[""].(string), password) + ok := db.Authenticate(user, password) if ok { fmt.Println("Authentication succeeded") } else { @@ -141,19 +167,16 @@ func getPassword() string { return string(p1) } -// chasquid-util removeuser -func RemoveUser() { - db, err := userdb.Load(args[""].(string)) - if err != nil { - Fatalf("Error loading database: %v", err) - } +// chasquid-util user-remove +func UserRemove() { + user, _, db := userDBFromArgs(false) - present := db.RemoveUser(args[""].(string)) + present := db.RemoveUser(user) if !present { Fatalf("Unknown user") } - err = db.Write() + err := db.Write() if err != nil { Fatalf("Error writing database: %v", err) } @@ -161,9 +184,8 @@ func RemoveUser() { fmt.Println("Removed user") } -// chasquid-util aliases-resolve
+// chasquid-util aliases-resolve
func AliasesResolve() { - configDir := args[""].(string) conf, err := config.Load(configDir + "/chasquid.conf") if err != nil { Fatalf("Error reading config") @@ -206,9 +228,8 @@ func AliasesResolve() { } -// chasquid-util print-config +// chasquid-util print-config func PrintConfig() { - configDir := args[""].(string) conf, err := config.Load(configDir + "/chasquid.conf") if err != nil { Fatalf("Error reading config") diff --git a/cmd/chasquid-util/test.sh b/cmd/chasquid-util/test.sh new file mode 100755 index 0000000..812c8e1 --- /dev/null +++ b/cmd/chasquid-util/test.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +set -e +. $(dirname ${0})/../../test/util/lib.sh + +init + +go build || exit 1 + +function r() { + ./chasquid-util -C .config "$@" +} + +function check_userdb() { + if ! r check-userdb domain > /dev/null; then + echo check-userdb failed + exit 1 + fi +} + + +mkdir -p .config/domains/domain +touch .config/chasquid.conf + +if ! r print-config > /dev/null; then + echo print-config failed + exit 1 +fi + +if ! r user-add user@domain --password=passwd > /dev/null; then + echo user-add failed + exit 1 +fi +check_userdb + +if ! r authenticate user@domain --password=passwd > /dev/null; then + echo authenticate failed + exit 1 +fi + +if r authenticate user@domain --password=abcd > /dev/null; then + echo authenticate with bad password worked + exit 1 +fi + +if ! r user-remove user@domain > /dev/null; then + echo user-remove failed + exit 1 +fi +check_userdb + +if r authenticate user@domain --password=passwd > /dev/null; then + echo authenticate for removed user worked + exit 1 +fi + +echo "alias: user@somewhere" > .config/domains/domain/aliases +A=$(r aliases-resolve alias@domain | grep somewhere) +if [ "$A" != "(email) user@somewhere" ]; then + echo aliases-resolve failed + echo output: "$A" + exit 1 +fi + +C=$(r print-config | grep hostname) +if [ "$C" != "hostname: \"$HOSTNAME\"" ]; then + echo print-config failed + echo output: "$C" + exit 1 +fi + +success diff --git a/test/util/lib.sh b/test/util/lib.sh index 6c2924b..53b47dc 100644 --- a/test/util/lib.sh +++ b/test/util/lib.sh @@ -42,7 +42,8 @@ function add_user() { CONFDIR="${CONFDIR:-config}" mkdir -p "${CONFDIR}/domains/${1}/" go run ${TBASE}/../../cmd/chasquid-util/chasquid-util.go \ - adduser "${CONFDIR}/domains/${1}/users" "${2}" \ + -C "${CONFDIR}" \ + user-add "$2@$1" \ --password "${3}" \ >> .add_user_logs }