feat(proj): init
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
# 2026-09-20 — Вход через WebView + Telegram Login Widget
|
||||
|
||||
## Запрос
|
||||
Реализовать нативный вход: открыть кабинет в WebView и забрать JWT через
|
||||
JS-канал. Бэкенд не менять.
|
||||
|
||||
## Почему не «просто открыть страницу»
|
||||
|
||||
Telegram Login Widget в обычном браузере работает через iframe + `data-onauth`.
|
||||
В Android/iOS WebView этот путь ломается:
|
||||
|
||||
- popup (`window.open` на `oauth.telegram.org`) не возвращает `opener`;
|
||||
- iframe режется third-party cookies и User-Agent с маркером `; wv`;
|
||||
- callback `onTelegramAuth` просто не вызывается.
|
||||
|
||||
Поэтому в WebView виджет переключается на **redirect-режим** (`data-auth-url`),
|
||||
а Flutter забирает уже готовый JWT, который кабинет и так кладёт в
|
||||
`localStorage.ppm_session_jwt`. API (`POST /api/auth/telegram`) не трогали.
|
||||
|
||||
## Поток
|
||||
|
||||
1. Экран входа на iOS/Android показывает «Войти через Telegram».
|
||||
2. Открывается fullscreen WebView на `{cabinet}/login`.
|
||||
3. Кабинет видит канал `window.PpmAuth` → ставит виджету `data-auth-url=/login`.
|
||||
4. Пользователь логинится в Telegram; редирект приходит на `/login?id&hash&…`.
|
||||
5. `telegramPayloadFromQuery` собирает payload, кабинет зовёт тот же
|
||||
`loginWithTelegram` / `POST /api/auth/telegram`.
|
||||
6. `setSession` пишет JWT в `localStorage` и зовёт `PpmAuth.postMessage`.
|
||||
7. Flutter парсит сообщение, закрывает WebView, проверяет токен через
|
||||
`GET /api/me`, кладёт сессию в `SharedPreferences`.
|
||||
|
||||
Запасные пути, если кабинет ещё не задеплоен с мостом:
|
||||
|
||||
- JS в WebView хукает `localStorage.setItem('ppm_session_jwt')` и поллит ключ;
|
||||
- на Windows/web WebView нет — форма «вставить токен»;
|
||||
- «Демо-режим» по-прежнему без сети.
|
||||
|
||||
## Что изменилось
|
||||
|
||||
### Web (не API)
|
||||
- `web/src/auth/telegramRedirect.ts` — разбор query и `postTokenToNativeApp`.
|
||||
- `TelegramLoginButton` — `data-auth-url` только если есть `window.PpmAuth`.
|
||||
- `LoginPage` — автологин, если в URL уже лежит telegram-payload.
|
||||
- `setSession` — после записи токена шлёт его в канал.
|
||||
|
||||
### Mobile
|
||||
- `TelegramLoginScreen` (`webview_flutter`): канал `PpmAuth`, Chrome UA без
|
||||
`; wv`, third-party cookies на Android, `tg://` уходит во внешнее приложение,
|
||||
кнопка «назад» после oauth.telegram.org.
|
||||
- `resolveCabinetLoginUri` всегда открывает `/login`.
|
||||
- `INTERNET` в main `AndroidManifest` (раньше был только в debug).
|
||||
- iOS: `LSApplicationQueriesSchemes` для `tg` / `telegram`.
|
||||
- `PPM_WEB_URL` по умолчанию = `PPM_API_BASE_URL` (один origin за nginx).
|
||||
|
||||
## Тесты
|
||||
- `resolveApiBaseUrl` / `resolveCabinetLoginUri` / парсер канала.
|
||||
- виджет: инжектированный launcher отдаёт JWT → `GET /api/me` → signed in.
|
||||
- 32 теста приложения, 102 в Widgetbook, `flutter analyze` чистый.
|
||||
|
||||
## Запуск против живого кабинета
|
||||
|
||||
```powershell
|
||||
cd mobile
|
||||
.\run.ps1 -Device windows # на Windows будет форма токена
|
||||
# на телефоне:
|
||||
.\run.ps1 -ApiBaseUrl https://<домен-кабинета>
|
||||
```
|
||||
|
||||
Нужен публичный HTTPS и BotFather `/setdomain` на этот домен — как для веба.
|
||||
Reference in New Issue
Block a user