fix missing gin context (fixes #1)

This commit is contained in:
Adrian Zürcher
2025-10-26 21:05:55 +01:00
parent 8d8a1e3c33
commit 4670c93eff
6 changed files with 368 additions and 357 deletions

View File

@@ -1,48 +1,20 @@
package handlers
import (
"errors"
"fmt"
"net/http"
"strconv"
"gitea.tecamino.com/paadi/access-handler/internal/utils"
"gitea.tecamino.com/paadi/access-handler/models"
"github.com/gin-gonic/gin"
)
// AddUserTable
//
// Description:
//
// Creates a new database table for storing user records if it does not already exist.
//
// Behavior:
// - Uses the DBHandler to add a table based on the `models.User` struct.
// - Returns any error encountered during table creation.
//
// Returns:
// - error: Any database error that occurs while creating the table.
func (aH *AccessHandler) AddUserTable() error {
return aH.dbHandler.AddNewTable(models.User{})
}
// AddDefaultUser
//
// Description:
//
// Ensures a default administrative user exists in the database.
// If a user with the predefined email already exists, the function logs
// a debug message and exits without making changes.
//
// Behavior:
// 1. Checks if the default user (admin) already exists by email.
// 2. If not found, creates default Quasar UI settings and adds the user.
//
// Default User:
// - Name: "admin"
// - Role: "admin"
// - Email: "zuercher@tecamino.ch"
// - Password: (empty or hashed later)
//
// Returns:
// - error: Any database or creation error encountered.
func (aH *AccessHandler) AddDefaultUser() (err error) {
name := "admin"
role := "admin"
@@ -71,148 +43,161 @@ func (aH *AccessHandler) AddDefaultUser() (err error) {
return
}
// AddNewUser
//
// Description:
//
// Adds a new user record to the database with a hashed password.
//
// Behavior:
// 1. Verifies that the email does not already exist.
// 2. Hashes the password using utils.HashPassword().
// 3. Inserts the new user record into the database.
//
// Parameters:
// - userName: The user's display name.
// - email: The user's unique email address.
// - password: The user's raw password (will be hashed).
// - role: The role assigned to the user.
//
// Returns:
// - error: If the user already exists or if hashing/insertion fails.
func (aH *AccessHandler) AddNewUser(userName, email, password, role string) (err error) {
func (aH *AccessHandler) AddUser(c *gin.Context) {
var user models.User
err := c.BindJSON(&user)
if err != nil {
aH.logger.Error("AddUser", err)
c.JSON(http.StatusInternalServerError, models.NewJsonErrorResponse(err))
return
}
if !user.IsValid() {
aH.logger.Error("AddUser", "user empty")
c.JSON(http.StatusBadRequest, models.NewJsonMessageResponse("user empty"))
return
}
// Check if a user with this email already exists
if err := aH.dbHandler.Exists(&models.User{}, "email", email, false); err == nil {
if err := aH.dbHandler.Exists(&models.User{}, "email", user.Email, false); err == nil {
// Found a user → skip create
aH.logger.Error("AddNewUser", "user with email "+email+" already exists")
return fmt.Errorf("user with email %s already exists", email)
aH.logger.Error("AddUser", "user with email "+user.Email+" already exists")
c.JSON(http.StatusBadRequest, models.NewJsonMessageResponse(fmt.Sprintf("user with email %s already exists", user.Email)))
return
}
if !utils.IsValidEmail(user.Email) {
aH.logger.Error("AddUser", "not valid email address")
c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(errors.New("not valid email address")))
return
}
// Hash the provided password before saving
hash, err := utils.HashPassword(password)
hash, err := utils.HashPassword(user.Password)
if err != nil {
return err
aH.logger.Error("AddUser", err)
c.JSON(http.StatusInternalServerError, nil)
return
}
aH.logger.Debug("AddNewUser", "add new user "+userName+" with role "+role)
aH.logger.Debug("AddUser", "add default quasar user setting ")
user.Settings.DefaultQuasarSettings()
aH.logger.Debug("AddUser", "add new user "+user.Name+" with role "+user.Role)
// Insert the new user record
aH.dbHandler.AddNewColum(&models.User{
Name: userName,
Role: role,
Email: email,
Name: user.Name,
Role: user.Role,
Email: user.Email,
Password: hash,
Settings: user.Settings,
})
c.JSON(http.StatusOK, gin.H{
"message": fmt.Sprintf("user '%s' successfully added", user.Name),
})
return
}
// GetUserById
//
// Description:
//
// Retrieves user(s) from the database by their unique ID.
//
// Parameters:
// - id: The numeric user ID.
//
// Returns:
// - users: A slice containing the matched user (usually length 1).
// - err: Any database error encountered.
func (aH *AccessHandler) GetUserById(id uint) (users []models.User, err error) {
err = aH.dbHandler.GetById(&users, id)
return
func (aH *AccessHandler) GetUser(c *gin.Context) {
var i int
var err error
id := c.Query("id")
if id == "undefined" || id == "null" || id == "" {
i = 0
} else {
i, err = strconv.Atoi(id)
if err != nil {
aH.logger.Error("GetUser", err)
c.JSON(http.StatusInternalServerError, nil)
return
}
}
var users []models.User
err = aH.dbHandler.GetById(&users, uint(i))
if err != nil {
aH.logger.Error("GetUser", err)
c.JSON(http.StatusInternalServerError, nil)
return
}
c.JSON(http.StatusOK, users)
}
// GetUserByKey
//
// Description:
//
// Queries users based on a given column key and value.
//
// Parameters:
// - key: The column name to search by (e.g., "email").
// - value: The value to match.
// - likeSearch: If true, performs a LIKE (partial) search.
//
// Returns:
// - users: A list of users that match the search criteria.
// - err: Any database error encountered.
func (aH *AccessHandler) GetUserByKey(key string, value any, likeSearch bool) (users []models.User, err error) {
err = aH.dbHandler.GetByKey(&users, key, value, likeSearch)
return
func (aH *AccessHandler) UpdateUser(c *gin.Context) {
var user models.User
if err := c.BindJSON(&user); err != nil {
aH.logger.Error("UpdateUser", err)
c.JSON(http.StatusInternalServerError, nil)
return
}
err := aH.dbHandler.UpdateValuesById(&user, user.Id)
if err != nil {
aH.logger.Error("UpdateUser", err)
c.JSON(http.StatusInternalServerError, nil)
return
}
c.JSON(http.StatusOK, models.NewJsonMessageResponse("successfully updated user '"+user.Email+"'"))
}
// UpdateUserById
//
// Description:
//
// Updates an existing user record identified by its numeric ID.
//
// Parameters:
// - id: The user ID to update.
// - user: A struct containing updated field values.
//
// Returns:
// - error: Any error encountered during the update.
func (aH *AccessHandler) UpdateUserById(id uint, user models.User) error {
return aH.dbHandler.UpdateValuesById(&user, id)
}
func (aH *AccessHandler) DeleteUser(c *gin.Context) {
queryId := c.Query("id")
// UpdateUserByKey
//
// Description:
//
// Updates a user record based on a specified column key and value.
//
// Parameters:
// - user: The updated user data.
// - key: The column name used for lookup.
// - value: The value to match against the key column.
//
// Returns:
// - error: Any error encountered during the update.
func (aH *AccessHandler) UpdateUserByKey(user models.User, key string, value any) error {
return aH.dbHandler.UpdateValuesByKey(&user, key, value)
}
if queryId == "" || queryId == "null" || queryId == "undefined" {
aH.logger.Error("DeleteUser", "id query missing or wrong value: "+queryId)
c.JSON(http.StatusBadRequest, gin.H{
"message": "id query missing or wrong value: " + queryId,
})
return
}
// DeleteUserById
//
// Description:
//
// Deletes a user from the database using their numeric ID.
//
// Parameters:
// - id: The ID of the user to delete.
//
// Returns:
// - error: Any database error encountered during deletion.
func (aH *AccessHandler) DeleteUserById(id uint) (err error) {
return aH.dbHandler.DeleteById(&models.User{}, id)
}
var request struct {
Ids []int `json:"ids"`
}
// DeleteUserByKey
//
// Description:
//
// Deletes users matching a specific key/value pair from the database.
//
// Parameters:
// - key: The column name to search by.
// - value: The value to match.
// - likeSearch: Whether to use a partial match (LIKE).
//
// Returns:
// - error: Any database error encountered during deletion.
func (aH *AccessHandler) DeleteUserByKey(key string, value any, likeSearch bool) (err error) {
return aH.dbHandler.DeleteByKey(&models.User{}, key, value, likeSearch)
err := c.BindJSON(&request)
if err != nil {
aH.logger.Error("DeleteUser", err)
c.JSON(http.StatusInternalServerError, nil)
return
}
if len(request.Ids) == 0 {
aH.logger.Error("DeleteUser", "no ids given to be deleted")
c.JSON(http.StatusBadRequest, gin.H{
"message": "no ids given to be deleted",
})
return
}
var ownId string
removeIds := make([]uint, len(request.Ids))
for i, id := range request.Ids {
if queryId == fmt.Sprint(id) {
ownId = queryId
continue
}
removeIds[i] = uint(id)
}
if ownId != "" {
aH.logger.Error("DeleteUser", "can not delete logged in member id: "+queryId)
c.JSON(http.StatusBadRequest, gin.H{
"message": "can not delete logged in member id: " + queryId,
"id": queryId,
})
return
}
err = aH.dbHandler.DeleteById(&models.User{}, removeIds...)
if err != nil {
aH.logger.Error("DeleteUser", err)
c.JSON(http.StatusInternalServerError, nil)
return
}
c.JSON(http.StatusOK, gin.H{
"message": "member(s) deleted",
})
}