template-monorepo/internal/model/member/usecase/otp_usecase_test.go

119 lines
3.2 KiB
Go

package usecase_test
import (
"context"
"testing"
memberconfig "gateway/internal/model/member/config"
"gateway/internal/model/member/domain/enum"
domusecase "gateway/internal/model/member/domain/usecase"
"gateway/internal/model/member/repository"
"gateway/internal/model/member/usecase"
redislib "gateway/internal/library/redis"
"github.com/alicebob/miniredis/v2"
"github.com/stretchr/testify/require"
"github.com/zeromicro/go-zero/core/stores/redis"
)
func TestOTPUseCase_GenerateAndVerify(t *testing.T) {
mr := miniredis.RunT(t)
rds, err := redislib.NewClient(redis.RedisConf{Host: mr.Addr(), Type: "node"})
require.NoError(t, err)
uc := usecase.MustOTPUseCase(usecase.OTPUseCaseParam{
Store: repository.NewRedisOTPChallengeStore(rds),
Config: memberconfig.Config{}.Defaults(),
})
dto, code, err := uc.Generate(context.Background(), &domusecase.GenerateOTPRequest{
TenantID: "t1",
UID: "u1",
Purpose: enum.OTPPurposeBusinessEmail,
Target: "user@example.com",
})
require.NoError(t, err)
require.NotEmpty(t, code)
target, err := uc.Verify(context.Background(), &domusecase.VerifyOTPRequest{
TenantID: "t1",
UID: "u1",
ChallengeID: dto.ChallengeID,
Code: code,
Purpose: enum.OTPPurposeBusinessEmail,
})
require.NoError(t, err)
require.Equal(t, "user@example.com", target)
}
func TestOTPUseCase_VerifyUIDMismatch(t *testing.T) {
mr := miniredis.RunT(t)
rds, err := redislib.NewClient(redis.RedisConf{Host: mr.Addr(), Type: "node"})
require.NoError(t, err)
uc := usecase.MustOTPUseCase(usecase.OTPUseCaseParam{
Store: repository.NewRedisOTPChallengeStore(rds),
Config: memberconfig.Config{}.Defaults(),
})
dto, code, err := uc.Generate(context.Background(), &domusecase.GenerateOTPRequest{
TenantID: "t1",
UID: "victim",
Purpose: enum.OTPPurposeBusinessEmail,
Target: "user@example.com",
})
require.NoError(t, err)
_, err = uc.Verify(context.Background(), &domusecase.VerifyOTPRequest{
TenantID: "t1",
UID: "attacker",
ChallengeID: dto.ChallengeID,
Code: code,
Purpose: enum.OTPPurposeBusinessEmail,
})
require.Error(t, err)
}
func TestOTPUseCase_MaxAttemptsLocks(t *testing.T) {
mr := miniredis.RunT(t)
rds, err := redislib.NewClient(redis.RedisConf{Host: mr.Addr(), Type: "node"})
require.NoError(t, err)
cfg := memberconfig.Config{}.Defaults()
cfg.OTP.MaxAttempts = 2
uc := usecase.MustOTPUseCase(usecase.OTPUseCaseParam{
Store: repository.NewRedisOTPChallengeStore(rds),
Config: cfg,
})
dto, _, err := uc.Generate(context.Background(), &domusecase.GenerateOTPRequest{
TenantID: "t1",
UID: "u1",
Purpose: enum.OTPPurposeBusinessEmail,
Target: "user@example.com",
})
require.NoError(t, err)
for range cfg.OTP.MaxAttempts {
_, err = uc.Verify(context.Background(), &domusecase.VerifyOTPRequest{
TenantID: "t1",
UID: "u1",
ChallengeID: dto.ChallengeID,
Code: "000000",
Purpose: enum.OTPPurposeBusinessEmail,
})
require.Error(t, err)
}
_, err = uc.Verify(context.Background(), &domusecase.VerifyOTPRequest{
TenantID: "t1",
UID: "u1",
ChallengeID: dto.ChallengeID,
Code: "000000",
Purpose: enum.OTPPurposeBusinessEmail,
})
require.Error(t, err)
}