From f836f40f898fbb9310f20e001f446e7796625514 Mon Sep 17 00:00:00 2001 From: endangered Date: Mon, 25 Nov 2019 06:58:44 +0930 Subject: [PATCH] Provide command line variables for initializing an admin user. Previously to get admin access on a fresh install I had to create a user in the web interface (to make sure the password hash/salt is properly setup) then manually change the role in the database to 'admin' using a postgresql client. This was a pain in the ass, and I think there really needs to be an easy way to create the admin user on the initial deployment. This solution fixes this, and adds documentation to the README file on how to use those variables. --- README.md | 9 ++++++++- lib/database/database.go | 3 +++ lib/database/ro.go | 5 +++++ lib/database/users.go | 40 +++++++++++++++++++++++++++++++++++++++- main.go | 7 +++++++ 5 files changed, 62 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7abb683..986d400 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,13 @@ You can run it (using `/var/lib/trantor` for storage): # $GOPATH/bin/trantor -assets $GOPATH/src/pkg/gitlab.com/trantor/trantor/ -store /var/lib/trantor ``` +The first time you run it, the database will be initialized. To initialize an admin user, include the -set-admin-user and -set-admin-pass variables +when you run it. The admin user will be initialized after the first time you run the application with these parameters, so there is no need to +include them on subsequent runs (but no harm in doing so). +``` +# $GOPATH/bin/trantor -assets $GOPATH/src/pkg/gitlab.com/trantor/trantor/ -store /var/lib/trantor -set-admin-user 'admin' -set-admin-pass 'MY_ADMIN_PASSWORD' +``` + Go to your browser to: http://localhost:8080 ### For developers @@ -49,7 +56,7 @@ $ go build Now you can run it: ``` -$ ./trantor +$ ./trantor -set-admin-user 'admin' -set-admin-pass 'MY_ADMIN_PASSWORD' ``` Go to your browser to: http://localhost:8080 diff --git a/lib/database/database.go b/lib/database/database.go index d18adbf..071871a 100644 --- a/lib/database/database.go +++ b/lib/database/database.go @@ -19,6 +19,7 @@ type DB interface { IsBookActive(id string) bool AddUser(name string, pass string) error AddRawUser(name string, hpass []byte, salt []byte, role string) error + SetAdminUser(name string, pass string) error GetRole(name string) (string, error) SetPassword(name string, pass string) error SetRole(name, role string) error @@ -140,6 +141,8 @@ CREATE INDEX IF NOT EXISTS books_lang_idx ON books (lang); CREATE INDEX IF NOT EXISTS books_isbn_idx ON books (isbn); CREATE INDEX IF NOT EXISTS books_active_idx ON books (active); + + -- Books trigram indexes CREATE INDEX IF NOT EXISTS books_title_idx ON books USING GIN (title gin_trgm_ops); CREATE INDEX IF NOT EXISTS books_contributor_idx ON books USING GIN (contributor gin_trgm_ops); diff --git a/lib/database/ro.go b/lib/database/ro.go index 6010a0f..ca3e7b7 100644 --- a/lib/database/ro.go +++ b/lib/database/ro.go @@ -53,6 +53,11 @@ func (db *roDB) AddRawUser(name string, hpass []byte, salt []byte, role string) return errors.New("RO database") } +func (db *roDB) SetAdminUser(name string, pass string) error { + return errors.New("RO database") +} + + func (db *roDB) GetRole(name string) (string, error) { return db.db.GetRole(name) } diff --git a/lib/database/users.go b/lib/database/users.go index 8a7591c..532f68e 100644 --- a/lib/database/users.go +++ b/lib/database/users.go @@ -45,6 +45,37 @@ func (db *pgDB) AddUser(name string, pass string) error { return db.AddRawUser(name, hpass, salt, "") } + +func (db *pgDB) SetAdminUser(name string, pass string) error { + + if !validAdminUserName(name) { + return errors.New("Invalid admin user name. Username needs to have at least 3 characters and can only be letters, numbers, '-', '_' and '.'.") + } + + num, err := db.sql.Model(&User{}).Where("lower(username) = lower(?)", name).Count() + if err != nil { + log.Error("Error on database checking user ", name, ": ", err) + return errors.New("An error happen on the database") + } + if num != 0 { + err := db.SetRole(name, "admin") + if err != nil { + log.Error("Error updating admin user ", name, ": ", err) + return errors.New("Error updating admin user") + } + return db.SetPassword(name, pass) + } + + hpass, salt, err := hashPass(pass) + if err != nil { + log.Error("Error hashing password: ", err) + return errors.New("An error happen storing the password") + } + return db.AddRawUser(name, hpass, salt, "admin") + +} + + func (db *pgDB) AddRawUser(name string, hpass []byte, salt []byte, role string) error { u := User{ Username: name, @@ -120,13 +151,20 @@ func (db *pgDB) getUser(name string) (User, error) { return user, err } -func validUserName(name string) bool { +func validAdminUserName(name string) bool { if len(name) < 3 { return false } if !alphaNumeric(name) { return false } + return true +} + +func validUserName(name string) bool { + if !validAdminUserName(name) { + return false + } switch name { case "", "admin", "webmaster", "postmaster", "info", "root", "news", "trantor", "librarian", "library", "imperial": return false diff --git a/main.go b/main.go index 65e39fb..37b1587 100644 --- a/main.go +++ b/main.go @@ -23,6 +23,8 @@ func main() { assetsPath = flag.String("assets", ".", "Path of the assets (templates, css, js, img)") hostname = flag.String("hostname", "xfmro77i3lixucja.onion", "Hostname of the website") loggerConfig = flag.String("logger-conf", "logger.xml", "xml configuration of the logger") + setAdminUser = flag.String("set-admin-user", "", "create/update this user to be admin if set-admin-pass is also specified") + setAdminPass = flag.String("set-admin-pass", "", "create/update admin user password if set-admin-user is also specified") ro = flag.Bool("ro", false, "read only mode") ) flag.Parse() @@ -40,6 +42,11 @@ func main() { Password: *dbPassword, Name: *dbName, }) + if err == nil { + if *setAdminUser != "" && *setAdminPass != "" { + db.SetAdminUser(*setAdminUser, *setAdminPass) + } + } if err != nil { log.Critical("Problem initializing database: ", err) os.Exit(1)