From a572b24702633800b2b6744fc4361ad3f0ef54b9 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 11 Mar 2020 19:01:03 +0100 Subject: [PATCH] cmd/jouncectl: new command Allows to create users. --- cmd/jouncectl/main.go | 81 +++++++++++++++++++++++++++++++++++++++++++ db.go | 22 ++++++++++++ go.mod | 1 + go.sum | 8 +++++ 4 files changed, 112 insertions(+) create mode 100644 cmd/jouncectl/main.go diff --git a/cmd/jouncectl/main.go b/cmd/jouncectl/main.go new file mode 100644 index 0000000..a09c759 --- /dev/null +++ b/cmd/jouncectl/main.go @@ -0,0 +1,81 @@ +package main + +import ( + "flag" + "fmt" + "log" + "os" + + "git.sr.ht/~emersion/jounce" + "git.sr.ht/~emersion/jounce/config" + "golang.org/x/crypto/bcrypt" + "golang.org/x/crypto/ssh/terminal" +) + +const usage = `usage: jouncectl [-config path] [options...] + + create-user Create a new user + help Show this help message +` + +func init() { + flag.Usage = func() { + fmt.Fprintf(flag.CommandLine.Output(), usage) + } +} + +func main() { + var configPath string + flag.StringVar(&configPath, "config", "", "path to configuration file") + flag.Parse() + + var cfg *config.Server + if configPath != "" { + var err error + cfg, err = config.Load(configPath) + if err != nil { + log.Fatalf("failed to load config file: %v", err) + } + } else { + cfg = config.Defaults() + } + + db, err := jounce.OpenSQLDB(cfg.SQLDriver, cfg.SQLSource) + if err != nil { + log.Fatalf("failed to open database: %v", err) + } + + switch cmd := flag.Arg(0); cmd { + case "create-user": + username := flag.Arg(1) + if username == "" { + flag.Usage() + os.Exit(1) + } + + fmt.Printf("Password: ") + password, err := terminal.ReadPassword(int(os.Stdin.Fd())) + if err != nil { + log.Fatalf("failed to read password: %v", err) + } + fmt.Printf("\n") + + hashed, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost) + if err != nil { + log.Fatalf("failed to hash password: %v", err) + } + + user := jounce.User{ + Username: username, + Password: string(hashed), + } + if err := db.CreateUser(&user); err != nil { + log.Fatalf("failed to create user: %v", err) + } + default: + flag.Usage() + if cmd != "help" { + os.Exit(1) + } + } +} diff --git a/db.go b/db.go index d37c79d..dd33353 100644 --- a/db.go +++ b/db.go @@ -73,6 +73,28 @@ func (db *DB) ListUsers() ([]User, error) { return users, nil } +func (db *DB) CreateUser(user *User) error { + db.lock.Lock() + defer db.lock.Unlock() + + tx, err := db.db.Begin() + if err != nil { + return err + } + defer tx.Rollback() + + var password *string + if user.Password != "" { + password = &user.Password + } + _, err = tx.Exec("INSERT INTO User(username, password) VALUES (?, ?)", user.Username, password) + if err != nil { + return err + } + + return tx.Commit() +} + func (db *DB) ListNetworks(username string) ([]Network, error) { db.lock.RLock() defer db.lock.RUnlock() diff --git a/go.mod b/go.mod index 1f534b3..13373b9 100644 --- a/go.mod +++ b/go.mod @@ -4,5 +4,6 @@ go 1.13 require ( github.com/mattn/go-sqlite3 v2.0.3+incompatible + golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 gopkg.in/irc.v3 v3.1.0 ) diff --git a/go.sum b/go.sum index a109788..423a1f4 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,13 @@ github.com/mattn/go-sqlite3 v1.13.0 h1:LnJI81JidiW9r7pS/hXe6cFeO5EXNq7KbfvoJLRI69c= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA= +golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/irc.v3 v3.1.0 h1:AeDaEhQ/78gHfpbj/3mSi8FfiNIsFiVrWEgLzOwHWnU= gopkg.in/irc.v3 v3.1.0/go.mod h1:qE0DWv0j8Z8wCbFhA9783JBO0bufi3rttcV1Sjin8io=