214 lines
5.7 KiB
Go
214 lines
5.7 KiB
Go
package services
|
|
|
|
// import (
|
|
// "errors"
|
|
// "fmt"
|
|
// "math/rand"
|
|
// "rijig/config"
|
|
// "rijig/dto"
|
|
// "rijig/internal/repositories"
|
|
// "rijig/model"
|
|
// "rijig/utils"
|
|
// "time"
|
|
|
|
// "github.com/golang-jwt/jwt/v5"
|
|
// )
|
|
|
|
// const otpCooldown = 30 * time.Second
|
|
|
|
// type AuthService interface {
|
|
// RegisterOrLogin(req *dto.RegisterRequest) error
|
|
// VerifyOTP(req *dto.VerifyOTPRequest) (*dto.UserDataResponse, error)
|
|
// Logout(userID, phone string) error
|
|
// }
|
|
|
|
// type authService struct {
|
|
// userRepo repositories.UserRepository
|
|
// roleRepo repositories.RoleRepository
|
|
// }
|
|
|
|
// func NewAuthService(userRepo repositories.UserRepository, roleRepo repositories.RoleRepository) AuthService {
|
|
// return &authService{userRepo, roleRepo}
|
|
// }
|
|
|
|
// func (s *authService) RegisterOrLogin(req *dto.RegisterRequest) error {
|
|
|
|
// if err := s.checkOTPRequestCooldown(req.Phone); err != nil {
|
|
// return err
|
|
// }
|
|
|
|
// user, err := s.userRepo.GetUserByPhoneAndRole(req.Phone, req.RoleID)
|
|
// if err != nil {
|
|
// return fmt.Errorf("failed to check existing user: %w", err)
|
|
// }
|
|
|
|
// if user != nil {
|
|
// return s.sendOTP(req.Phone)
|
|
// }
|
|
|
|
// user = &model.User{
|
|
// Phone: req.Phone,
|
|
// RoleID: req.RoleID,
|
|
// }
|
|
|
|
// createdUser, err := s.userRepo.CreateUser(user)
|
|
// if err != nil {
|
|
// return fmt.Errorf("failed to create new user: %w", err)
|
|
// }
|
|
|
|
// if err := s.saveUserToRedis(createdUser.ID, createdUser, req.Phone); err != nil {
|
|
// return err
|
|
// }
|
|
|
|
// return s.sendOTP(req.Phone)
|
|
// }
|
|
|
|
// func (s *authService) checkOTPRequestCooldown(phone string) error {
|
|
// otpSentTime, err := utils.GetStringData("otp_sent:" + phone)
|
|
// if err != nil || otpSentTime == "" {
|
|
// return nil
|
|
// }
|
|
// lastSent, _ := time.Parse(time.RFC3339, otpSentTime)
|
|
// if time.Since(lastSent) < otpCooldown {
|
|
// return errors.New("please wait before requesting a new OTP")
|
|
// }
|
|
// return nil
|
|
// }
|
|
|
|
// func (s *authService) sendOTP(phone string) error {
|
|
// otp := generateOTP()
|
|
// if err := config.SendWhatsAppMessage(phone, fmt.Sprintf("Your OTP is: %s", otp)); err != nil {
|
|
// return err
|
|
// }
|
|
|
|
// if err := utils.SetStringData("otp:"+phone, otp, 10*time.Minute); err != nil {
|
|
// return err
|
|
// }
|
|
// return utils.SetStringData("otp_sent:"+phone, time.Now().Format(time.RFC3339), 10*time.Minute)
|
|
// }
|
|
|
|
// func (s *authService) VerifyOTP(req *dto.VerifyOTPRequest) (*dto.UserDataResponse, error) {
|
|
|
|
// storedOTP, err := utils.GetStringData("otp:" + req.Phone)
|
|
// if err != nil || storedOTP == "" {
|
|
// return nil, errors.New("OTP expired or not found")
|
|
// }
|
|
|
|
// if storedOTP != req.OTP {
|
|
// return nil, errors.New("invalid OTP")
|
|
// }
|
|
|
|
// if err := utils.DeleteData("otp:" + req.Phone); err != nil {
|
|
// return nil, fmt.Errorf("failed to remove OTP from Redis: %w", err)
|
|
// }
|
|
|
|
// existingUser, err := s.userRepo.GetUserByPhoneAndRole(req.Phone, req.RoleID)
|
|
// if err != nil {
|
|
// return nil, fmt.Errorf("failed to check existing user: %w", err)
|
|
// }
|
|
|
|
// var user *model.User
|
|
// if existingUser != nil {
|
|
// user = existingUser
|
|
// } else {
|
|
|
|
// user = &model.User{
|
|
// Phone: req.Phone,
|
|
// RoleID: req.RoleID,
|
|
// }
|
|
// createdUser, err := s.userRepo.CreateUser(user)
|
|
// if err != nil {
|
|
// return nil, err
|
|
// }
|
|
// user = createdUser
|
|
// }
|
|
|
|
// token, err := s.generateJWTToken(user.ID)
|
|
// if err != nil {
|
|
// return nil, err
|
|
// }
|
|
|
|
// role, err := s.roleRepo.FindByID(user.RoleID)
|
|
// if err != nil {
|
|
// return nil, fmt.Errorf("failed to get role: %w", err)
|
|
// }
|
|
|
|
// if err := s.saveSessionData(user.ID, user.RoleID, role.RoleName, token); err != nil {
|
|
// return nil, err
|
|
// }
|
|
|
|
// return &dto.UserDataResponse{
|
|
// UserID: user.ID,
|
|
// UserRole: role.RoleName,
|
|
// Token: token,
|
|
// }, nil
|
|
// }
|
|
|
|
// func (s *authService) saveUserToRedis(userID string, user *model.User, phone string) error {
|
|
// if err := utils.SetJSONData("user:"+userID, user, 10*time.Minute); err != nil {
|
|
// return fmt.Errorf("failed to store user data in Redis: %w", err)
|
|
// }
|
|
|
|
// if err := utils.SetStringData("user_phone:"+userID, phone, 10*time.Minute); err != nil {
|
|
// return fmt.Errorf("failed to store user phone in Redis: %w", err)
|
|
// }
|
|
|
|
// return nil
|
|
// }
|
|
|
|
// func (s *authService) generateJWTToken(userID string) (string, error) {
|
|
// expirationTime := time.Now().Add(24 * time.Hour)
|
|
// claims := &jwt.RegisteredClaims{
|
|
// Subject: userID,
|
|
// ExpiresAt: jwt.NewNumericDate(expirationTime),
|
|
// }
|
|
|
|
// token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
|
// secretKey := config.GetSecretKey()
|
|
|
|
// return token.SignedString([]byte(secretKey))
|
|
// }
|
|
|
|
// func (s *authService) saveSessionData(userID string, roleID string, roleName string, token string) error {
|
|
// sessionKey := fmt.Sprintf("session:%s", userID)
|
|
// sessionData := map[string]interface{}{
|
|
// "userID": userID,
|
|
// "roleID": roleID,
|
|
// "roleName": roleName,
|
|
// }
|
|
|
|
// if err := utils.SetJSONData(sessionKey, sessionData, 24*time.Hour); err != nil {
|
|
// return fmt.Errorf("failed to set session data: %w", err)
|
|
// }
|
|
|
|
// if err := utils.SetStringData("session_token:"+userID, token, 24*time.Hour); err != nil {
|
|
// return fmt.Errorf("failed to set session token: %w", err)
|
|
// }
|
|
|
|
// return nil
|
|
// }
|
|
|
|
// func (s *authService) Logout(userID, phone string) error {
|
|
// keys := []string{
|
|
// "session:" + userID,
|
|
// "session_token:" + userID,
|
|
// "user_logged_in:" + userID,
|
|
// "user:" + userID,
|
|
// "user_phone:" + userID,
|
|
// "otp_sent:" + phone,
|
|
// }
|
|
|
|
// for _, key := range keys {
|
|
// if err := utils.DeleteData(key); err != nil {
|
|
// return fmt.Errorf("failed to delete key %s from Redis: %w", key, err)
|
|
// }
|
|
// }
|
|
|
|
// return nil
|
|
// }
|
|
|
|
// func generateOTP() string {
|
|
// randGenerator := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
// return fmt.Sprintf("%04d", randGenerator.Intn(10000))
|
|
// }
|