package user import ( "backend/dbRequest" "backend/models" "backend/utils" "database/sql" "encoding/json" "errors" "fmt" "io" "net/http" "os" "strconv" "strings" "github.com/gin-gonic/gin" ) type UserManager struct { database *sql.DB } func NewUserManager(dir string) (*UserManager, error) { if dir == "" { dir = "." } var err error var um UserManager file := fmt.Sprintf("%s/user.db", dir) um.database, err = sql.Open("sqlite", file) if err != nil { return nil, err } if _, err := os.Stat(file); err != nil { _, err = um.database.Exec(dbRequest.CreateUserTable) if err != nil { return nil, err } hash, err := utils.HashPassword("tecamino@2025") if err != nil { return nil, err } _, err = um.database.Exec(dbRequest.NewUser, "admin", "", "admin", hash, `{"databaseName":"members.dba","primaryColor":"#1976d2", "secondaryColor":"#26a69a"}`) if err != nil { return nil, err } } return &um, nil } func (um *UserManager) databaseOpened(c *gin.Context) bool { if um.database == nil { c.JSON(http.StatusBadRequest, gin.H{ "message": "no database opened", }) return false } return true } func (um *UserManager) AddUser(c *gin.Context) { if !um.databaseOpened(c) { return } body, err := io.ReadAll(c.Request.Body) if err != nil { c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err)) return } user := models.User{} err = json.Unmarshal(body, &user) if err != nil { c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err)) return } if !user.IsValid() { c.JSON(http.StatusBadRequest, models.NewJsonErrorMessageResponse("user empty")) return } var exists bool if err := um.database.QueryRow(dbRequest.DBUserLookup, user.Name).Scan(&exists); dbRequest.CheckDBError(c, user.Name, err) { return } if exists { c.JSON(http.StatusOK, models.NewJsonErrorMessageResponse(fmt.Sprintf("user '%s' exists already", user.Name))) return } hash, err := utils.HashPassword(user.Password) if err != nil { c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(err)) return } if !utils.IsValidEmail(user.Email) { c.JSON(http.StatusBadRequest, models.NewJsonErrorResponse(errors.New("not valid email address"))) return } if _, err := um.database.Exec(dbRequest.NewUser, user.Name, user.Email, user.Role, hash, "{}"); dbRequest.CheckDBError(c, user.Name, err) { return } c.JSON(http.StatusOK, gin.H{ "message": fmt.Sprintf("user '%s' successfully added", user.Name), }) } func (um *UserManager) GetUserById(c *gin.Context) { if !um.databaseOpened(c) { return } var i int var err error id := c.Query("id") if id != "" { i, err = strconv.Atoi(id) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "message": err.Error(), }) return } } query := `SELECT id, username, email, role, settings FROM users` var args any if i > 0 { query = ` SELECT id, username, email, role, settings FROM users WHERE id = ? ` args = i } rows, err := um.database.Query(query, args) if err != nil { return } defer rows.Close() var users []models.User for rows.Next() { var id int var name, email, role, settingsString string if err = rows.Scan(&id, &name, &email, &role, &settingsString); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "message": err.Error(), }) return } var settings models.Settings err := json.Unmarshal([]byte(settingsString), &settings) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "message": err.Error(), }) return } users = append(users, models.User{ Id: id, Name: name, Email: email, Role: role, Settings: settings, }) } if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "message": err.Error(), }) return } c.JSON(http.StatusOK, users) } func (um *UserManager) DeleteUser(c *gin.Context) { if !um.databaseOpened(c) { return } queryId := c.Query("id") if queryId == "" || queryId == "null" || queryId == "undefined" { c.JSON(http.StatusBadRequest, gin.H{ "message": "id query missing or wrong value: " + queryId, }) return } var request struct { Ids []int `json:"ids"` } err := c.BindJSON(&request) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "message": err.Error(), }) return } if len(request.Ids) == 0 { c.JSON(http.StatusBadRequest, gin.H{ "message": "no ids given to be deleted", }) return } var ownId string placeholders := make([]string, len(request.Ids)) args := make([]any, len(request.Ids)) for i, id := range request.Ids { if queryId == fmt.Sprint(id) { ownId = queryId continue } placeholders[i] = "?" args[i] = id } query := fmt.Sprintf("DELETE FROM users WHERE id IN (%s)", strings.Join(placeholders, ",")) _, err = um.database.Exec(query, args...) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "message": err.Error(), }) return } if ownId != "" { c.JSON(http.StatusBadRequest, gin.H{ "message": "can not delete logged in member id: " + queryId, "id": queryId, }) return } c.JSON(http.StatusOK, gin.H{ "message": "member(s) deleted", }) }