Aditya Siregar be92ec8b23 test wheels
2025-09-18 12:01:20 +07:00

117 lines
4.6 KiB
Go

package repository
import (
"context"
"fmt"
"time"
"apskel-pos-be/internal/entities"
"gorm.io/gorm"
)
type OtpRepository interface {
CreateOtpSession(ctx context.Context, otpSession *entities.OtpSession) error
GetOtpSessionByToken(ctx context.Context, token string) (*entities.OtpSession, error)
GetOtpSessionByPhoneAndPurpose(ctx context.Context, phoneNumber string, purpose string) (*entities.OtpSession, error)
GetLastOtpSessionByPhoneAndPurpose(ctx context.Context, phoneNumber string, purpose string) (*entities.OtpSession, error)
GetOtpSessionByRegistrationToken(ctx context.Context, registrationToken string) (*entities.OtpSession, error)
UpdateOtpSession(ctx context.Context, otpSession *entities.OtpSession) error
DeleteOtpSession(ctx context.Context, token string) error
DeleteExpiredOtpSessions(ctx context.Context) error
InvalidateOtpSessionsByPhone(ctx context.Context, phoneNumber string, purpose string) error
}
type otpRepository struct {
db *gorm.DB
}
func NewOtpRepository(db *gorm.DB) OtpRepository {
return &otpRepository{
db: db,
}
}
func (r *otpRepository) CreateOtpSession(ctx context.Context, otpSession *entities.OtpSession) error {
if err := r.db.WithContext(ctx).Create(otpSession).Error; err != nil {
return fmt.Errorf("failed to create OTP session: %w", err)
}
return nil
}
func (r *otpRepository) GetOtpSessionByToken(ctx context.Context, token string) (*entities.OtpSession, error) {
var otpSession entities.OtpSession
if err := r.db.WithContext(ctx).Where("token = ?", token).First(&otpSession).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil // OTP session not found, not an error
}
return nil, fmt.Errorf("failed to get OTP session by token: %w", err)
}
return &otpSession, nil
}
func (r *otpRepository) GetOtpSessionByPhoneAndPurpose(ctx context.Context, phoneNumber string, purpose string) (*entities.OtpSession, error) {
var otpSession entities.OtpSession
if err := r.db.WithContext(ctx).Where("phone_number = ? AND purpose = ? AND is_used = false AND expires_at > ?",
phoneNumber, purpose, time.Now()).Order("created_at DESC").First(&otpSession).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil // No active OTP session found
}
return nil, fmt.Errorf("failed to get OTP session by phone and purpose: %w", err)
}
return &otpSession, nil
}
func (r *otpRepository) GetLastOtpSessionByPhoneAndPurpose(ctx context.Context, phoneNumber string, purpose string) (*entities.OtpSession, error) {
var otpSession entities.OtpSession
if err := r.db.WithContext(ctx).Where("phone_number = ? AND purpose = ?",
phoneNumber, purpose).Order("created_at DESC").First(&otpSession).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil // No OTP session found
}
return nil, fmt.Errorf("failed to get last OTP session by phone and purpose: %w", err)
}
return &otpSession, nil
}
func (r *otpRepository) GetOtpSessionByRegistrationToken(ctx context.Context, registrationToken string) (*entities.OtpSession, error) {
var otpSession entities.OtpSession
if err := r.db.WithContext(ctx).Where("metadata->>'registration_token' = ? AND purpose = ?",
registrationToken, "registration").First(&otpSession).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil // OTP session not found
}
return nil, fmt.Errorf("failed to get OTP session by registration token: %w", err)
}
return &otpSession, nil
}
func (r *otpRepository) UpdateOtpSession(ctx context.Context, otpSession *entities.OtpSession) error {
if err := r.db.WithContext(ctx).Save(otpSession).Error; err != nil {
return fmt.Errorf("failed to update OTP session: %w", err)
}
return nil
}
func (r *otpRepository) DeleteOtpSession(ctx context.Context, token string) error {
if err := r.db.WithContext(ctx).Where("token = ?", token).Delete(&entities.OtpSession{}).Error; err != nil {
return fmt.Errorf("failed to delete OTP session: %w", err)
}
return nil
}
func (r *otpRepository) DeleteExpiredOtpSessions(ctx context.Context) error {
if err := r.db.WithContext(ctx).Where("expires_at < ?", time.Now()).Delete(&entities.OtpSession{}).Error; err != nil {
return fmt.Errorf("failed to delete expired OTP sessions: %w", err)
}
return nil
}
func (r *otpRepository) InvalidateOtpSessionsByPhone(ctx context.Context, phoneNumber string, purpose string) error {
if err := r.db.WithContext(ctx).Model(&entities.OtpSession{}).Where("phone_number = ? AND purpose = ? AND is_used = false",
phoneNumber, purpose).Update("is_used", true).Error; err != nil {
return fmt.Errorf("failed to invalidate OTP sessions: %w", err)
}
return nil
}