feat: селектор режима и стенда (v1.2.30)
Новое: - Селектор режима (🎭 Эмуляция / ☁️ Облако) над версией - Селектор стенда (DEV/TEST/PROD) в режиме эмуляции - В эмуляции — всё в полигон (/stand/api/v1/svc) - В эмуляции — токен дезактивирован - По умолчанию: эмуляция + TEST Изменено: - auth.py: get_mode(), get_polygon_stand(), get_client() с префиксом стенда - main.py: action=set_mode, единый get_client() вместо real_client/inst_client - index.html: селекторы, disable токена - service_list.py: обрезка polygon_ префикса - api_test.py: get_real_client → get_client Задокументировано в HISTORY/2026-08-03-session.md.
This commit is contained in:
+62
-44
@@ -5,13 +5,24 @@
|
||||
в main.py и api_test.py с идентичным или почти идентичным кодом.
|
||||
Теперь всё здесь — один источник правды для всех роутов.
|
||||
|
||||
Режимы работы (2026-08-03):
|
||||
- Эмуляция (mode=polygon): всё в полигон, стенд из селектора (dev/test/prod)
|
||||
- Облако (mode=cloud): реальный API, стенд автоопределяется по токену
|
||||
|
||||
Cookie (устанавливаются main.py:action=set_mode):
|
||||
- mode — "polygon" (по умолчанию) или "cloud"
|
||||
- polygon_stand — "test" (по умолчанию), "dev", "prod"
|
||||
|
||||
Функции (все без аргументов — берут данные из Flask request/current_app):
|
||||
get_token() — токен: cookie → env-переменная
|
||||
get_client() — HttpClient с автоопределением стенда
|
||||
get_client_id() — ClientID из JWT (base64url, без проверки подписи)
|
||||
get_stand() — "dev" / "test" по токену
|
||||
get_token_info() — {email, company, client_id} из JWT для UI
|
||||
get_token_masked() — маскированный токен (abc...xyz) для placeholder
|
||||
get_mode() — "polygon" / "cloud"
|
||||
get_polygon_stand() — "dev" / "test" / "prod"
|
||||
get_token() — токен: cookie → env (в эмуляции только env)
|
||||
get_client() — HttpClient с учётом режима и стенда
|
||||
get_real_client() — алиас get_client() (историческая совместимость)
|
||||
get_client_id() — ClientID из JWT (base64url, без проверки подписи)
|
||||
get_stand() — "polygon_test" / "dev" / "test"
|
||||
get_token_info() — {email, company, client_id} из JWT для UI
|
||||
get_token_masked() — маскированный токен (abc...xyz) для placeholder
|
||||
"""
|
||||
|
||||
import base64
|
||||
@@ -21,57 +32,63 @@ from flask import request, current_app
|
||||
from api.http_client import HttpClient, detect_endpoint, stand_name, STANDS
|
||||
|
||||
|
||||
def get_mode():
|
||||
"""Режим: 'polygon' (эмуляция) или 'cloud' (реальное облако).
|
||||
|
||||
Если POLYGON_ENDPOINT не задан в конфиге — всегда облако (селектор не нужен).
|
||||
Иначе — из cookie, по умолчанию эмуляция."""
|
||||
if not current_app.config.get("POLYGON_ENDPOINT", ""):
|
||||
return "cloud"
|
||||
return request.cookies.get("mode", "polygon")
|
||||
|
||||
|
||||
def get_polygon_stand():
|
||||
"""Стенд полигона: 'test' (по умолчанию), 'dev', 'prod'.
|
||||
|
||||
Используется ТОЛЬКО в режиме эмуляции — для построения URL и load_service_ids."""
|
||||
return request.cookies.get("polygon_stand", "test")
|
||||
|
||||
|
||||
def get_token():
|
||||
"""Получить активный токен: сначала из cookie пользователя, потом из env.
|
||||
"""Получить активный токен.
|
||||
|
||||
Приоритет:
|
||||
1. cookie "token" — пользователь ввёл свой токен в форме
|
||||
2. NUBES_API_TOKEN из env — сервисный токен (для автоматических тестов)
|
||||
|
||||
Пользовательский токен приоритетнее — он переопределяет сервисный."""
|
||||
В эмуляции — ТОЛЬКО env-токен (пользовательский ввод дезактивирован).
|
||||
В облаке — cookie → env (как раньше)."""
|
||||
if get_mode() == "polygon":
|
||||
return current_app.config["NUBES_API_TOKEN"]
|
||||
return request.cookies.get("token") or current_app.config["NUBES_API_TOKEN"]
|
||||
|
||||
|
||||
def _make_client(*, use_polygon):
|
||||
"""Фабрика HttpClient — ЕДИНСТВЕННОЕ место где выбирается endpoint.
|
||||
def get_client():
|
||||
"""HttpClient с учётом режима и стенда.
|
||||
|
||||
Args:
|
||||
use_polygon: если True и POLYGON_ENDPOINT задан → polygon.
|
||||
Если False → всегда реальный API (для чтения сервисов/инстансов).
|
||||
|
||||
Returns:
|
||||
HttpClient с правильным endpoint и токеном.
|
||||
"""
|
||||
Эмуляция: polygon_url + "/" + stand → https://polygon.../{stand}/api/v1/svc
|
||||
Облако: реальный API с автоопределением стенда (dev/test по токену)."""
|
||||
token = get_token()
|
||||
mode = get_mode()
|
||||
|
||||
# Режим полигона — только если разрешено и переменная задана
|
||||
if use_polygon:
|
||||
if mode == "polygon":
|
||||
polygon = current_app.config.get("POLYGON_ENDPOINT", "")
|
||||
if polygon:
|
||||
return HttpClient(polygon, token)
|
||||
stand = get_polygon_stand()
|
||||
# POLYGON_ENDPOINT = "https://polygon.../api/v1/svc"
|
||||
# → "https://polygon.../{stand}/api/v1/svc"
|
||||
# rstrip на случай trailing slash в конфиге
|
||||
return HttpClient(f"{polygon.rstrip('/')}/{stand}", token)
|
||||
|
||||
# Реальный API: автоопределение или NUBES_API_ENDPOINT
|
||||
# Облако: NUBES_API_ENDPOINT с автоопределением
|
||||
endpoint = current_app.config["NUBES_API_ENDPOINT"]
|
||||
if endpoint in STANDS:
|
||||
endpoint = detect_endpoint(token) or endpoint
|
||||
return HttpClient(endpoint, token)
|
||||
|
||||
|
||||
def get_client():
|
||||
"""HttpClient для ОПЕРАЦИЙ (create/modify/delete/run/poll).
|
||||
|
||||
Если POLYGON_ENDPOINT задан → polygon.
|
||||
Иначе → автоопределение реального стенда.
|
||||
"""
|
||||
return _make_client(use_polygon=True)
|
||||
|
||||
|
||||
def get_real_client():
|
||||
"""HttpClient для ЧТЕНИЯ (сервисы, список инстансов).
|
||||
"""Алиас get_client() — историческая совместимость.
|
||||
|
||||
ВСЕГДА реальный API, даже при POLYGON_ENDPOINT.
|
||||
"""
|
||||
return _make_client(use_polygon=False)
|
||||
Раньше get_real_client() всегда ходил в реальный API (для сервисов).
|
||||
Теперь в эмуляции сервисы тоже из полигона → обе функции идентичны.
|
||||
Оставлено чтобы не ломать все места вызова."""
|
||||
return get_client()
|
||||
|
||||
|
||||
def get_client_id():
|
||||
@@ -100,12 +117,13 @@ def get_client_id():
|
||||
|
||||
|
||||
def get_stand():
|
||||
"""Определить стенд (dev/test/mock) по активному токену.
|
||||
"""Определить стенд.
|
||||
|
||||
Если POLYGON_ENDPOINT задан → "polygon".
|
||||
Иначе — автоопределение или stand_name."""
|
||||
if current_app.config.get("POLYGON_ENDPOINT", ""):
|
||||
return "polygon"
|
||||
Эмуляция: "polygon_{dev|test|prod}" — для load_service_ids и трекера.
|
||||
Облако: автоопределение или stand_name (dev/test/mock)."""
|
||||
mode = get_mode()
|
||||
if mode == "polygon":
|
||||
return f"polygon_{get_polygon_stand()}"
|
||||
|
||||
token = get_token()
|
||||
endpoint = current_app.config["NUBES_API_ENDPOINT"]
|
||||
|
||||
Reference in New Issue
Block a user