6679260d0a
Thread the Telegram bot's service language (en/ru) from the session mint response through the gateway into the FlatBuffers Session, so the UI knows which bot the player signed in through. handleTelegramAuth refreshes the account's service language onto the response before minting (it was set after the fetched copy). Empty for a non-Telegram login.
135 lines
5.0 KiB
Go
135 lines
5.0 KiB
Go
package transcode_test
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"testing"
|
|
|
|
flatbuffers "github.com/google/flatbuffers/go"
|
|
|
|
"scrabble/gateway/internal/connector"
|
|
"scrabble/gateway/internal/transcode"
|
|
fb "scrabble/pkg/fbs/scrabblefb"
|
|
)
|
|
|
|
// fakeValidator stands in for the connector's ValidateInitData RPC.
|
|
type fakeValidator struct {
|
|
user connector.User
|
|
err error
|
|
}
|
|
|
|
func (f fakeValidator) ValidateInitData(context.Context, string) (connector.User, error) {
|
|
return f.user, f.err
|
|
}
|
|
|
|
func (f fakeValidator) ValidateLoginWidget(context.Context, string) (connector.User, error) {
|
|
return f.user, f.err
|
|
}
|
|
|
|
func telegramLoginPayload(initData string) []byte {
|
|
b := flatbuffers.NewBuilder(0)
|
|
off := b.CreateString(initData)
|
|
fb.TelegramLoginRequestStart(b)
|
|
fb.TelegramLoginRequestAddInitData(b, off)
|
|
b.Finish(fb.TelegramLoginRequestEnd(b))
|
|
return b.FinishedBytes()
|
|
}
|
|
|
|
func TestTelegramAuthForwardsSeedFields(t *testing.T) {
|
|
var gotBody map[string]string
|
|
backend, cleanup := fakeBackend(t, func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/api/v1/internal/sessions/telegram" {
|
|
t.Errorf("unexpected path %q", r.URL.Path)
|
|
}
|
|
_ = json.NewDecoder(r.Body).Decode(&gotBody)
|
|
_, _ = w.Write([]byte(`{"token":"tok-tg","user_id":"u-tg","is_guest":false,"display_name":"Иван","service_language":"ru"}`))
|
|
})
|
|
defer cleanup()
|
|
|
|
v := fakeValidator{user: connector.User{ExternalID: "42", Username: "neo", FirstName: "Иван", LanguageCode: "ru", ServiceLanguage: "ru", SupportedLanguages: []string{"ru"}}}
|
|
reg := transcode.NewRegistry(backend, v)
|
|
op, ok := reg.Lookup(transcode.MsgAuthTelegram)
|
|
if !ok {
|
|
t.Fatal("auth.telegram not registered")
|
|
}
|
|
|
|
payload, err := op.Handler(context.Background(), transcode.Request{Payload: telegramLoginPayload("init")})
|
|
if err != nil {
|
|
t.Fatalf("handler: %v", err)
|
|
}
|
|
sess := fb.GetRootAsSession(payload, 0)
|
|
if string(sess.Token()) != "tok-tg" || string(sess.UserId()) != "u-tg" {
|
|
t.Fatalf("session decoded wrong: token=%q user=%q", sess.Token(), sess.UserId())
|
|
}
|
|
// The validating bot's supported languages ride the Session so the UI gates the
|
|
// New Game variant choice (here: ru -> Russian + Эрудит only).
|
|
if got := sessionLanguages(sess); len(got) != 1 || got[0] != "ru" {
|
|
t.Errorf("session supported_languages = %v, want [ru]", got)
|
|
}
|
|
// The bot's service language rides the Session so the UI can build a share link to
|
|
// the same bot.
|
|
if got := string(sess.ServiceLanguage()); got != "ru" {
|
|
t.Errorf("session service_language = %q, want ru", got)
|
|
}
|
|
// The validated launch fields are forwarded so the backend can seed a new account;
|
|
// service_language is recorded to route the account's later out-of-app push.
|
|
if gotBody["external_id"] != "42" || gotBody["language_code"] != "ru" || gotBody["first_name"] != "Иван" || gotBody["service_language"] != "ru" {
|
|
t.Errorf("forwarded body = %+v, want external_id=42 language_code=ru first_name=Иван service_language=ru", gotBody)
|
|
}
|
|
}
|
|
|
|
// sessionLanguages reads the supported_languages vector off a decoded Session.
|
|
func sessionLanguages(s *fb.Session) []string {
|
|
out := make([]string, s.SupportedLanguagesLength())
|
|
for i := range out {
|
|
out[i] = string(s.SupportedLanguages(i))
|
|
}
|
|
return out
|
|
}
|
|
|
|
// TestGuestAuthSeedsDefaultLanguages confirms a non-platform (guest) session carries
|
|
// the gateway's default supported-languages set, so the web client is ungated.
|
|
func TestGuestAuthSeedsDefaultLanguages(t *testing.T) {
|
|
backend, cleanup := fakeBackend(t, func(w http.ResponseWriter, _ *http.Request) {
|
|
_, _ = w.Write([]byte(`{"token":"tok-g","user_id":"u-g","is_guest":true,"display_name":"Guest"}`))
|
|
})
|
|
defer cleanup()
|
|
|
|
reg := transcode.NewRegistry(backend, nil, "en", "ru")
|
|
op, _ := reg.Lookup(transcode.MsgAuthGuest)
|
|
payload, err := op.Handler(context.Background(), transcode.Request{})
|
|
if err != nil {
|
|
t.Fatalf("handler: %v", err)
|
|
}
|
|
if got := sessionLanguages(fb.GetRootAsSession(payload, 0)); len(got) != 2 || got[0] != "en" || got[1] != "ru" {
|
|
t.Errorf("guest session supported_languages = %v, want [en ru]", got)
|
|
}
|
|
}
|
|
|
|
func TestTelegramAuthInvalidInitData(t *testing.T) {
|
|
backend, cleanup := fakeBackend(t, func(http.ResponseWriter, *http.Request) {
|
|
t.Error("backend must not be called when initData is invalid")
|
|
})
|
|
defer cleanup()
|
|
|
|
reg := transcode.NewRegistry(backend, fakeValidator{err: connector.ErrInvalidInitData})
|
|
op, _ := reg.Lookup(transcode.MsgAuthTelegram)
|
|
|
|
_, err := op.Handler(context.Background(), transcode.Request{Payload: telegramLoginPayload("bad")})
|
|
if code, ok := transcode.DomainCode(err); !ok || code != "invalid_init_data" {
|
|
t.Errorf("DomainCode = (%q, %v), want (invalid_init_data, true)", code, ok)
|
|
}
|
|
}
|
|
|
|
// TestTelegramAuthDisabledWithoutConnector confirms a nil validator leaves
|
|
// auth.telegram unregistered.
|
|
func TestTelegramAuthDisabledWithoutConnector(t *testing.T) {
|
|
backend, cleanup := fakeBackend(t, func(http.ResponseWriter, *http.Request) {})
|
|
defer cleanup()
|
|
reg := transcode.NewRegistry(backend, nil)
|
|
if _, ok := reg.Lookup(transcode.MsgAuthTelegram); ok {
|
|
t.Error("auth.telegram should be unregistered without a connector")
|
|
}
|
|
}
|