Author | Jakob Wakeling <[email protected]> |
Date | 2023-08-08 10:43:43 |
Commit | ff9ec25a03d343b2b4ea7c538faa27264dd0233c |
Parent | 0dadb00e59a08480835e2e6b9de8510d42857b64 |
Update the user login page
Diffstat
M | main.go | | | 3 | ++- |
M | res/repo/create.html | | | 4 | +--- |
M | res/style.css | | | 1 | + |
M | res/user/login.html | | | 44 | ++++++++++++++++++++++++++++++++++---------- |
M | src/repo/log.go | | | 4 | ++-- |
M | src/user.go | | | 50 | -------------------------------------------------- |
A | src/user/login.go | | | 64 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
7 files changed, 104 insertions, 66 deletions
diff --git a/main.go b/main.go index 90df6ef..6daa6f0 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,7 @@ import ( "github.com/Jamozed/Goit/res" goit "github.com/Jamozed/Goit/src" "github.com/Jamozed/Goit/src/repo" + "github.com/Jamozed/Goit/src/user" "github.com/gorilla/mux" ) @@ -25,7 +26,7 @@ func main() { h.StrictSlash(true) h.Path("/").HandlerFunc(goit.HandleIndex) - h.Path("/user/login").Methods("GET", "POST").HandlerFunc(goit.HandleUserLogin) + h.Path("/user/login").Methods("GET", "POST").HandlerFunc(user.HandleLogin) h.Path("/user/logout").Methods("GET", "POST").HandlerFunc(goit.HandleUserLogout) h.Path("/user/sessions").Methods("GET", "POST").HandlerFunc(goit.HandleUserSessions) h.Path("/repo/create").Methods("GET", "POST").HandlerFunc(repo.HandleCreate) diff --git a/res/repo/create.html b/res/repo/create.html index 7f5f495..753e578 100644 --- a/res/repo/create.html +++ b/res/repo/create.html @@ -4,9 +4,7 @@ <header> <table> <tr> - <td rowspan="2"> - <a href="/"><img src="/static/favicon.png" style="max-height: 24px"></a> - </td> + <td rowspan="2"><a href="/"><img src="/static/favicon.png" style="max-height: 24px"></a></td> <td><h1>{{.Title}}</h1></td> </tr> <tr><td></td></tr> diff --git a/res/style.css b/res/style.css index 8b0443f..2c00a7f 100644 --- a/res/style.css +++ b/res/style.css @@ -18,6 +18,7 @@ table td.line { tab-size: 4; white-space: pre; } form table input { border: 2px solid #333333; border-radius: 3px; background-color: #111111; padding: 2px; } form table input[type="text"] { color: #888888; width: 24em; } +form table input[type="password"] { color: #888888; width: 24em; } form table input[type="submit"] { color: #FF7E00; width: 6em; } form table select { diff --git a/res/user/login.html b/res/user/login.html index f7890de..4d235cf 100644 --- a/res/user/login.html +++ b/res/user/login.html @@ -1,14 +1,38 @@ <!DOCTYPE html> <head lang="en-GB">{{template "base/head" .}}</head> <body> -<body> - <h1>Login</h1> - <form action="/user/login" method="post"> - <label for="username">Username:</label> - <input type="text" name="username"><br> - <label for="password">Password:</label> - <input type="password" name="password"><br> - <input type="submit" value="Login"> - </form> - <p>{{.Message}}</p> + <header> + <table> + <tr> + <td rowspan="2"><a href="/"><img src="/static/favicon.png" style="max-height: 24px"></a></td> + <td><h1>{{.Title}}</h1></td> + </tr> + <tr><td></td></tr> + </table> + </header> + <main> + <form action="/user/login" method="post"> + <table> + <tr> + <td style="text-align: right;"><label for="username">Username</label></td> + <td><input type="text" name="username" value="{{.Name}}" {{if not .FocusPw}}autofocus{{end}}></td> + </tr> + <tr> + <td style="text-align: right;"><label for="password">Password</label></td> + <td><input type="password" name="password" {{if .FocusPw}}autofocus{{end}}></td> + </tr> + <tr> + <td></td> + <td> + <input type="submit" value="Login"> + <a href="/" style="color: inherit;">Cancel</a> + </td> + </tr> + <tr> + <td></td> + <td style="color: #AA0000">{{.Message}}</td> + </tr> + </table> + </form> + </main> </body> diff --git a/src/repo/log.go b/src/repo/log.go index ab408d6..7c0f08a 100644 --- a/src/repo/log.go +++ b/src/repo/log.go @@ -18,13 +18,13 @@ import ( ) func HandleLog(w http.ResponseWriter, r *http.Request) { - _, uid := goit.AuthCookie(w, r, true) + auth, uid := goit.AuthCookie(w, r, true) repo, err := goit.GetRepoByName(mux.Vars(r)["repo"]) if err != nil { goit.HttpError(w, http.StatusInternalServerError) return - } else if repo == nil || (repo.IsPrivate && repo.OwnerId != uid) { + } else if repo == nil || (repo.IsPrivate && (!auth || repo.OwnerId != uid)) { goit.HttpError(w, http.StatusNotFound) return } diff --git a/src/user.go b/src/user.go index 4d0ee24..9e74553 100644 --- a/src/user.go +++ b/src/user.go @@ -5,12 +5,10 @@ package goit import ( - "bytes" "database/sql" "errors" "fmt" "log" - "net" "net/http" "strings" "time" @@ -30,54 +28,6 @@ type User struct { var reserved []string = []string{"admin", "repo", "static", "user"} -func HandleUserLogin(w http.ResponseWriter, r *http.Request) { - if ok, _ := AuthCookie(w, r, true); ok { - http.Redirect(w, r, "/", http.StatusFound) - return - } - - data := struct{ Title, Message string }{"Login", ""} - - if r.Method == http.MethodPost { - u := User{} - username := strings.ToLower(r.FormValue("username")) - password := r.FormValue("password") - - if username == "" { - data.Message = "Username cannot be empty" - } else if exists, err := UserExists(username); err != nil { - log.Println("[User:Login:Exists]", err.Error()) - HttpError(w, http.StatusInternalServerError) - return - } else if !exists { - data.Message = "Invalid credentials" - } else if err := db.QueryRow( - "SELECT id, name, pass, pass_algo, salt FROM users WHERE name = ?", username, - ).Scan(&u.Id, &u.Name, &u.Pass, &u.PassAlgo, &u.Salt); err != nil { - log.Println("[User:Login:SELECT]", err.Error()) - HttpError(w, http.StatusInternalServerError) - return - } else if !bytes.Equal(Hash(password, u.Salt), u.Pass) { - data.Message = "Invalid credentials" - } else { - ip, _, _ := net.SplitHostPort(r.RemoteAddr) - if s, err := NewSession(u.Id, ip, time.Now().Add(2*24*time.Hour)); err != nil { - log.Println("[User:Login:Session]", err.Error()) - HttpError(w, http.StatusInternalServerError) - return - } else { - SetSessionCookie(w, u.Id, s) - http.Redirect(w, r, "/", http.StatusFound) - return - } - } - } - - if err := Tmpl.ExecuteTemplate(w, "user/login", data); err != nil { - log.Println("[/user/login]", err.Error()) - } -} - func HandleUserLogout(w http.ResponseWriter, r *http.Request) { id, s := GetSessionCookie(r) EndSession(id, s.Token) diff --git a/src/user/login.go b/src/user/login.go new file mode 100644 index 0000000..f307e5d --- /dev/null +++ b/src/user/login.go @@ -0,0 +1,64 @@ +// user/login.go +// Copyright (C) 2023, Jakob Wakeling +// All rights reserved. + +package user + +import ( + "bytes" + "log" + "net" + "net/http" + "time" + + goit "github.com/Jamozed/Goit/src" +) + +func HandleLogin(w http.ResponseWriter, r *http.Request) { + if auth, _ := goit.AuthCookie(w, r, true); auth { + http.Redirect(w, r, "/", http.StatusFound) + } + + data := struct { + Title, Message, Name string + FocusPw bool + }{Title: "Login"} + + if r.Method == http.MethodPost { + data.Name = r.FormValue("username") + password := r.FormValue("password") + + if data.Name == "" { + data.Message = "Username cannot be empty" + goto execute + } + + user, err := goit.GetUserByName(data.Name) + if err != nil { + log.Println("[/user/login]", err.Error()) + goit.HttpError(w, http.StatusInternalServerError) + return + } else if user == nil || !bytes.Equal(goit.Hash(password, user.Salt), user.Pass) { + data.Message = "Invalid credentials" + data.FocusPw = true + goto execute + } + + ip, _, _ := net.SplitHostPort(r.RemoteAddr) + sess, err := goit.NewSession(user.Id, ip, time.Now().Add(2*24*time.Hour)) + if err != nil { + log.Println("[/user/login]", err.Error()) + goit.HttpError(w, http.StatusInternalServerError) + return + } + + goit.SetSessionCookie(w, user.Id, sess) + http.Redirect(w, r, "/", http.StatusFound) + return + } + +execute: + if err := goit.Tmpl.ExecuteTemplate(w, "user/login", data); err != nil { + log.Println("[/user/login]", err.Error()) + } +}