diff options
author | Andinus <andinus@nand.sh> | 2020-03-27 22:43:11 +0530 |
---|---|---|
committer | Andinus <andinus@nand.sh> | 2020-03-27 22:43:11 +0530 |
commit | b0b83af1c45c2d5ee587dc96847e25c95a3d50b0 (patch) | |
tree | 09aeffb9ee5538a002d76457d2cfdc50257c67f2 | |
parent | 79b376a659a1d58db01f60ad049110363fbf15fc (diff) | |
download | perseus-b0b83af1c45c2d5ee587dc96847e25c95a3d50b0.tar.gz |
Add login handler
-rw-r--r-- | auth/login.go | 6 | ||||
-rw-r--r-- | auth/token/add.go | 4 | ||||
-rw-r--r-- | cmd/perseus/main.go | 3 | ||||
-rw-r--r-- | handler/web/login.go | 83 | ||||
-rw-r--r-- | web/login.html | 52 | ||||
-rw-r--r-- | web/register.html | 9 |
6 files changed, 145 insertions, 12 deletions
diff --git a/auth/login.go b/auth/login.go index 66d1b21..99e74ba 100644 --- a/auth/login.go +++ b/auth/login.go @@ -9,13 +9,13 @@ import ( // Login takes in login details and returns an error. If error doesn't // equal nil then consider login failed. -func Login(db *sqlite3.DB, loginInfo map[string]string) error { +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(loginInfo["username"]) + u.SetUsername(uInfo["username"]) // Get password for this user from the database. stmt, err := db.Conn.Prepare("SELECT password FROM users WHERE username = ?") @@ -36,7 +36,7 @@ func Login(db *sqlite3.DB, loginInfo map[string]string) error { u.SetPassword(pass) // Check user's password. - err = checkPass(loginInfo["password"], u.Password()) + err = checkPass(uInfo["password"], u.Password()) if err != nil { log.Printf("auth/login.go: %s%s\n", "user login failed, username: ", u.Username()) diff --git a/auth/token/add.go b/auth/token/add.go index c7f632c..eadc6dc 100644 --- a/auth/token/add.go +++ b/auth/token/add.go @@ -37,9 +37,9 @@ func AddToken(db *sqlite3.DB, uInfo map[string]string) (token string, err error) } stmt, err := db.Conn.Prepare(` -INSERT INTO access(id, username, genTime) values(?, ?, ?)`) +INSERT INTO access(id, token, genTime) values(?, ?, ?)`) if err != nil { - log.Printf("auth/tokenr.go: %s\n", + log.Printf("auth/token.go: %s\n", "failed to prepare statement") return } diff --git a/cmd/perseus/main.go b/cmd/perseus/main.go index b94793e..6abd3a4 100644 --- a/cmd/perseus/main.go +++ b/cmd/perseus/main.go @@ -30,6 +30,9 @@ func main() { http.HandleFunc("/register", func(w http.ResponseWriter, r *http.Request) { web.HandleRegister(w, r, db) }) + http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) { + web.HandleLogin(w, r, db) + }) log.Printf("main/main.go: listening on port %s...", envPort) log.Fatal(srv.ListenAndServe()) diff --git a/handler/web/login.go b/handler/web/login.go new file mode 100644 index 0000000..0c70b56 --- /dev/null +++ b/handler/web/login.go @@ -0,0 +1,83 @@ +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/web/login.html b/web/login.html new file mode 100644 index 0000000..cd0d6a7 --- /dev/null +++ b/web/login.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>Login · Perseus</title> + <link rel="stylesheet" href="https://andinus.nand.sh/static/style.css"> + <link rel="stylesheet" href="https://andinus.nand.sh/static/perseus/style.css"> + <link rel="icon" href="https://andinus.nand.sh/static/perseus/favicon.png" type="image/png"> + </head> + <body> + <div id="content"> + <h1 class="title">Perseus</h1>{{ if .SafeList }} + <ul>{{ range .SafeList }} + <li>{{ . }}</li>{{ end }} + </ul>{{end}} {{ if .List }} + <ul>{{ range .List }} + <li>{{ . }}</li>{{ end }} + </ul>{{end}} {{ if .Error }} + <ul class="error">{{ range .Error }} + <li>{{ . }}</li>{{ end }} + </ul>{{end}} {{ if .Success }} + <ul class="success">{{ range .Success }} + <li>{{ . }}</li>{{ end }} + </ul>{{end}} {{ if .Notice }} + <ul class="notice">{{ range .Notice }} + <li>{{ . }}</li>{{ end }} + </ul>{{end}} + <form action="./login" method="post"> + <h4>Username</h4> + <input type="text" name="username" required> + <h4>Password</h4> + <input type="password" name="password" required> + <input type="submit" name="submit" value="Login!"> + </form> + </div> + <div id="postamble" class="status"> + <p class="postamble"> + <a href="https://andinus.nand.sh/">Andinus</a> + / + <a href="https://andinus.nand.sh/perseus">Perseus</a> + <span style="float:right"> + Perseus {{ .Version }} + / + <a href="https://tildegit.org/andinus/perseus"> + Source Code + </a> + </span> + </p> + </div> + </body> +</html> diff --git a/web/register.html b/web/register.html index e71979e..c351ae1 100644 --- a/web/register.html +++ b/web/register.html @@ -10,12 +10,7 @@ </head> <body> <div id="content"> - <h1 class="title">Perseus</h1> - <p> - Perseus is a simple link aggregation and discussion program. - It is written in Go & uses sqlite3 for storage. - </p> - <hr>{{ if .SafeList }} + <h1 class="title">Perseus</h1>{{ if .SafeList }} <ul>{{ range .SafeList }} <li>{{ . }}</li>{{ end }} </ul>{{end}} {{ if .List }} @@ -36,7 +31,7 @@ <input type="text" name="username" required> <h4>Password</h4> <input type="password" name="password" required> - <input type="submit" name="submit" value="Go!"> + <input type="submit" name="submit" value="Register!"> </form> </div> <div id="postamble" class="status"> |