owpengram-server/internal/app/account/login_email_test.go

116 lines
3.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package account
import (
"context"
"errors"
"testing"
"telesrv/internal/domain"
"telesrv/internal/store/memory"
)
func newLoginEmailService(t *testing.T) (*Service, *memory.UserStore) {
t.Helper()
users := memory.NewUserStore()
svc := NewService(memory.NewPasswordStore(), WithUsers(users))
return svc, users
}
func createUser(t *testing.T, users *memory.UserStore, phone string) domain.User {
t.Helper()
u, err := users.Create(context.Background(), domain.User{Phone: phone, FirstName: "Test"})
if err != nil {
t.Fatalf("create user: %v", err)
}
return u
}
// TestSetLoginEmailPersistsAndMasks 设置登录邮箱后GetPassword 下发掩码 pattern原始
// 地址只在 LoginEmail 读路径可见。
func TestSetLoginEmailPersistsAndMasks(t *testing.T) {
ctx := context.Background()
svc, users := newLoginEmailService(t)
u := createUser(t, users, "15550010001")
if err := svc.SetLoginEmail(ctx, u.ID, "alice@example.com"); err != nil {
t.Fatalf("SetLoginEmail: %v", err)
}
settings, err := svc.GetPassword(ctx, u.ID)
if err != nil {
t.Fatalf("GetPassword: %v", err)
}
if got, want := settings.LoginEmailPattern, "a***e@example.com"; got != want {
t.Fatalf("LoginEmailPattern = %q, want %q", got, want)
}
if settings.LoginEmail != "alice@example.com" {
t.Fatalf("LoginEmail = %q, want raw address", settings.LoginEmail)
}
email, found, err := svc.LoginEmail(ctx, u.ID)
if err != nil || !found || email != "alice@example.com" {
t.Fatalf("LoginEmail = %q found=%v err=%v", email, found, err)
}
}
// TestLoginEmailByPhoneAndClear 验证按手机号读取/清除登录邮箱sendCode 检测 + reset 用)。
func TestLoginEmailByPhoneAndClear(t *testing.T) {
ctx := context.Background()
svc, users := newLoginEmailService(t)
createUser(t, users, "15550010002")
if err := svc.SetLoginEmailByPhone(ctx, "+1 555 001 0002", "bob@mail.com"); err != nil {
t.Fatalf("SetLoginEmailByPhone: %v", err)
}
email, found, err := svc.LoginEmailByPhone(ctx, "15550010002")
if err != nil || !found || email != "bob@mail.com" {
t.Fatalf("LoginEmailByPhone = %q found=%v err=%v", email, found, err)
}
if err := svc.ClearLoginEmailByPhone(ctx, "15550010002"); err != nil {
t.Fatalf("ClearLoginEmailByPhone: %v", err)
}
if _, found, _ := svc.LoginEmailByPhone(ctx, "15550010002"); found {
t.Fatal("login email still present after clear")
}
}
// TestSetLoginEmailRejectsInvalid 空/无 @ 的邮箱被拒。
func TestSetLoginEmailRejectsInvalid(t *testing.T) {
ctx := context.Background()
svc, users := newLoginEmailService(t)
u := createUser(t, users, "15550010003")
for _, bad := range []string{"", " ", "not-an-email"} {
if err := svc.SetLoginEmail(ctx, u.ID, bad); !errors.Is(err, domain.ErrEmailInvalid) {
t.Fatalf("SetLoginEmail(%q) err = %v, want ErrEmailInvalid", bad, err)
}
}
}
// TestRecoveryEmailDoesNotLeakIntoLoginEmailPattern 是核心解耦回归:设置 2FA 恢复邮箱
// 不得把恢复邮箱掩码写进 login_email_pattern历史 bug
func TestRecoveryEmailDoesNotLeakIntoLoginEmailPattern(t *testing.T) {
ctx := context.Background()
svc, users := newLoginEmailService(t)
u := createUser(t, users, "15550010004")
// 设置 2FA 恢复邮箱email-only 路径即可触发历史 bug 的写入点)。
if err := svc.UpdatePasswordSettings(ctx, u.ID, domain.PasswordCheck{Empty: true}, domain.PasswordInputSettings{
Email: "recovery@secret.com",
HasEmail: true,
}); err != nil {
t.Fatalf("UpdatePasswordSettings: %v", err)
}
settings, err := svc.GetPassword(ctx, u.ID)
if err != nil {
t.Fatalf("GetPassword: %v", err)
}
if settings.LoginEmailPattern != "" {
t.Fatalf("LoginEmailPattern = %q, want empty (recovery email must not leak into login email)", settings.LoginEmailPattern)
}
if !settings.HasRecovery {
t.Fatal("HasRecovery = false, want true after setting recovery email")
}
}