package user import ( "crypto/rand" "encoding/base64" "janex/admin-dashboard-backend/modules/database" "janex/admin-dashboard-backend/modules/structs" "janex/admin-dashboard-backend/modules/utils" "janex/admin-dashboard-backend/socketclients" "math/big" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog/log" "github.com/savsgio/gotils/uuid" "golang.org/x/crypto/bcrypt" ) func UserLogin(c *fiber.Ctx) error { var body structs.UserLoginRequest if err := c.BodyParser(&body); err != nil { log.Error().Msg("Failed to parse body, err: " + err.Error()) return c.Status(fiber.StatusBadRequest).JSON(err) } if err := utils.ValidateStruct(body); err != nil { log.Error().Msgf("Failed to validate body, err: %v", err) return c.SendStatus(fiber.StatusBadRequest) } decodedPassword, err := base64.StdEncoding.DecodeString(body.Password) if err != nil { log.Error().Msg("Failed to decode base64 password, err: " + err.Error()) return c.Status(fiber.StatusBadRequest).JSON(err.Error()) } if passwordValid := utils.IsPasswordLengthValid(string(decodedPassword)); !passwordValid { return c.SendStatus(fiber.StatusBadRequest) } var user structs.User database.DB.First(&user, "username = ?", body.Username) if user.Id == "" { log.Error().Msg("User not found") return c.SendStatus(fiber.StatusBadRequest) } if err := bcrypt.CompareHashAndPassword([]byte(user.Password), decodedPassword); err != nil { log.Error().Msg("Incorrect password") return c.SendStatus(fiber.StatusBadRequest) } session, err := GenerateSession() if err != nil { return c.SendStatus(fiber.StatusInternalServerError) } database.DB.Create(&structs.UserSession{ Id: session, IdForDeletion: uuid.V4(), UserId: user.Id, UserAgent: string(c.Context().UserAgent()), ExpiresAt: utils.GetSessionExpiresAtTime()}) return c.JSON(structs.UserLoginResponse{Session: session}) } func UserLogout(c *fiber.Ctx) error { session := utils.GetXAuhorizationHeader(c) database.DB.Delete(&structs.UserSession{}, "id = ?", session) socketclients.CloseAllUserSessionConnections(session) return c.SendStatus(fiber.StatusCreated) } func GenerateSession() (string, error) { var letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" r := make([]byte, 36) for i := 0; i < 36; i++ { num, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters)))) if err != nil { return "", nil } if i == 8 || i == 13 || i == 18 || i == 23 { r[i] = 45 } else { r[i] = letters[num.Int64()] } } return string(r), nil }