94 lines
2.1 KiB
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
|
|
}
|
|
|
|
|