feat: add otp redis repo
This commit is contained in:
parent
75e1b5111e
commit
36cda3fd5a
@ -6,6 +6,7 @@ type Config struct {
|
||||
DB DB `mapstructure:"db"`
|
||||
Redis Redis `mapstructure:"redis"`
|
||||
KYCProvider KYC `mapstructure:"kyc"`
|
||||
OTP OTP `mapstructure:"otp"`
|
||||
}
|
||||
type Server struct {
|
||||
Host string `mapstructure:"host"`
|
||||
@ -36,3 +37,7 @@ type KYC struct {
|
||||
APIKey string `mapstructure:"api_key"`
|
||||
URL string `mapstructure:"url"`
|
||||
}
|
||||
|
||||
type OTP struct {
|
||||
CodeExpMinutes uint `mapstructure:"code_exp_minutes"`
|
||||
}
|
||||
|
||||
29
internal/domain/otp.go
Normal file
29
internal/domain/otp.go
Normal file
@ -0,0 +1,29 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"backend/pkg/util"
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type OTPRepo interface {
|
||||
Create(ctx context.Context, phone string, otp *OTP) error
|
||||
Delete(ctx context.Context, phone string) error
|
||||
}
|
||||
|
||||
type OTP struct {
|
||||
ID uuid.UUID
|
||||
Code string
|
||||
Phone string
|
||||
ExpiredAt time.Time
|
||||
}
|
||||
|
||||
func NewOTP(phone string) *OTP {
|
||||
return &OTP{
|
||||
ID: uuid.New(),
|
||||
Code: util.GenOTPCode(),
|
||||
Phone: phone,
|
||||
}
|
||||
}
|
||||
53
internal/repository/cache/otp_repo.go
vendored
Normal file
53
internal/repository/cache/otp_repo.go
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"backend/internal/domain"
|
||||
"backend/pkg/cache"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type OTPRepository struct {
|
||||
redis *cache.Redis
|
||||
}
|
||||
|
||||
func NewOTPRepository(redis *cache.Redis) domain.OTPRepo {
|
||||
return &OTPRepository{
|
||||
redis: redis,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *OTPRepository) Create(ctx context.Context, phone string, otp *domain.OTP) error {
|
||||
key := r.getOTPKey(phone)
|
||||
|
||||
otpData, err := json.Marshal(otp)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal otp: %w", err)
|
||||
}
|
||||
|
||||
ttl := time.Until(otp.ExpiredAt)
|
||||
if ttl <= 0 {
|
||||
return fmt.Errorf("OTP expired already")
|
||||
}
|
||||
|
||||
if err := r.redis.Client().Set(ctx, key, otpData, ttl).Err(); err != nil {
|
||||
return fmt.Errorf("failed to store otp in redis: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *OTPRepository) Delete(ctx context.Context, phone string) error {
|
||||
key := r.getOTPKey(phone)
|
||||
|
||||
if err := r.redis.Client().Del(ctx, key).Err(); err != nil {
|
||||
return fmt.Errorf("failed to del otp from redis")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *OTPRepository) getOTPKey(phone string) string {
|
||||
return fmt.Sprintf("challenge:%s", phone)
|
||||
}
|
||||
@ -189,3 +189,7 @@ func (s *authService) VerifyKYC(ctx context.Context, userID, nationalID, birthDa
|
||||
return fmt.Errorf("KYC verification failed - shahkar status: %d, identity status: %d",
|
||||
shahkarResp.StatusCode, identityResp.StatusCode)
|
||||
}
|
||||
|
||||
func (*authService) SendOTPVerifaction(ctx context.Context, phone string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
14
pkg/util/otp.go
Normal file
14
pkg/util/otp.go
Normal file
@ -0,0 +1,14 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func GenOTPCode() string {
|
||||
newRand := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
minNum := 100000
|
||||
maxNum := 999999
|
||||
return strconv.Itoa(newRand.Intn(maxNum-minNum+1) + minNum)
|
||||
}
|
||||
@ -21,3 +21,6 @@ jwt:
|
||||
|
||||
RPC:
|
||||
url: "exmaple.com"
|
||||
|
||||
otp:
|
||||
code_exp_minutes: 2
|
||||
Loading…
x
Reference in New Issue
Block a user