summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndinus <andinus@nand.sh>2020-03-28 19:25:53 +0530
committerAndinus <andinus@nand.sh>2020-03-28 19:25:53 +0530
commit7b95d6b80dd2d1efb26f7c515383abd4f0dc9d42 (patch)
tree76dca236dc2d7c3be989896442cb3edfa1235e8d
parentb0b83af1c45c2d5ee587dc96847e25c95a3d50b0 (diff)
downloadperseus-7b95d6b80dd2d1efb26f7c515383abd4f0dc9d42.tar.gz
Prepare for rewrite on several functions
User struct now exports everything, encapsulation is not necessary
over here. Instead of introducing a new variable uInfo we'll use
user.User and pass that. Handlers & related functions will be
rewritten to work with this change. This will make it easier to work
on later as the program grows. I'm also rethinking error handling.
-rw-r--r--auth/login.go46
-rw-r--r--auth/register.go42
-rw-r--r--auth/token/add.go58
-rw-r--r--auth/token/generate.go14
-rw-r--r--auth/token/validate.go51
-rw-r--r--handler/web/login.go83
-rw-r--r--handler/web/page.go7
-rw-r--r--handler/web/register.go74
-rw-r--r--user/adduser.go4
-rw-r--r--user/getid.go4
-rw-r--r--user/user.go37
11 files changed, 13 insertions, 407 deletions
diff --git a/auth/login.go b/auth/login.go
deleted file mode 100644
index 99e74ba..0000000
--- a/auth/login.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package auth
-
-import (
-	"log"
-
-	"tildegit.org/andinus/perseus/storage/sqlite3"
-	"tildegit.org/andinus/perseus/user"
-)
-
-// Login takes in login details and returns an error. If error doesn't
-// equal nil then consider login failed.
-func Login(db *sqlite3.DB, uInfo map[string]string) error {
-	// Acquire read lock on the database.
-	db.Mu.RLock()
-	defer db.Mu.RUnlock()
-
-	u := user.User{}
-	u.SetUsername(uInfo["username"])
-
-	// Get password for this user from the database.
-	stmt, err := db.Conn.Prepare("SELECT password FROM users WHERE username = ?")
-	if err != nil {
-		log.Printf("auth/login.go: %s\n",
-			"failed to prepare statement")
-		return err
-	}
-	defer stmt.Close()
-
-	var pass string
-	err = stmt.QueryRow(u.Username()).Scan(&pass)
-	if err != nil {
-		log.Printf("auth/login.go: %s\n",
-			"query failed")
-		return err
-	}
-	u.SetPassword(pass)
-
-	// Check user's password.
-	err = checkPass(uInfo["password"], u.Password())
-	if err != nil {
-		log.Printf("auth/login.go: %s%s\n",
-			"user login failed, username: ", u.Username())
-	}
-
-	return err
-}
diff --git a/auth/register.go b/auth/register.go
deleted file mode 100644
index f946072..0000000
--- a/auth/register.go
+++ /dev/null
@@ -1,42 +0,0 @@
-package auth
-
-import (
-	"errors"
-	"log"
-	"regexp"
-	"strings"
-
-	"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 unsuccessful.
-// uInfo should have username & password.
-func Register(db *sqlite3.DB, uInfo map[string]string) error {
-	u := user.User{}
-	u.SetID(genID(64))
-	u.SetUsername(strings.ToLower(uInfo["username"]))
-
-	// Validate username
-	re := regexp.MustCompile("^[a-z0-9]*$")
-	if !re.MatchString(u.Username()) {
-		return errors.New("auth/register.go: invalid username")
-	}
-
-	// Validate password
-	if len(uInfo["password"]) < 8 {
-		return errors.New("auth/register.go: password too short")
-	}
-
-	pass, err := hashPass(uInfo["password"])
-	if err != nil {
-		log.Printf("auth/register.go: %s\n",
-			"hashPass func failed")
-		return err
-	}
-	u.SetPassword(pass)
-
-	err = u.AddUser(db)
-	return err
-}
diff --git a/auth/token/add.go b/auth/token/add.go
deleted file mode 100644
index eadc6dc..0000000
--- a/auth/token/add.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package token
-
-import (
-	"log"
-	"time"
-
-	"tildegit.org/andinus/perseus/storage/sqlite3"
-	"tildegit.org/andinus/perseus/user"
-)
-
-// AddToken will generate a random token, add it to database and
-// return the token.
-func AddToken(db *sqlite3.DB, uInfo map[string]string) (token string, err error) {
-	// Acquire write lock on the database.
-	db.Mu.Lock()
-	defer db.Mu.Unlock()
-
-	token = genToken(64)
-
-	u := user.User{}
-	u.SetUsername(uInfo["username"])
-
-	// Set user id from username.
-	err = u.GetID(db)
-	if err != nil {
-		log.Printf("auth/token.go: %s\n",
-			"failed to get id from username")
-		return
-	}
-
-	// Start the transaction
-	tx, err := db.Conn.Begin()
-	if err != nil {
-		log.Printf("auth/token.go: %s\n",
-			"failed to begin transaction")
-		return
-	}
-
-	stmt, err := db.Conn.Prepare(`
-INSERT INTO access(id, token, genTime) values(?, ?, ?)`)
-	if err != nil {
-		log.Printf("auth/token.go: %s\n",
-			"failed to prepare statement")
-		return
-	}
-	defer stmt.Close()
-
-	_, err = stmt.Exec(u.ID(), u.Username(), time.Now().UTC())
-	if err != nil {
-		log.Printf("auth/token.go: %s\n",
-			"failed to execute statement")
-		return
-	}
-
-	tx.Commit()
-	return
-
-}
diff --git a/auth/token/generate.go b/auth/token/generate.go
deleted file mode 100644
index 0c717d9..0000000
--- a/auth/token/generate.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package token
-
-import (
-	"crypto/rand"
-	"encoding/base64"
-)
-
-// genToken generates a random token string of length n. Don't forget to
-// seed the random number generator otherwise it won't be random.
-func genToken(n int) string {
-	b := make([]byte, n/2)
-	rand.Read(b)
-	return base64.StdEncoding.EncodeToString(b)
-}
diff --git a/auth/token/validate.go b/auth/token/validate.go
deleted file mode 100644
index f1ee149..0000000
--- a/auth/token/validate.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package token
-
-import (
-	"errors"
-	"log"
-
-	"tildegit.org/andinus/perseus/storage/sqlite3"
-	"tildegit.org/andinus/perseus/user"
-)
-
-// ValToken will validate the token and returns an error. If error
-// doesn't equal nil then consider token invalid.
-func ValToken(db *sqlite3.DB, uInfo map[string]string) error {
-	// Acquire read lock on the database.
-	db.Mu.RLock()
-	defer db.Mu.RUnlock()
-
-	u := user.User{}
-	u.SetUsername(uInfo["username"])
-
-	// Set user id from username.
-	err := u.GetID(db)
-	if err != nil {
-		log.Printf("auth/token.go: %s\n",
-			"failed to get id from username")
-		return err
-	}
-
-	// Check if user's token is valid.
-	stmt, err := db.Conn.Prepare("SELECT token FROM access WHERE id = ?")
-	if err != nil {
-		log.Printf("auth/token.go: %s\n",
-			"failed to prepare statement")
-		return err
-	}
-	defer stmt.Close()
-
-	var token string
-	err = stmt.QueryRow(u.ID()).Scan(&token)
-	if err != nil {
-		log.Printf("auth/token.go: %s\n",
-			"query failed")
-		return err
-	}
-
-	if token != uInfo["token"] {
-		err = errors.New("token mismatch")
-	}
-
-	return err
-}
diff --git a/handler/web/login.go b/handler/web/login.go
deleted file mode 100644
index 0c70b56..0000000
--- a/handler/web/login.go
+++ /dev/null
@@ -1,83 +0,0 @@
-package web
-
-import (
-	"fmt"
-	"html/template"
-	"log"
-	"net/http"
-	"time"
-
-	"tildegit.org/andinus/perseus/auth"
-	"tildegit.org/andinus/perseus/auth/token"
-	"tildegit.org/andinus/perseus/core"
-	"tildegit.org/andinus/perseus/storage/sqlite3"
-)
-
-// HandleLogin handles /login pages.
-func HandleLogin(w http.ResponseWriter, r *http.Request, db *sqlite3.DB) {
-	p := Page{Version: core.Version()}
-	error := []string{}
-	success := []string{}
-
-	switch r.Method {
-	case http.MethodGet:
-		t, _ := template.ParseFiles("web/login.html")
-		t.Execute(w, p)
-
-	case http.MethodPost:
-		if err := r.ParseForm(); err != nil {
-			log.Printf("web/login.go: 400 Bad Request :: %s", err.Error())
-			http.Error(w, "400 Bad Request", http.StatusBadRequest)
-			return
-		}
-
-		// Get form values
-		uInfo := make(map[string]string)
-		uInfo["username"] = r.FormValue("username")
-		uInfo["password"] = r.FormValue("password")
-
-		// Perform authentication
-		err := auth.Login(db, uInfo)
-
-		if err != nil {
-			log.Printf("web/login.go: %s :: %s :: %s",
-				"login failed",
-				uInfo["username"],
-				err.Error())
-
-			error = append(error,
-				fmt.Sprintf("Login failed"))
-
-			p.Error = error
-		} else {
-			success = append(success,
-				fmt.Sprintf("Login successful"))
-			p.Success = success
-
-			// Set token if login was successful.
-			token, err := token.AddToken(db, uInfo)
-			if err != nil {
-				log.Printf("web/login.go: %s :: %s :: %s",
-					"token generation failed",
-					uInfo["username"],
-					err.Error())
-
-				error = append(error,
-					fmt.Sprintf("Token generation failed"))
-			}
-			// If token was generated then ask browser to
-			// set it as cookie.
-			expiration := time.Now().Add(1 * 24 * time.Hour)
-			cookie := http.Cookie{Name: "token", Value: token, Expires: expiration}
-			http.SetCookie(w, &cookie)
-		}
-
-		t, _ := template.ParseFiles("web/login.html")
-		t.Execute(w, p)
-
-	default:
-		w.WriteHeader(http.StatusMethodNotAllowed)
-		log.Printf("web/login.go: %v not allowed on %v", r.Method, r.URL)
-	}
-
-}
diff --git a/handler/web/page.go b/handler/web/page.go
index 647984d..1f457de 100644
--- a/handler/web/page.go
+++ b/handler/web/page.go
@@ -1,8 +1,11 @@
 package web
 
-import "html/template"
+import (
+	"html/template"
+)
 
-// Page holds page information
+// Page holds page information that is sent to all webpages rendered
+// by perseus.
 type Page struct {
 	SafeList []template.HTML
 	List     []string
diff --git a/handler/web/register.go b/handler/web/register.go
deleted file mode 100644
index 1e76af2..0000000
--- a/handler/web/register.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package web
-
-import (
-	"fmt"
-	"html/template"
-	"log"
-	"net/http"
-	"strings"
-
-	"tildegit.org/andinus/perseus/auth"
-	"tildegit.org/andinus/perseus/core"
-	"tildegit.org/andinus/perseus/storage/sqlite3"
-)
-
-// HandleRegister handles /register pages.
-func HandleRegister(w http.ResponseWriter, r *http.Request, db *sqlite3.DB) {
-	p := Page{Version: core.Version()}
-	p.Notice = []string{
-		"Only [a-z] & [0-9] allowed for username",
-		"Password length must be greater than 8 characters",
-	}
-	switch r.Method {
-	case http.MethodGet:
-		t, _ := template.ParseFiles("web/register.html")
-		t.Execute(w, p)
-
-	case http.MethodPost:
-		if err := r.ParseForm(); err != nil {
-			log.Printf("web/register.go: 400 Bad Request :: %s", err.Error())
-			http.Error(w, "400 Bad Request", http.StatusBadRequest)
-			return
-		}
-
-		// Get form values
-		uInfo := make(map[string]string)
-		uInfo["username"] = r.FormValue("username")
-		uInfo["password"] = r.FormValue("password")
-
-		// Perform registration
-		err := auth.Register(db, uInfo)
-
-		if err != nil {
-			log.Printf("web/register.go: %s :: %s :: %s",
-				"registration failed",
-				uInfo["username"],
-				err.Error())
-
-			error := []string{}
-			error = append(error,
-				fmt.Sprintf("Registration failed"))
-
-			// Check if the error was because of username
-			// not being unique.
-			if strings.HasPrefix(err.Error(), "UNIQUE constraint failed") {
-				error = append(error,
-					fmt.Sprintf("Username not unique"))
-			}
-			p.Error = error
-		} else {
-			success := []string{}
-			success = append(success,
-				fmt.Sprintf("Registration successful"))
-			p.Success = success
-		}
-
-		t, _ := template.ParseFiles("web/register.html")
-		t.Execute(w, p)
-
-	default:
-		w.WriteHeader(http.StatusMethodNotAllowed)
-		log.Printf("web/register.go: %v not allowed on %v", r.Method, r.URL)
-	}
-
-}
diff --git a/user/adduser.go b/user/adduser.go
index 873454b..d1dbcde 100644
--- a/user/adduser.go
+++ b/user/adduser.go
@@ -8,7 +8,7 @@ import (
 )
 
 // AddUser adds the user to record.
-func (u *User) AddUser(db *sqlite3.DB) error {
+func (u User) AddUser(db *sqlite3.DB) error {
 	// Acquire write lock on the database.
 	db.Mu.Lock()
 	defer db.Mu.Unlock()
@@ -30,7 +30,7 @@ INSERT INTO users(id, username, password, regTime) values(?, ?, ?, ?)`)
 	}
 	defer usrStmt.Close()
 
-	_, err = usrStmt.Exec(u.id, u.username, u.password, time.Now().UTC())
+	_, err = usrStmt.Exec(u.ID, u.Username, u.Password, time.Now().UTC())
 	if err != nil {
 		log.Printf("user/adduser.go: %s\n",
 			"failed to execute statement")
diff --git a/user/getid.go b/user/getid.go
index b8edfc7..9cf8870 100644
--- a/user/getid.go
+++ b/user/getid.go
@@ -18,12 +18,12 @@ func (u *User) GetID(db *sqlite3.DB) error {
 	defer stmt.Close()
 
 	var id string
-	err = stmt.QueryRow(u.username).Scan(&id)
+	err = stmt.QueryRow(u.Username).Scan(&id)
 	if err != nil {
 		log.Printf("user/getid.go: %s\n",
 			"query failed")
 	}
-	u.id = id
+	u.ID = id
 
 	return err
 }
diff --git a/user/user.go b/user/user.go
index a15d625..078215e 100644
--- a/user/user.go
+++ b/user/user.go
@@ -2,37 +2,8 @@ package user
 
 // User holds information about the user.
 type User struct {
-	id       string
-	username string
-	password string
-}
-
-// SetUsername will set the username.
-func (u *User) SetUsername(username string) {
-	u.username = username
-}
-
-// Username returns the username.
-func (u *User) Username() string {
-	return u.username
-}
-
-// SetPassword will set the password.
-func (u *User) SetPassword(password string) {
-	u.password = password
-}
-
-// Password returns the password.
-func (u *User) Password() string {
-	return u.password
-}
-
-// SetID will set the id.
-func (u *User) SetID(id string) {
-	u.id = id
-}
-
-// ID returns the id.
-func (u *User) ID() string {
-	return u.id
+	ID       string
+	Username string
+	Password string
+	Hash     string
 }