80 lines
1.6 KiB
Go

package cache
import (
"backend/internal/domain"
"backend/pkg/cache"
"context"
"encoding/json"
"fmt"
"time"
"github.com/redis/go-redis/v9"
)
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.ExpiresAt)
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) Get(ctx context.Context, phone string) (*domain.OTP, error) {
key := r.getOTPKey(phone)
result, err := r.redis.Client().Get(ctx, key).Result()
if err != nil {
if err == redis.Nil {
return nil, fmt.Errorf("otp code not found")
}
return nil, err
}
var otp domain.OTP
if err := json.Unmarshal([]byte(result), &otp); err != nil {
return nil, err
}
if otp.IsExpired() {
r.Delete(ctx, phone)
return nil, fmt.Errorf("otp is expired")
}
return &otp, nil
}
func (r *OTPRepository) getOTPKey(phone string) string {
return fmt.Sprintf("challenge:%s", phone)
}