Hub-Api/services/authentication/generate_code.go

94 lines
2.1 KiB
Go

package authentication
import (
"errors"
"fmt"
"math/rand"
"netina/models"
"time"
"netina/validation"
"gorm.io/gorm"
)
type GenerateCode struct {
DB *gorm.DB
}
func NewGenerateCode(db *gorm.DB) *GenerateCode {
return &GenerateCode{DB: db}
}
// Generate a random 6-digit code
func generateCode() string {
rand.Seed(time.Now().UnixNano())
return fmt.Sprintf("%06d", rand.Intn(1000000))
}
// CreateLoginCode generates a login code and stores it in the database
func (s *GenerateCode) CreateLoginCode(phoneNumber string) (string, error) {
var code string
var isUnique bool
// Try to generate a unique code
for !isUnique {
code = generateCode()
isUnique, _ = s.isCodeUnique(code)
}
now := time.Now()
expiresAt := now.Add(2 * time.Minute)
loginCode := &models.LoginCode{
PhoneNumber: phoneNumber,
Code: code,
CreatedAt: now,
ExpiresAt: expiresAt,
}
if err := validation.ValidateStruct(loginCode); err != nil {
return "" , err
}
if err := s.DB.Create(loginCode).Error; err != nil {
return "", err
}
return code, nil
}
// Check if the generated code is unique
func (s *GenerateCode) isCodeUnique(code string) (bool, error) {
var loginCode models.LoginCode
if err := s.DB.Where("code = ?", code).First(&loginCode).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return true, nil
}
return false, err
}
return false, nil
}
// VerifyLoginCode verifies the login code and checks if it is still valid
func (s *GenerateCode) VerifyLoginCode(phoneNumber, code string) error {
var loginCode models.LoginCode
// Find the login code
if err := s.DB.Where("phone_number = ? AND code = ?", phoneNumber, code).First(&loginCode).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("code not found")
}
return err
}
// Check if the code has expired
if time.Now().After(loginCode.ExpiresAt) {
return errors.New("code expired")
}
return nil
}