234 lines
7.9 KiB
Go
234 lines
7.9 KiB
Go
package rpc
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/iamxvbaba/td/tg"
|
|
"go.uber.org/zap/zaptest"
|
|
|
|
"telesrv/internal/domain"
|
|
)
|
|
|
|
type loginEmailAccountService struct {
|
|
AccountService
|
|
verifiedEmail string
|
|
}
|
|
|
|
func (s loginEmailAccountService) VerifyLoginEmail(context.Context, int64, string, string, string, bool) (string, error) {
|
|
return s.verifiedEmail, nil
|
|
}
|
|
|
|
func TestEmailSentCodeUsesDeliveryLength(t *testing.T) {
|
|
authSvc := &captureAuthService{
|
|
codeDelivery: domain.AuthCodeDelivery{
|
|
Kind: domain.AuthCodeDeliveryEmail,
|
|
EmailPattern: "a***e@example.test",
|
|
Length: 6,
|
|
},
|
|
}
|
|
r := New(Config{}, Deps{Auth: authSvc}, zaptest.NewLogger(t), fixedClock{now: time.Unix(1700000000, 0)})
|
|
|
|
sent, err := r.tgSentCodeForHash(context.Background(), "hash-email")
|
|
if err != nil {
|
|
t.Fatalf("tgSentCodeForHash: %v", err)
|
|
}
|
|
code, ok := sent.(*tg.AuthSentCode)
|
|
if !ok {
|
|
t.Fatalf("sent = %T, want *tg.AuthSentCode", sent)
|
|
}
|
|
emailType, ok := code.Type.(*tg.AuthSentCodeTypeEmailCode)
|
|
if !ok {
|
|
t.Fatalf("sent type = %T, want *tg.AuthSentCodeTypeEmailCode", code.Type)
|
|
}
|
|
if emailType.Length != 6 {
|
|
t.Fatalf("email sent code length = %d, want 6", emailType.Length)
|
|
}
|
|
}
|
|
|
|
// TestEmailSentCodeOmitsResetPeriodWhenUnavailable locks down the client
|
|
// signal for "this server can't service auth.resetLoginEmail" (no real SMS
|
|
// sender, or login email is this account's actual identity): the flags-
|
|
// optional reset_available_period field must be entirely absent, not merely
|
|
// 0, since 0 is also what "available right now" looks like on the wire.
|
|
func TestEmailSentCodeOmitsResetPeriodWhenUnavailable(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name string
|
|
resetAvailable bool
|
|
}{
|
|
{name: "unavailable", resetAvailable: false},
|
|
{name: "available", resetAvailable: true},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
authSvc := &captureAuthService{
|
|
codeDelivery: domain.AuthCodeDelivery{
|
|
Kind: domain.AuthCodeDeliveryEmail,
|
|
EmailPattern: "a***e@example.test",
|
|
Length: 6,
|
|
},
|
|
resetAvailable: tc.resetAvailable,
|
|
}
|
|
r := New(Config{}, Deps{Auth: authSvc}, zaptest.NewLogger(t), fixedClock{now: time.Unix(1700000000, 0)})
|
|
|
|
sent, err := r.tgSentCodeForHash(context.Background(), "hash-email")
|
|
if err != nil {
|
|
t.Fatalf("tgSentCodeForHash: %v", err)
|
|
}
|
|
code := sent.(*tg.AuthSentCode)
|
|
emailType := code.Type.(*tg.AuthSentCodeTypeEmailCode)
|
|
_, ok := emailType.GetResetAvailablePeriod()
|
|
if ok != tc.resetAvailable {
|
|
t.Fatalf("reset_available_period present = %v, want %v", ok, tc.resetAvailable)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAuthSignInRoutesOfficialEmailCodeCarriers(t *testing.T) {
|
|
const (
|
|
phone = "+86 188 0000 0021"
|
|
hash = "hash-email-login"
|
|
code = "654321"
|
|
)
|
|
tests := []struct {
|
|
name string
|
|
request func() *tg.AuthSignInRequest
|
|
wantPhoneCodeCalls int
|
|
wantEmailCodeCalls int
|
|
}{
|
|
{
|
|
name: "webk_phone_code",
|
|
request: func() *tg.AuthSignInRequest {
|
|
return &tg.AuthSignInRequest{PhoneNumber: phone, PhoneCodeHash: hash, PhoneCode: code}
|
|
},
|
|
wantPhoneCodeCalls: 1,
|
|
},
|
|
{
|
|
name: "tdesktop_android_email_verification",
|
|
request: func() *tg.AuthSignInRequest {
|
|
req := &tg.AuthSignInRequest{PhoneNumber: phone, PhoneCodeHash: hash}
|
|
req.SetEmailVerification(&tg.EmailVerificationCode{Code: code})
|
|
return req
|
|
},
|
|
wantEmailCodeCalls: 1,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
authSvc := &captureAuthService{signInUser: domain.User{ID: 100200301, Phone: "8618800000021", FirstName: "Alice"}}
|
|
r := New(Config{}, Deps{Auth: authSvc}, zaptest.NewLogger(t), fixedClock{now: time.Unix(1700000000, 0)})
|
|
|
|
if _, err := r.onAuthSignIn(context.Background(), tc.request()); err != nil {
|
|
t.Fatalf("onAuthSignIn: %v", err)
|
|
}
|
|
if authSvc.signInCount != tc.wantPhoneCodeCalls || authSvc.signInWithEmailCount != tc.wantEmailCodeCalls {
|
|
t.Fatalf("SignIn/SignInWithEmail calls=%d/%d, want %d/%d", authSvc.signInCount, authSvc.signInWithEmailCount, tc.wantPhoneCodeCalls, tc.wantEmailCodeCalls)
|
|
}
|
|
if tc.wantPhoneCodeCalls == 1 && (authSvc.signInPhone != phone || authSvc.signInHash != hash || authSvc.signInCode != code) {
|
|
t.Fatalf("SignIn proof=%q/%q/%q, want %q/%q/%q", authSvc.signInPhone, authSvc.signInHash, authSvc.signInCode, phone, hash, code)
|
|
}
|
|
if tc.wantEmailCodeCalls == 1 && (authSvc.signInWithEmailPhone != phone || authSvc.signInWithEmailHash != hash || authSvc.signInWithEmailCode != code) {
|
|
t.Fatalf("SignInWithEmail proof=%q/%q/%q, want %q/%q/%q", authSvc.signInWithEmailPhone, authSvc.signInWithEmailHash, authSvc.signInWithEmailCode, phone, hash, code)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAccountVerifyEmailLoginSetupReturnsSentCodeSuccess(t *testing.T) {
|
|
user := domain.User{
|
|
ID: 100200300,
|
|
AccessHash: 900100200,
|
|
Phone: "8618800000020",
|
|
FirstName: "Alice",
|
|
}
|
|
authSvc := &captureAuthService{signInUser: user}
|
|
r := New(Config{}, Deps{
|
|
Auth: authSvc,
|
|
Account: loginEmailAccountService{verifiedEmail: "alice@example.test"},
|
|
}, zaptest.NewLogger(t), fixedClock{now: time.Unix(1700000000, 0)})
|
|
|
|
got, err := r.onAccountVerifyEmail(context.Background(), &tg.AccountVerifyEmailRequest{
|
|
Purpose: &tg.EmailVerifyPurposeLoginSetup{
|
|
PhoneNumber: "+86 188 0000 0020",
|
|
PhoneCodeHash: "hash-email-setup",
|
|
},
|
|
Verification: &tg.EmailVerificationCode{Code: "654321"},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("onAccountVerifyEmail: %v", err)
|
|
}
|
|
verified, ok := got.(*tg.AccountEmailVerifiedLogin)
|
|
if !ok {
|
|
t.Fatalf("verified = %T, want *tg.AccountEmailVerifiedLogin", got)
|
|
}
|
|
if verified.Email != "alice@example.test" {
|
|
t.Fatalf("verified email = %q", verified.Email)
|
|
}
|
|
success, ok := verified.SentCode.(*tg.AuthSentCodeSuccess)
|
|
if !ok {
|
|
t.Fatalf("sent code = %T, want *tg.AuthSentCodeSuccess", verified.SentCode)
|
|
}
|
|
authorization, ok := success.Authorization.(*tg.AuthAuthorization)
|
|
if !ok {
|
|
t.Fatalf("authorization = %T, want *tg.AuthAuthorization", success.Authorization)
|
|
}
|
|
self, ok := authorization.User.(*tg.User)
|
|
if !ok {
|
|
t.Fatalf("authorization user = %T, want *tg.User", authorization.User)
|
|
}
|
|
if self.ID != user.ID || !self.Self {
|
|
t.Fatalf("authorization user = %+v, want self user %d", self, user.ID)
|
|
}
|
|
if authSvc.signInWithEmailCount != 1 {
|
|
t.Fatalf("SignInWithEmail calls = %d, want 1", authSvc.signInWithEmailCount)
|
|
}
|
|
}
|
|
|
|
func TestAccountVerifyEmailLoginSetupAndroidReturnsEmailSentCode(t *testing.T) {
|
|
authSvc := &captureAuthService{}
|
|
r := New(Config{}, Deps{
|
|
Auth: authSvc,
|
|
Account: loginEmailAccountService{verifiedEmail: "alice@example.test"},
|
|
}, zaptest.NewLogger(t), fixedClock{now: time.Unix(1700000000, 0)})
|
|
|
|
ctx := WithClientInfo(context.Background(), ClientInfo{
|
|
Type: ClientTypeAndroid,
|
|
AppVersion: "12.8.1 (69169) pbeta",
|
|
})
|
|
got, err := r.onAccountVerifyEmail(ctx, &tg.AccountVerifyEmailRequest{
|
|
Purpose: &tg.EmailVerifyPurposeLoginSetup{
|
|
PhoneNumber: "+86 188 0000 0020",
|
|
PhoneCodeHash: "hash-email-setup",
|
|
},
|
|
Verification: &tg.EmailVerificationCode{Code: "654321"},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("onAccountVerifyEmail: %v", err)
|
|
}
|
|
verified, ok := got.(*tg.AccountEmailVerifiedLogin)
|
|
if !ok {
|
|
t.Fatalf("verified = %T, want *tg.AccountEmailVerifiedLogin", got)
|
|
}
|
|
sent, ok := verified.SentCode.(*tg.AuthSentCode)
|
|
if !ok {
|
|
t.Fatalf("sent code = %T, want *tg.AuthSentCode", verified.SentCode)
|
|
}
|
|
if sent.PhoneCodeHash != "hash-email-setup" {
|
|
t.Fatalf("phone_code_hash = %q", sent.PhoneCodeHash)
|
|
}
|
|
emailType, ok := sent.Type.(*tg.AuthSentCodeTypeEmailCode)
|
|
if !ok {
|
|
t.Fatalf("sent type = %T, want *tg.AuthSentCodeTypeEmailCode", sent.Type)
|
|
}
|
|
if emailType.EmailPattern != "a***e@example.test" {
|
|
t.Fatalf("email pattern = %q", emailType.EmailPattern)
|
|
}
|
|
if emailType.Length != 6 {
|
|
t.Fatalf("email code length = %d, want 6", emailType.Length)
|
|
}
|
|
if authSvc.signInWithEmailCount != 0 {
|
|
t.Fatalf("SignInWithEmail calls = %d, want 0 for Android compat downgrade", authSvc.signInWithEmailCount)
|
|
}
|
|
}
|