111 lines
2.9 KiB
Go
111 lines
2.9 KiB
Go
package logic
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
smsentity "spark-server/internal/module/sms/entity"
|
|
smsmodel "spark-server/internal/module/sms/model"
|
|
"spark-server/internal/pkg/errs"
|
|
"spark-server/internal/pkg/reqctx"
|
|
)
|
|
|
|
type stubEmail struct {
|
|
n int
|
|
}
|
|
|
|
func (s *stubEmail) SendOTP(context.Context, string, smsentity.Purpose, string, string) error {
|
|
s.n++
|
|
return nil
|
|
}
|
|
|
|
type stubPhone struct {
|
|
carrier smsentity.Carrier
|
|
n int
|
|
}
|
|
|
|
func (s *stubPhone) Carrier() smsentity.Carrier { return s.carrier }
|
|
|
|
func (s *stubPhone) SendOTP(context.Context, string, smsentity.Purpose, string) error {
|
|
s.n++
|
|
return nil
|
|
}
|
|
|
|
type stubAccounts struct {
|
|
email string
|
|
}
|
|
|
|
func (s stubAccounts) EmailByUserID(context.Context, int64) (string, error) {
|
|
return s.email, nil
|
|
}
|
|
|
|
func TestSendUnifiedEmail(t *testing.T) {
|
|
store := smsmodel.NewMemoryStore()
|
|
mail := &stubEmail{}
|
|
svc := NewService(store, mail, nil, nil)
|
|
out, err := svc.Send(t.Context(), SendCodeInput{
|
|
Purpose: smsentity.PurposeLogin,
|
|
Target: "ada@example.com",
|
|
})
|
|
if err != nil || out == nil || mail.n != 1 {
|
|
t.Fatalf("send %+v %v mail=%d", out, err, mail.n)
|
|
}
|
|
}
|
|
|
|
func TestSendPhoneDispatchesByCarrier(t *testing.T) {
|
|
store := smsmodel.NewMemoryStore()
|
|
mobile := &stubPhone{carrier: smsentity.CarrierMobile}
|
|
unicom := &stubPhone{carrier: smsentity.CarrierUnicom}
|
|
svc := NewService(store, nil, []PhoneCarrierSender{mobile, unicom}, nil)
|
|
_, err := svc.Send(t.Context(), SendCodeInput{
|
|
Purpose: smsentity.PurposeLogin,
|
|
Target: "13812345678",
|
|
})
|
|
if err != nil || mobile.n != 1 || unicom.n != 0 {
|
|
t.Fatalf("mobile %v mobile=%d unicom=%d", err, mobile.n, unicom.n)
|
|
}
|
|
_, err = svc.Send(t.Context(), SendCodeInput{
|
|
Purpose: smsentity.PurposeLogin,
|
|
Target: "13012345678",
|
|
})
|
|
if err != nil || unicom.n != 1 {
|
|
t.Fatalf("unicom %v unicom=%d", err, unicom.n)
|
|
}
|
|
}
|
|
|
|
func TestGuardAccountDeletePurpose(t *testing.T) {
|
|
store := smsmodel.NewMemoryStore()
|
|
svc := NewService(store, &stubEmail{}, nil, stubAccounts{email: "me@example.com"})
|
|
ctx := reqctx.With(t.Context(), &reqctx.RequestContext{UserID: 9})
|
|
_, err := svc.Send(ctx, SendCodeInput{
|
|
Purpose: smsentity.PurposeAccountDelete,
|
|
Target: "other@example.com",
|
|
})
|
|
if !errors.Is(err, errs.ErrForbidden) {
|
|
t.Fatalf("wrong email %v", err)
|
|
}
|
|
_, err = svc.Send(ctx, SendCodeInput{
|
|
Purpose: smsentity.PurposeAccountDelete,
|
|
Target: "me@example.com",
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestClearTargetRemovesCode(t *testing.T) {
|
|
store := smsmodel.NewMemoryStore()
|
|
svc := NewService(store, nil, nil, nil)
|
|
ctx := t.Context()
|
|
email := "ada@example.com"
|
|
key := storeKey(smsentity.ChannelEmail, smsentity.PurposeLogin, email)
|
|
if err := store.Put(ctx, key, "123456", 60); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
svc.ClearTarget(ctx, smsentity.ChannelEmail, email)
|
|
if err := svc.CheckAndConsume(ctx, smsentity.ChannelEmail, smsentity.PurposeLogin, email, "123456"); !errors.Is(err, errs.ErrVerifyCodeInvalid) {
|
|
t.Fatalf("still there %v", err)
|
|
}
|
|
}
|