Добавить проверку токена прокси, динамические лимиты трафика и Telegram magic-link вход
Прокси теперь может валидировать клиентские JWT и отчитываться о расходе трафика через новые internal-эндпоинты (защищены X-Internal-Secret), лимит на юзера настраивается динамически через admin PATCH без передеплоя прокси. Заодно реализован задокументированный, но не подключённый флоу входа через Telegram-бота (magic-link) для десктоп/мобильного приложения, и seed-эндпоинты теперь возвращают access_token в JSON (не только в cookie) — без этого Tauri-приложение не могло ими пользоваться. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+20
-1
@@ -29,6 +29,7 @@ use crate::modules::{
|
||||
auth::{controller as auth_ctrl, service::AuthService},
|
||||
billing::{controller as bill_ctrl, service::BillingService},
|
||||
nodes::{controller as node_ctrl, service::NodeService},
|
||||
proxy_internal,
|
||||
referrals::{controller as ref_ctrl, service::ReferralService},
|
||||
users::{controller as user_ctrl, service::UserService},
|
||||
};
|
||||
@@ -67,6 +68,9 @@ pub struct ApiState {
|
||||
/// (CSRF-проверка в `auth::guard`). Отдельно от `CORS_ALLOWED_ORIGINS`, т.к. туда
|
||||
/// же попадают Bearer-клиенты (Tauri), для которых CSRF неактуален.
|
||||
pub csrf_allowed_origins: Vec<String>,
|
||||
/// Общий секрет для `netrunner-proxy` (`X-Internal-Secret`) — не пользовательская
|
||||
/// авторизация, см. `modules::proxy_internal::internal_secret_guard`.
|
||||
pub proxy_internal_secret: String,
|
||||
}
|
||||
|
||||
impl Clone for ApiState {
|
||||
@@ -85,6 +89,7 @@ impl Clone for ApiState {
|
||||
cookie_domain: self.cookie_domain.clone(),
|
||||
cookie_secure: self.cookie_secure,
|
||||
csrf_allowed_origins: self.csrf_allowed_origins.clone(),
|
||||
proxy_internal_secret: self.proxy_internal_secret.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,7 +137,20 @@ pub fn create_router(state: ApiState, frontend_dir: &str) -> Router {
|
||||
.route("/config", get(get_public_config))
|
||||
.layer(GovernorLayer::new(gov_conf));
|
||||
|
||||
let admin_routes_v1 = Router::new().nest("/nodes", node_ctrl::admin_router(state.clone()));
|
||||
let admin_routes_v1 = Router::new()
|
||||
.nest("/nodes", node_ctrl::admin_router(state.clone()))
|
||||
.nest("/users", user_ctrl::admin_router(state.clone()));
|
||||
|
||||
// Внутренний контракт для прокси-нод — отдельный секрет, не auth_guard
|
||||
// (прокси не пользовательская сессия) и не участвует в CORS ниже (никогда
|
||||
// не вызывается из браузера).
|
||||
let internal_routes = Router::new().nest(
|
||||
"/internal",
|
||||
proxy_internal::router().layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
proxy_internal::internal_secret_guard,
|
||||
)),
|
||||
);
|
||||
|
||||
// Строгий CORS. Список разрешённых origin берём из env (через запятую),
|
||||
// чтобы помимо веб-фронта пускать и десктоп/мобайл-приложение (Tauri webview).
|
||||
@@ -156,6 +174,7 @@ pub fn create_router(state: ApiState, frontend_dir: &str) -> Router {
|
||||
Router::new()
|
||||
.nest("/api/v1", api_routes_v1)
|
||||
.nest("/api/v1/admin", admin_routes_v1)
|
||||
.nest("/api/v1", internal_routes)
|
||||
// Liveness/readiness пробы для Docker/оркестратора и балансировщика.
|
||||
.route("/health", get(health_live))
|
||||
.route("/health/ready", get(health_ready))
|
||||
|
||||
Reference in New Issue
Block a user