From 7233e8b70a34e3dd40028e163e3ebd43740ad32d Mon Sep 17 00:00:00 2001 From: lendry Date: Mon, 29 Jun 2026 21:00:23 +0300 Subject: [PATCH] fix and update --- apps/frontend/lib/api.ts | 6 +- install.sh | 120 ++++++++++++++++++++++++++++++++++----- 2 files changed, 109 insertions(+), 17 deletions(-) diff --git a/apps/frontend/lib/api.ts b/apps/frontend/lib/api.ts index 1aba90f..d1af5c8 100644 --- a/apps/frontend/lib/api.ts +++ b/apps/frontend/lib/api.ts @@ -625,7 +625,7 @@ export function buildSystemSettingPayload(setting: Pick { return new Promise((resolve) => setTimeout(resolve, ms)); @@ -638,14 +638,14 @@ async function fetchWithGatewayRetry(url: string, init: RequestInit): Promise.*)$ { @@ -2420,6 +2425,26 @@ validate_docker_api_nginx_config() { ok "Конфиг API-домена: динамический DNS (resolver + idp_up_api)" } +validate_docker_frontend_nginx_config() { + [[ "$NGINX_MODE" == "docker" ]] || return 0 + local conf="${LOCAL_CONF_DIR}/${NGINX_PREFIX}-frontend.conf" + [[ -f "$conf" ]] || fail "Не найден ${conf} — конфиг SSO-домена не записан" + + if ! grep -q 'location.*idp-api' "$conf" 2>/dev/null; then + fail "Конфиг ${conf} без location /idp-api — браузер SPA получит 502. Выполните ./install.sh --fix-all" + fi + if ! grep -q 'resolver 127.0.0.11' "$conf" 2>/dev/null; then + fail "Конфиг ${conf} без resolver 127.0.0.11 — /idp-api на SSO не переживёт пересборку api-gateway" + fi + if ! grep -q 'idp_up_api' "$conf" 2>/dev/null; then + fail "Конфиг ${conf} без idp_up_api — /idp-api проксируется некорректно. Выполните ./install.sh --fix-all" + fi + if ! grep -q 'location \^~ /idp-api/ws' "$conf" 2>/dev/null; then + warn "Конфиг ${conf}: location ^~ /idp-api/ws отсутствует — WebSocket может идти на api-gateway вместо media-ws" + fi + ok "Конфиг SSO-домена: /idp-api с динамическим DNS (resolver + idp_up_api)" +} + verify_nginx_reaches_api_gateway() { docker_nginx_container_running || return 0 build_compose_stack_cmd @@ -2436,6 +2461,59 @@ verify_nginx_reaches_api_gateway() { return 1 } +verify_nginx_reaches_media_ws() { + docker_nginx_container_running || return 0 + build_compose_stack_cmd + local body + body="$(docker_cmd "${COMPOSE_STACK_CMD[@]}" exec -T nginx \ + wget -qO- --timeout=5 http://lendry-id-media-ws:8085/health 2>/dev/null || true)" + if [[ "$body" == *ok* ]] || [[ "$body" == *healthy* ]]; then + ok "Docker Nginx → lendry-id-media-ws:8085/health OK" + return 0 + fi + warn "Docker Nginx не достучался до lendry-id-media-ws:8085" + warn "Проверьте: docker compose ps media-ws && docker compose logs --tail=40 media-ws" + return 1 +} + +# Проверка того же пути, что использует браузер после логина: https://sso.../idp-api/* +check_sso_idp_api_proxy() { + local frontend_domain code body + frontend_domain="$(env_get DOMAIN_FRONTEND "")" + [[ -n "$frontend_domain" ]] || return 0 + + if docker_nginx_container_running; then + body="$(docker_cmd exec lendry-id-frontend \ + wget -qO- --timeout=5 http://lendry-id-api-gateway:3000/health 2>/dev/null || true)" + if [[ "$body" == *'"status":"ok"'* ]] || [[ "$body" == *'"status": "ok"'* ]]; then + echo -e " ${GREEN}✔${NC} frontend → api-gateway:3000/health OK (fallback через Next.js rewrites)" + else + echo -e " ${RED}✘${NC} frontend → api-gateway:3000 недоступен (Next.js rewrites тоже дадут 502)" + echo " Проверьте: docker compose exec frontend wget -qO- http://lendry-id-api-gateway:3000/health" + return 1 + fi + fi + + if [[ "$(env_get USE_NGINX_SSL false)" != "true" ]]; then + code="$(curl -fsS --max-time 5 -o /dev/null -w '%{http_code}' "http://${frontend_domain}/idp-api/health" 2>/dev/null || echo 000)" + else + code="$(curl -sk --max-time 5 -o /dev/null -w '%{http_code}' "https://${frontend_domain}/idp-api/health" 2>/dev/null || echo 000)" + fi + + if [[ "$code" == "200" ]]; then + echo -e " ${GREEN}✔${NC} SSO /idp-api/health → 200 (путь браузера после логина)" + return 0 + elif [[ "$code" == "502" ]]; then + echo -e " ${RED}✘${NC} SSO /idp-api/health → 502 — Nginx не проксирует /idp-api на api-gateway" + echo " Проверьте: grep -E 'idp-api|idp_up_api|resolver' nginx/conf.d/${NGINX_PREFIX}-frontend.conf" + echo " docker compose --profile proxy exec nginx wget -qO- http://lendry-id-api-gateway:3000/health" + return 1 + else + echo -e " ${YELLOW}!${NC} SSO /idp-api/health → HTTP ${code} (ожидалось 200)" + return 1 + fi +} + write_all_nginx_configs() { ensure_nginx_mode_for_config_write local ssl_type="${1:-$(env_get SSL_TYPE none)}" @@ -2473,6 +2551,7 @@ write_all_nginx_configs() { [[ -n "${DOMAIN_MINIO_CONSOLE:-}" ]] && write_nginx_site_minio "$DOMAIN_MINIO_CONSOLE" minio-console minio-console "$ssl_type" validate_docker_api_nginx_config + validate_docker_frontend_nginx_config if [[ "$NGINX_MODE" == "host" ]]; then if run_root nginx -t; then @@ -2916,6 +2995,16 @@ diagnose_common_issues() { issues=$((issues + 1)) elif docker_cmd ps --format '{{.Names}} {{.Status}}' 2>/dev/null | grep -q 'lendry-id-api-gateway.*Up'; then echo -e " ${GREEN}✔${NC} api-gateway: контейнер запущен" + local restart_count started_at + restart_count="$(docker_cmd inspect lendry-id-api-gateway --format '{{.RestartCount}}' 2>/dev/null || echo '?')" + started_at="$(docker_cmd inspect lendry-id-api-gateway --format '{{.State.StartedAt}}' 2>/dev/null || echo '?')" + if [[ "$restart_count" =~ ^[0-9]+$ ]] && [[ "$restart_count" -gt 2 ]]; then + echo -e " ${RED}✘${NC} api-gateway RestartCount=${restart_count} (Started=${started_at}) — частые перезапуски дают 502 в браузере" + echo " Проверьте: docker compose logs --tail=80 api-gateway sso-core" + issues=$((issues + 1)) + else + echo -e " ${GREEN}✔${NC} api-gateway RestartCount=${restart_count} (Started=${started_at})" + fi local grpc_code grpc_code="$(curl -fsS --max-time 3 -o /dev/null -w '%{http_code}' http://127.0.0.1:3000/health/ready 2>/dev/null || echo 000)" if [[ "$grpc_code" == "200" ]]; then @@ -2930,6 +3019,7 @@ diagnose_common_issues() { if [[ "$(env_get USE_NGINX_SSL false)" == "true" ]] \ && [[ -n "$(env_get DOMAIN_API "")" && -n "$(env_get DOMAIN_FRONTEND "")" ]]; then check_https_api_with_origin || issues=$((issues + 1)) + check_sso_idp_api_proxy || issues=$((issues + 1)) fi local api_domain frontend_domain public_api @@ -2937,15 +3027,15 @@ diagnose_common_issues() { frontend_domain="$(env_get DOMAIN_FRONTEND "")" public_api="$(env_get PUBLIC_API_URL "")" if [[ -n "$api_domain" && -n "$frontend_domain" && "$api_domain" != "$frontend_domain" ]]; then - if [[ "$public_api" == *"/idp-api"* ]]; then - echo -e " ${RED}✘${NC} Split-domain: PUBLIC_API_URL=${public_api} — должно быть https://${api_domain} (не /idp-api на SSO)" - echo " Решение: ./install.sh --fix-all" - issues=$((issues + 1)) - elif [[ "$public_api" == *"${frontend_domain}"* && "$public_api" != *"${api_domain}"* ]]; then - echo -e " ${RED}✘${NC} PUBLIC_API_URL указывает на домен SSO (${frontend_domain}), а не API (${api_domain})" - issues=$((issues + 1)) + if [[ "$public_api" == *"${frontend_domain}"*"/idp-api"* ]]; then + echo -e " ${GREEN}✔${NC} Split-domain + same-origin SPA: PUBLIC_API_URL=${public_api}, браузер → /idp-api на SSO" + elif [[ "$public_api" == *"${api_domain}"* ]]; then + echo -e " ${GREEN}✔${NC} Split-domain: PUBLIC_API_URL=${public_api} (OAuth issuer), SPA → /idp-api на SSO" + elif [[ "$public_api" == *"/idp-api"* ]]; then + echo -e " ${YELLOW}!${NC} PUBLIC_API_URL=${public_api} — для OAuth issuer лучше https://${api_domain}" else - echo -e " ${GREEN}✔${NC} Split-domain: PUBLIC_API_URL=${public_api}" + echo -e " ${YELLOW}!${NC} Split-domain: PUBLIC_API_URL=${public_api} — проверьте настройки" + issues=$((issues + 1)) fi fi @@ -3244,8 +3334,10 @@ action_fix_all_errors() { apply_intranet_selfsigned_runtime recreate_docker_nginx verify_nginx_reaches_api_gateway || compose_build_and_up api-gateway + verify_nginx_reaches_media_ws || compose_build_and_up media-ws recreate_docker_nginx verify_nginx_reaches_api_gateway || fail "Nginx не проксирует на api-gateway — см. docker compose logs nginx api-gateway" + check_sso_idp_api_proxy || fail "SSO /idp-api/health недоступен — см. nginx/conf.d/${NGINX_PREFIX}-frontend.conf" if ! docker_nginx_container_running; then fail "Контейнер lendry-id-nginx не запущен. Проверьте: docker compose --profile proxy logs nginx" fi