package login import ( "backend/dbRequest" "backend/models" "backend/utils" "database/sql" "encoding/json" "fmt" "io" "net/http" "time" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" _ "modernc.org/sqlite" ) func (lm *LoginManager) AddUser(c *gin.Context) { 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 } db, err := sql.Open(lm.dbType, lm.dbFile) if dbRequest.CheckDBError(c, user.Name, err) { return } defer db.Close() var exists bool if err := db.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 _, err := db.Exec(dbRequest.DBNewUser, user.Role, user.Name, hash); dbRequest.CheckDBError(c, user.Name, err) { return } c.JSON(http.StatusOK, gin.H{ "message": fmt.Sprintf("user '%s' successfully added", user.Name), }) } func (lm *LoginManager) RemoveUser(c *gin.Context) { 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 } db, err := sql.Open(lm.dbType, lm.dbFile) if dbRequest.CheckDBError(c, user.Name, err) { return } defer db.Close() var storedPassword string if err := db.QueryRow(dbRequest.DBQueryPassword, user.Name).Scan(&storedPassword, &user.Role); dbRequest.CheckDBError(c, user.Name, err) { return } if !utils.CheckPassword(user.Password, storedPassword) { c.JSON(http.StatusBadRequest, models.NewJsonErrorMessageResponse("wrong password")) return } if _, err := db.Exec(dbRequest.DBRemoveUser, user.Name); dbRequest.CheckDBError(c, user.Name, err) { return } c.JSON(http.StatusOK, gin.H{ "message": fmt.Sprintf("user '%s' successfully removed", user.Name), }) } func (lm *LoginManager) Login(c *gin.Context) { 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 } db, err := sql.Open(lm.dbType, lm.dbFile) if dbRequest.CheckDBError(c, user.Name, err) { return } defer db.Close() var storedPassword string if err := db.QueryRow(dbRequest.DBQueryPassword, user.Name).Scan(&user.Role, &storedPassword); dbRequest.CheckDBError(c, user.Name, err) { return } if !utils.CheckPassword(user.Password, storedPassword) { c.JSON(http.StatusBadRequest, models.NewJsonErrorMessageResponse("wrong password")) return } // Create token token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "username": user.Name, "role": user.Role, "exp": time.Now().Add(time.Minute * 60).Unix(), // expires in 72h }) secret, err := utils.GenerateJWTSecret(32) // 32 bytes = 256 bits if err != nil { c.JSON(http.StatusInternalServerError, models.NewJsonErrorMessageResponse("error generate jwt token")) return } // Sign and get the complete encoded token as a string tokenString, err := token.SignedString(secret) if err != nil { c.JSON(http.StatusInternalServerError, models.NewJsonErrorMessageResponse("Could not generate token")) return } c.JSON(http.StatusOK, models.User{ Token: tokenString, }) }