121 lines
2.9 KiB
Go
121 lines
2.9 KiB
Go
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: %s", 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 := validatePasswordLength(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())})
|
|
|
|
log.Info().Msg("Login user: " + user.Email)
|
|
|
|
return c.JSON(structs.UserLoginResponse{Session: session})
|
|
}
|
|
|
|
func UserLogout(c *fiber.Ctx) error {
|
|
session := utils.GetXAuhorizationHeader(c)
|
|
|
|
if len(session) != utils.LenHeaderXAuthorization {
|
|
return c.SendStatus(fiber.StatusUnauthorized)
|
|
}
|
|
|
|
log.Info().Msg(session)
|
|
|
|
database.DB.Delete(&structs.UserSession{}, "id = ?", session)
|
|
|
|
socketclients.CloseAllUserSessionConnections(session)
|
|
|
|
return c.SendStatus(fiber.StatusCreated)
|
|
}
|
|
|
|
func validatePasswordLength(password string) bool {
|
|
lenPassword := len(password)
|
|
|
|
if lenPassword < utils.MinPassword || lenPassword > utils.MaxPassword {
|
|
log.Error().Msg("Password length not valid")
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
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
|
|
}
|