Goit

Simple and lightweight Git web server
git clone http://git.omkov.net/Goit
Log | Tree | Refs | README | Download

AuthorJakob Wakeling <[email protected]>
Date2023-09-07 10:53:16
Commitd0994fe1eb5d3b189dd5382da841a23a2d54550e
Parentedde49188189df2433f5b5562c2bec5c96bbe736

Implement user edit page

Diffstat

M main.go | 1 +
M res/res.go | 3 +++
A res/user/edit.html | 34 ++++++++++++++++++++++++++++++++++
M res/user/header.html | 1 +
M src/auth.go | 4 ++--
M src/http.go | 1 +
M src/repo.go | 4 ----
M src/repo/edit.go | 12 ++++++------
M src/user.go | 11 +++++++++++
A src/user/edit.go | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A src/user/user.go | 3 +++

11 files changed, 133 insertions, 12 deletions

diff --git a/main.go b/main.go
index 153a80b..e292e5b 100644
--- a/main.go
+++ b/main.go
@@ -29,6 +29,7 @@ func main() {
 	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("/user/edit").Methods("GET", "POST").HandlerFunc(user.HandleEdit)
 	h.Path("/repo/create").Methods("GET", "POST").HandlerFunc(repo.HandleCreate)
 	h.Path("/repo/delete").Methods("DELETE").HandlerFunc(repo.HandleDelete)
 	h.Path("/admin").Methods("GET").HandlerFunc(goit.HandleAdminIndex)
diff --git a/res/res.go b/res/res.go
index e5dfd89..b2dde74 100644
--- a/res/res.go
+++ b/res/res.go
@@ -40,6 +40,9 @@ var UserLogin string
 //go:embed user/sessions.html
 var UserSessions string
 
+//go:embed user/edit.html
+var UserEdit string
+
 //go:embed repo/header.html
 var RepoHeader string
 
diff --git a/res/user/edit.html b/res/user/edit.html
new file mode 100644
index 0000000..af2bb1b
--- /dev/null
+++ b/res/user/edit.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<head lang="en-GB">{{template "base/head" .}}</head>
+<body>
+	<header>{{template "user/header" .}}</header><hr>
+	<main>
+		<h1>{{.Title}}</h1><hr>
+		<form action="/user/edit" method="post">
+			<table>
+				<tr>
+					<td style="text-align: right;"><label for="username">Username</label></td>
+					<td><input type="text" name="username" value="{{.Form.Name}}" spellcheck="false"></td>
+				</tr>
+				<tr>
+					<td style="text-align: right;"><label for="fullname">Full Name</label></td>
+					<td><input type="text" name="fullname" value="{{.Form.FullName}}" spellcheck="false"></td>
+				</tr>
+				<tr>
+					<td></td>
+					<td>
+						<input type="submit" value="Update">
+						<a href="/" style="color: inherit;">Cancel</a>
+					</td>
+				</tr>
+				<tr>
+					<td></td>
+					<td style="color: #AA0000">{{.Message}}</td>
+				</tr>
+			</table>
+		</form>
+		<table>
+			<tr><td style="text-align: right;"><span>ID:</span></td><td><span>{{.Form.Id}}</span></td></tr>
+		</table>
+	</main>
+</body>
diff --git a/res/user/header.html b/res/user/header.html
index 1b86f45..a984290 100644
--- a/res/user/header.html
+++ b/res/user/header.html
@@ -9,6 +9,7 @@
 	<tr>
 		<td>
 			<a href="/user/sessions">Sessions</a>
+			| <a href="/user/edit">Edit</a>
 		</td>
 	</tr>
 </table>
diff --git a/src/auth.go b/src/auth.go
index 4cefd53..d78b2c2 100644
--- a/src/auth.go
+++ b/src/auth.go
@@ -102,7 +102,7 @@ func EndSessionCookie(w http.ResponseWriter) {
 	http.SetCookie(w, &http.Cookie{Name: "session", Path: "/", MaxAge: -1})
 }
 
-func AuthCookie(w http.ResponseWriter, r *http.Request, renew bool) (auth bool, uid int64) {
+func AuthCookie(w http.ResponseWriter, r *http.Request, renew bool) (bool, int64) {
 	if uid, s := GetSessionCookie(r); s != (Session{}) {
 		if s.Expiry.After(time.Now()) {
 			if renew && time.Until(s.Expiry) < 24*time.Hour {
@@ -125,7 +125,7 @@ func AuthCookie(w http.ResponseWriter, r *http.Request, renew bool) (auth bool,
 	return false, -1
 }
 
-func AuthCookieAdmin(w http.ResponseWriter, r *http.Request, renew bool) (auth bool, admin bool, uid int64) {
+func AuthCookieAdmin(w http.ResponseWriter, r *http.Request, renew bool) (bool, bool, int64) {
 	if ok, uid := AuthCookie(w, r, renew); ok {
 		if user, err := GetUser(uid); err == nil && user.IsAdmin {
 			return true, true, uid
diff --git a/src/http.go b/src/http.go
index 8955ca3..ebda9e2 100644
--- a/src/http.go
+++ b/src/http.go
@@ -28,6 +28,7 @@ func init() {
 	template.Must(Tmpl.New("user/header").Parse(res.UserHeader))
 	template.Must(Tmpl.New("user/login").Parse(res.UserLogin))
 	template.Must(Tmpl.New("user/sessions").Parse(res.UserSessions))
+	template.Must(Tmpl.New("user/edit").Parse(res.UserEdit))
 
 	template.Must(Tmpl.New("repo/header").Parse(res.RepoHeader))
 	template.Must(Tmpl.New("repo/create").Parse(res.RepoCreate))
diff --git a/src/repo.go b/src/repo.go
index 6b2b8dc..2662f42 100644
--- a/src/repo.go
+++ b/src/repo.go
@@ -141,9 +141,5 @@ func UpdateRepo(rid int64, repo Repo) error {
 		return err
 	}
 
-	if _, err := db.Exec(""); err != nil {
-		return err
-	}
-
 	return nil
 }
diff --git a/src/repo/edit.go b/src/repo/edit.go
index 7f49c15..53af807 100644
--- a/src/repo/edit.go
+++ b/src/repo/edit.go
@@ -91,16 +91,16 @@ func HandleEdit(w http.ResponseWriter, r *http.Request) {
 		data.Form.Description = r.FormValue("description")
 		data.Form.IsPrivate = r.FormValue("visibility") == "private"
 
-		if data.Name == "" {
+		if data.Form.Name == "" {
 			data.Message = "Name cannot be empty"
-		} else if slices.Contains(reserved, data.Name) {
-			data.Message = "Name \"" + data.Name + "\" is reserved"
-		} else if exists, err := goit.RepoExists(data.Name); err != nil {
+		} else if slices.Contains(reserved, data.Form.Name) {
+			data.Message = "Name \"" + data.Form.Name + "\" is reserved"
+		} else if exists, err := goit.RepoExists(data.Form.Name); err != nil {
 			log.Println("[/repo/edit]", err.Error())
 			goit.HttpError(w, http.StatusInternalServerError)
 			return
-		} else if exists && data.Name != repo.Name {
-			data.Message = "Name \"" + data.Name + "\" is taken"
+		} else if exists && data.Form.Name != repo.Name {
+			data.Message = "Name \"" + data.Form.Name + "\" is taken"
 		} else if err := goit.UpdateRepo(repo.Id, goit.Repo{
 			Name: data.Form.Name, Description: data.Form.Description, IsPrivate: data.Form.IsPrivate,
 		}); err != nil {
diff --git a/src/user.go b/src/user.go
index 9e74553..e7688df 100644
--- a/src/user.go
+++ b/src/user.go
@@ -104,3 +104,14 @@ func UserExists(name string) (bool, error) {
 		return true, nil
 	}
 }
+
+func UpdateUser(uid int64, user User) error {
+	if _, err := db.Exec(
+		"UPDATE users SET name = ?, name_full = ? WHERE id = ?",
+		user.Name, user.FullName, uid,
+	); err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/src/user/edit.go b/src/user/edit.go
new file mode 100644
index 0000000..2c22694
--- /dev/null
+++ b/src/user/edit.go
@@ -0,0 +1,71 @@
+package user
+
+import (
+	"fmt"
+	"log"
+	"net/http"
+	"slices"
+
+	goit "github.com/Jamozed/Goit/src"
+)
+
+func HandleEdit(w http.ResponseWriter, r *http.Request) {
+	auth, uid := goit.AuthCookie(w, r, true)
+	if !auth {
+		goit.HttpError(w, http.StatusUnauthorized)
+		return
+	}
+
+	user, err := goit.GetUser(uid)
+	if err != nil {
+		log.Println("[/user/edit]", err.Error())
+		goit.HttpError(w, http.StatusInternalServerError)
+		return
+	} else if user == nil {
+		log.Println("[/user/edit]", uid, "is a nonexistent UID")
+		goit.HttpError(w, http.StatusInternalServerError)
+		return
+	}
+
+	data := struct {
+		Title, Message string
+
+		Form struct{ Id, Name, FullName string }
+	}{
+		Title: "User - Edit",
+	}
+
+	data.Form.Id = fmt.Sprint(user.Id)
+	data.Form.Name = user.Name
+	data.Form.FullName = user.FullName
+
+	if r.Method == http.MethodPost {
+		data.Form.Name = r.FormValue("username")
+		data.Form.FullName = r.FormValue("fullname")
+
+		if data.Form.Name == "" {
+			data.Message = "Username cannot be empty"
+		} else if slices.Contains(reserved, data.Form.Name) && uid != 0 {
+			data.Message = "Username \"" + data.Form.Name + "\" is reserved"
+		} else if exists, err := goit.UserExists(data.Form.Name); err != nil {
+			log.Println("[/user/edit]", err.Error())
+			goit.HttpError(w, http.StatusInternalServerError)
+			return
+		} else if exists && data.Form.Name != user.Name {
+			data.Message = "Username \"" + data.Form.Name + "\" is taken"
+		} else if err := goit.UpdateUser(user.Id, goit.User{
+			Name: data.Form.Name, FullName: data.Form.FullName,
+		}); err != nil {
+			log.Println("[/user/edit]", err.Error())
+			goit.HttpError(w, http.StatusInternalServerError)
+			return
+		} else {
+			http.Redirect(w, r, "/user/edit", http.StatusFound)
+			return
+		}
+	}
+
+	if err := goit.Tmpl.ExecuteTemplate(w, "user/edit", data); err != nil {
+		log.Println("[/user/edit]", err.Error())
+	}
+}
diff --git a/src/user/user.go b/src/user/user.go
new file mode 100644
index 0000000..b41a851
--- /dev/null
+++ b/src/user/user.go
@@ -0,0 +1,3 @@
+package user
+
+var reserved []string = []string{"admin", "repo", "static", "user"}