fierj
PublicTiny personal git forge
package main
import (
"html/template"
"net/http"
"strings"
)
// ----- Login -----
func LoginGet(tmpl *template.Template) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
tmpl.ExecuteTemplate(w, "auth_login.html", map[string]any{"User": User(r)})
}
}
func LoginPost(users UserStore, secret []byte, tmpl *template.Template) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
username := strings.TrimSpace(r.FormValue("username"))
password := r.FormValue("password")
if !users.Verify(username, password) {
tmpl.ExecuteTemplate(w, "auth_login.html", map[string]any{
"Error": "Invalid username or password.",
"User": User(r),
})
return
}
setAuthCookie(w, username, secret)
http.Redirect(w, r, "/", http.StatusSeeOther)
}
}
func Logout() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
clearAuthCookie(w)
http.Redirect(w, r, "/", http.StatusSeeOther)
}
}
// ----- Setup (first-run) -----
func SetupGet(tmpl *template.Template) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
tmpl.ExecuteTemplate(w, "auth_setup.html", map[string]any{"User": User(r)})
}
}
func SetupPost(users UserStore, usersPath string, secret []byte, tmpl *template.Template) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
username := strings.TrimSpace(r.FormValue("username"))
password := r.FormValue("password")
confirm := r.FormValue("confirm")
if password != confirm {
tmpl.ExecuteTemplate(w, "auth_setup.html", map[string]any{"Error": "Passwords do not match.", "User": User(r)})
return
}
if err := users.Add(username, password); err != nil {
tmpl.ExecuteTemplate(w, "auth_setup.html", map[string]any{"Error": err.Error(), "User": User(r)})
return
}
if err := users.Save(usersPath); err != nil {
tmpl.ExecuteTemplate(w, "auth_setup.html", map[string]any{"Error": "Failed to save: " + err.Error(), "User": User(r)})
return
}
setAuthCookie(w, username, secret)
http.Redirect(w, r, "/", http.StatusSeeOther)
}
}
// ----- User management -----
func UsersGet(users UserStore, usersPath string, tmpl *template.Template) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if User(r) == "" {
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
userList := make([]string, 0, len(users))
for u := range users {
userList = append(userList, u)
}
tmpl.ExecuteTemplate(w, "auth_users.html", map[string]any{
"Users": userList,
"User": User(r),
})
}
}
func UsersPost(users UserStore, usersPath string, tmpl *template.Template) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if User(r) == "" {
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
action := r.FormValue("action")
switch action {
case "add":
username := strings.TrimSpace(r.FormValue("username"))
password := r.FormValue("password")
if err := users.Add(username, password); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
users.Save(usersPath)
case "remove":
username := strings.TrimSpace(r.FormValue("username"))
if username == User(r) {
http.Error(w, "cannot remove yourself", http.StatusBadRequest)
return
}
users.Remove(username)
users.Save(usersPath)
case "change-password":
currentUser := User(r)
newPassword := r.FormValue("password")
if err := users.ChangePassword(currentUser, newPassword); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
users.Save(usersPath)
}
http.Redirect(w, r, "/users", http.StatusSeeOther)
}
}