291 lines
7.6 KiB
Go
291 lines
7.6 KiB
Go
package routes
|
|
|
|
import (
|
|
"io"
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"gitea.zokki.net/zokki/uni/web43-diary/context"
|
|
"gitea.zokki.net/zokki/uni/web43-diary/internal/database"
|
|
"gitea.zokki.net/zokki/uni/web43-diary/internal/models"
|
|
"gitea.zokki.net/zokki/uni/web43-diary/internal/session"
|
|
)
|
|
|
|
func createUser(writer http.ResponseWriter, req *http.Request) {
|
|
user := models.User{
|
|
Username: req.FormValue("username"),
|
|
FirstName: req.FormValue("firstName"),
|
|
LastName: req.FormValue("lastName"),
|
|
Password: req.FormValue("password"),
|
|
}
|
|
|
|
if user.Username == "" || user.FirstName == "" || user.LastName == "" || user.Password == "" {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Es müssen alle Felder gefüllt sein",
|
|
Code: http.StatusBadRequest,
|
|
})
|
|
return
|
|
}
|
|
|
|
if user.Password != req.FormValue("passwordRepeat") {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Passwörter müssen übereinstimmen",
|
|
Code: http.StatusBadRequest,
|
|
})
|
|
return
|
|
}
|
|
|
|
var httpErr *models.HTTPError
|
|
user.Password, user.Salt, httpErr = hashPassword(user.Password, "")
|
|
if httpErr != nil {
|
|
errorJson(writer, httpErr)
|
|
return
|
|
}
|
|
|
|
_, err := database.GetOne(req.Context().(*context.Context), &models.User{Username: user.Username})
|
|
if err == nil {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Benutzername bereits vergeben",
|
|
Code: http.StatusBadRequest,
|
|
})
|
|
return
|
|
}
|
|
|
|
userId, err := database.InsertInto(req.Context().(*context.Context), &user)
|
|
if err != nil {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "User konnte nicht in die Datenbank gespeichert werden",
|
|
Code: http.StatusInternalServerError,
|
|
Data: err,
|
|
})
|
|
return
|
|
}
|
|
|
|
if userId == 1 {
|
|
// set first user as admin
|
|
user.Role = models.AdminUser
|
|
if err := database.Update(req.Context().(*context.Context), &models.User{ID: uint32(userId)}, &user); err != nil {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Fehler beim Aktualisieren des Benutzers",
|
|
Code: http.StatusInternalServerError,
|
|
Data: err,
|
|
})
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func updateTheme(writer http.ResponseWriter, req *http.Request) {
|
|
body, err := io.ReadAll(io.LimitReader(req.Body, 8))
|
|
if err != nil {
|
|
http.Error(writer, "Unable to read request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
defer req.Body.Close()
|
|
|
|
theme := models.WebThemeFromString(string(body))
|
|
session.GetSession(req).SetTheme(theme)
|
|
}
|
|
|
|
func loginUser(writer http.ResponseWriter, req *http.Request) {
|
|
username := req.FormValue("username")
|
|
password := req.FormValue("password")
|
|
|
|
if username == "" || password == "" {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Es müssen alle Felder gefüllt sein",
|
|
Code: http.StatusBadRequest,
|
|
})
|
|
return
|
|
}
|
|
|
|
user, err := database.GetOne(req.Context().(*context.Context), &models.User{Username: username})
|
|
if err != nil {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Benutzername oder Passwort ist falsch",
|
|
Code: http.StatusUnauthorized,
|
|
})
|
|
return
|
|
}
|
|
|
|
hashedPassword, _, httpErr := hashPassword(password, user.Salt)
|
|
if httpErr != nil {
|
|
errorJson(writer, httpErr)
|
|
return
|
|
}
|
|
if hashedPassword != user.Password {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Benutzername oder Passwort ist falsch",
|
|
Code: http.StatusUnauthorized,
|
|
})
|
|
return
|
|
}
|
|
|
|
session.GetSession(req).SetUser(user)
|
|
}
|
|
|
|
func logoutUser(writer http.ResponseWriter, req *http.Request) {
|
|
session.GetSession(req).Destroy(writer, req)
|
|
http.Redirect(writer, req, "/", http.StatusSeeOther)
|
|
}
|
|
|
|
func updateUser(writer http.ResponseWriter, req *http.Request) {
|
|
idToUpdate, err := strconv.ParseUint(req.PathValue(UserIDValue), 10, 32)
|
|
if err != nil || idToUpdate == 0 {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Malformed user ID",
|
|
Code: http.StatusBadRequest,
|
|
})
|
|
return
|
|
}
|
|
updateID := uint32(idToUpdate)
|
|
|
|
user := models.User{}
|
|
|
|
if username := req.FormValue("username"); username != "" {
|
|
user.Username = username
|
|
}
|
|
if firstName := req.FormValue("firstName"); firstName != "" {
|
|
user.FirstName = firstName
|
|
}
|
|
if lastName := req.FormValue("lastName"); lastName != "" {
|
|
user.LastName = lastName
|
|
}
|
|
|
|
if user.Username != "" || user.FirstName != "" || user.LastName != "" {
|
|
sess := session.GetSession(req)
|
|
currentUser := sess.GetUser()
|
|
|
|
if currentUser.ID != updateID && !currentUser.Role.IsAdminUser() {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Sie haben keine Berechtigung, diesen Benutzer zu bearbeiten",
|
|
Code: http.StatusForbidden,
|
|
})
|
|
return
|
|
}
|
|
|
|
_, err := database.GetOne(req.Context().(*context.Context), &models.User{Username: user.Username})
|
|
if err == nil {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Benutzername bereits vergeben",
|
|
Code: http.StatusBadRequest,
|
|
})
|
|
return
|
|
}
|
|
|
|
// Update user in the database
|
|
if err := database.Update(req.Context().(*context.Context), &models.User{ID: updateID}, &user); err != nil {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Fehler beim Aktualisieren des Benutzers",
|
|
Code: http.StatusInternalServerError,
|
|
Data: err,
|
|
})
|
|
return
|
|
}
|
|
|
|
// Update user in the session
|
|
currentUser.Username = user.Username
|
|
currentUser.FirstName = user.FirstName
|
|
currentUser.LastName = user.LastName
|
|
sess.SetUser(currentUser)
|
|
|
|
writer.WriteHeader(http.StatusNoContent)
|
|
}
|
|
}
|
|
|
|
func updateUserPassword(writer http.ResponseWriter, req *http.Request) {
|
|
currentPassword := req.FormValue("currentPassword")
|
|
newPassword := req.FormValue("newPassword")
|
|
repeatPassword := req.FormValue("passwordRepeat")
|
|
|
|
if currentPassword == "" || newPassword == "" || repeatPassword == "" {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Es müssen alle Felder gefüllt sein",
|
|
Code: http.StatusBadRequest,
|
|
})
|
|
return
|
|
}
|
|
|
|
if newPassword != repeatPassword {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Passwörter müssen übereinstimmen",
|
|
Code: http.StatusBadRequest,
|
|
})
|
|
return
|
|
}
|
|
|
|
sess := session.GetSession(req)
|
|
user := sess.GetUser()
|
|
|
|
hashedCurrentPassword, _, err := hashPassword(currentPassword, user.Salt)
|
|
if err != nil {
|
|
errorJson(writer, err)
|
|
return
|
|
}
|
|
if hashedCurrentPassword != user.Password {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Aktuelles Passwort ist falsch",
|
|
Code: http.StatusUnauthorized,
|
|
})
|
|
return
|
|
}
|
|
|
|
hashedNewPassword, salt, httpErr := hashPassword(newPassword, "")
|
|
if httpErr != nil {
|
|
errorJson(writer, httpErr)
|
|
return
|
|
}
|
|
|
|
newPasswordUser := &models.User{
|
|
Password: hashedNewPassword,
|
|
Salt: salt,
|
|
}
|
|
|
|
if err := database.Update(req.Context().(*context.Context), &models.User{ID: user.ID}, newPasswordUser); err != nil {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Fehler beim Aktualisieren des Passworts",
|
|
Code: http.StatusInternalServerError,
|
|
Data: err,
|
|
})
|
|
return
|
|
}
|
|
|
|
sess.SetUser(user)
|
|
writer.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
func deleteUser(writer http.ResponseWriter, req *http.Request) {
|
|
idToDelete, err := strconv.ParseUint(req.PathValue(UserIDValue), 10, 32)
|
|
if err != nil || idToDelete == 0 {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Malformed user ID",
|
|
Code: http.StatusBadRequest,
|
|
})
|
|
return
|
|
}
|
|
deleteID := uint32(idToDelete)
|
|
|
|
sess := session.GetSession(req)
|
|
user := sess.GetUser()
|
|
if user.ID != deleteID && !user.Role.IsAdminUser() {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Sie haben keine Berechtigung, diesen Benutzer zu löschen",
|
|
Code: http.StatusForbidden,
|
|
})
|
|
return
|
|
}
|
|
|
|
if err := database.Delete(req.Context().(*context.Context), &models.User{ID: deleteID}); err != nil {
|
|
errorJson(writer, &models.HTTPError{
|
|
Message: "Fehler beim Löschen des Benutzers",
|
|
Code: http.StatusInternalServerError,
|
|
Data: err,
|
|
})
|
|
return
|
|
}
|
|
|
|
if user.ID == deleteID {
|
|
sess.Destroy(writer, req)
|
|
}
|
|
}
|