141 lines
3.4 KiB
Go
141 lines
3.4 KiB
Go
package services
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"math/rand"
|
|
|
|
"rijig/config"
|
|
"rijig/dto"
|
|
"rijig/internal/repositories"
|
|
"rijig/model"
|
|
)
|
|
|
|
type AuthService interface {
|
|
RegisterUser(request *dto.RegisterRequest) error
|
|
VerifyOTP(request *dto.VerifyOTPRequest) error
|
|
}
|
|
|
|
type authService struct {
|
|
userRepo repositories.UserRepository
|
|
roleRepo repositories.RoleRepository
|
|
redisRepo repositories.RedisRepository
|
|
}
|
|
|
|
func NewAuthService(userRepo repositories.UserRepository, roleRepo repositories.RoleRepository, redisRepo repositories.RedisRepository) AuthService {
|
|
return &authService{
|
|
userRepo: userRepo,
|
|
roleRepo: roleRepo,
|
|
redisRepo: redisRepo,
|
|
}
|
|
}
|
|
|
|
func (s *authService) RegisterUser(request *dto.RegisterRequest) error {
|
|
|
|
if request.RoleID == "" {
|
|
return fmt.Errorf("role_id cannot be empty")
|
|
}
|
|
|
|
role, err := s.roleRepo.FindByID(request.RoleID)
|
|
if err != nil {
|
|
return fmt.Errorf("role not found: %v", err)
|
|
}
|
|
if role == nil {
|
|
return fmt.Errorf("role with ID %s not found", request.RoleID)
|
|
}
|
|
|
|
existingUser, err := s.userRepo.FindByPhone(request.Phone)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to check existing user: %v", err)
|
|
}
|
|
if existingUser != nil {
|
|
return fmt.Errorf("phone number already registered")
|
|
}
|
|
|
|
temporaryData := &model.User{
|
|
Phone: request.Phone,
|
|
RoleID: request.RoleID,
|
|
}
|
|
|
|
err = s.redisRepo.StoreData(request.Phone, temporaryData, 1*time.Hour)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to store registration data in Redis: %v", err)
|
|
}
|
|
|
|
otp := generateOTP()
|
|
err = s.redisRepo.StoreData("otp:"+request.Phone, otp, 10*time.Minute)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to store OTP in Redis: %v", err)
|
|
}
|
|
|
|
err = config.SendWhatsAppMessage(request.Phone, fmt.Sprintf("Your OTP is: %s", otp))
|
|
if err != nil {
|
|
return fmt.Errorf("failed to send OTP via WhatsApp: %v", err)
|
|
}
|
|
|
|
log.Printf("OTP sent to phone number: %s", request.Phone)
|
|
return nil
|
|
}
|
|
|
|
func (s *authService) VerifyOTP(request *dto.VerifyOTPRequest) error {
|
|
|
|
storedOTP, err := s.redisRepo.GetData("otp:" + request.Phone)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to retrieve OTP from Redis: %v", err)
|
|
}
|
|
if storedOTP != request.OTP {
|
|
return fmt.Errorf("invalid OTP")
|
|
}
|
|
|
|
temporaryData, err := s.redisRepo.GetData(request.Phone)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get registration data from Redis: %v", err)
|
|
}
|
|
if temporaryData == "" {
|
|
return fmt.Errorf("no registration data found for phone: %s", request.Phone)
|
|
}
|
|
|
|
temporaryDataStr, ok := temporaryData.(string)
|
|
if !ok {
|
|
return fmt.Errorf("failed to assert data to string")
|
|
}
|
|
|
|
temporaryDataBytes := []byte(temporaryDataStr)
|
|
|
|
var user model.User
|
|
err = json.Unmarshal(temporaryDataBytes, &user)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to unmarshal registration data: %v", err)
|
|
}
|
|
|
|
_, err = s.userRepo.SaveUser(&user)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to save user to database: %v", err)
|
|
}
|
|
|
|
err = s.redisRepo.DeleteData(request.Phone)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete registration data from Redis: %v", err)
|
|
}
|
|
|
|
err = s.redisRepo.DeleteData("otp:" + request.Phone)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete OTP from Redis: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func generateOTP() string {
|
|
|
|
return fmt.Sprintf("%06d", RandomInt(100000, 999999))
|
|
}
|
|
|
|
func RandomInt(min, max int) int {
|
|
rand.Seed(time.Now().UnixNano())
|
|
return rand.Intn(max-min+1) + min
|
|
}
|