From 7a3e2f9552a063ac99f87e47b38e3fd14919fdf0 Mon Sep 17 00:00:00 2001 From: Andinus Date: Thu, 26 Mar 2020 23:29:48 +0530 Subject: Add auth and user package --- auth/genid.go | 14 ++++++++++ auth/hashpass.go | 13 +++++++++ auth/register.go | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 auth/genid.go create mode 100644 auth/hashpass.go create mode 100644 auth/register.go (limited to 'auth') diff --git a/auth/genid.go b/auth/genid.go new file mode 100644 index 0000000..fea7ac9 --- /dev/null +++ b/auth/genid.go @@ -0,0 +1,14 @@ +package auth + +import ( + "crypto/rand" + "encoding/base64" +) + +// genID generates a random id string of length n. Don't forget to +// seed the random number generator otherwise it won't be random. +func genID(n int) string { + b := make([]byte, n/2) + rand.Read(b) + return base64.StdEncoding.EncodeToString(b) +} diff --git a/auth/hashpass.go b/auth/hashpass.go new file mode 100644 index 0000000..4e5041a --- /dev/null +++ b/auth/hashpass.go @@ -0,0 +1,13 @@ +package auth + +import ( + "golang.org/x/crypto/bcrypt" +) + +// hashPass takes a string as input and returns the hash of the +// password. +func hashPass(password string) (string, error) { + // 10 is the default cost. + bytes, err := bcrypt.GenerateFromPassword([]byte(password), 10) + return string(bytes), err +} diff --git a/auth/register.go b/auth/register.go new file mode 100644 index 0000000..c50f3f4 --- /dev/null +++ b/auth/register.go @@ -0,0 +1,81 @@ +package auth + +import ( + "log" + "strings" + "time" + + "tildegit.org/andinus/perseus/storage/sqlite3" + "tildegit.org/andinus/perseus/user" +) + +// Register takes in registration details and returns an error. If +// error doesn't equal nil then the registration was unsucessful. +// regInfo should have username, password & ip. +func Register(db *sqlite3.DB, regInfo map[string]string) error { + u := user.User{} + u.SetID(genID(64)) + u.SetUsername(strings.ToLower(regInfo["username"])) + + pass, err := hashPass(regInfo["password"]) + if err != nil { + log.Printf("auth/register.go: %s\n", + "hashPass func failed") + return err + } + u.SetPassword(pass) + + // Acquire write lock on the database. + db.Mu.Lock() + defer db.Mu.Unlock() + + err = insertRecords(db, u, regInfo) + return err +} + +func insertRecords(db *sqlite3.DB, u user.User, regInfo map[string]string) error { + // Start the transaction + tx, err := db.Conn.Begin() + if err != nil { + log.Printf("auth/register.go: %s\n", + "Failed to begin transaction") + return err + } + + // Insert the record into registration table + regStmt, err := db.Conn.Prepare(` +INSERT INTO registration(id, username, reg_time, reg_ip) values(?, ?, ?, ?)`) + if err != nil { + log.Printf("auth/register.go: %s\n", + "Failed to prepare statement") + return err + } + defer regStmt.Close() + + _, err = regStmt.Exec(u.ID(), u.Username(), time.Now().UTC(), regInfo["ip"]) + if err != nil { + log.Printf("auth/register.go: %s\n", + "Failed to execute statement") + return err + } + + // Insert the record into users table + usrStmt, err := db.Conn.Prepare(` +INSERT INTO users(id, username, password) values(?, ?, ?)`) + if err != nil { + log.Printf("auth/register.go: %s\n", + "Failed to prepare statement") + return err + } + defer usrStmt.Close() + + _, err = usrStmt.Exec(u.ID(), u.Username(), u.Password()) + if err != nil { + log.Printf("auth/register.go: %s\n", + "Failed to execute statement") + return err + } + + tx.Commit() + return err +} -- cgit 1.4.1-2-gfad0