From 58df887f1ce25f861417620d837cb20da3ab99ba Mon Sep 17 00:00:00 2001 From: nns <278048682+nurdotnet@users.noreply.github.com> Date: Thu, 30 Apr 2026 13:56:51 +0500 Subject: [PATCH] =?UTF-8?q?feat(domains):=20=D0=BC=D0=B8=D0=B3=D1=80=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=BD=D0=B0=20food-market.kz=20/=20admin.?= =?UTF-8?q?food-market.kz?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Заменил все хардкоды URL в src/** и deploy/: food-market.zat.kz → food-market.kz (публичный сайт) app.food-market.zat.kz → admin.food-market.kz (админ-API + SPA) - public/SignupForm и Header: дефолт PUBLIC_APP_URL теперь https://admin.food-market.kz (раньше указывал на сам публичный домен, что было багом — фронт стучался не туда после переезда зон). - public/Dockerfile ARG PUBLIC_APP_URL → admin.food-market.kz. - API appsettings.json CORS — оставил только два прода-origin (localhost для dev живёт там же). - Program.cs: добавил opts.SetIssuer(uri) если задан OpenIddict:Issuer в конфиге — иначе iss вычислялся из текущего HTTP-запроса и ломался при nginx-прокси без X-Forwarded-Proto. - docker-compose стейджа: env OpenIddict__Issuer=https://admin.food-market.kz/ + Cors__AllowedOrigins[0,1]. Nginx (на сервере, не в репе): - /etc/nginx/conf.d/food-market.kz.conf, admin.food-market.kz.conf — новые конфиги с certbot-выданными сертификатами на оба домена (LetsEncrypt --webroot, действителен до 2026-07-29). - Старые food-market.zat.kz / app.food-market.zat.kz переведены в 301-редирект на новые домены (HTTP+HTTPS), серты zat.kz пока оставлены чтобы handshake шёл нормально. --- deploy/telegram-bridge/bridge.py | 4 ++-- src/food-market.api/Program.cs | 8 ++++++++ src/food-market.api/appsettings.json | 4 +--- src/food-market.public/Dockerfile | 2 +- src/food-market.public/public/robots.txt | 2 +- src/food-market.public/scripts/og.mjs | 2 +- src/food-market.public/scripts/screenshots.mjs | 2 +- src/food-market.public/src/components/Header.astro | 2 +- src/food-market.public/src/components/SignupForm.tsx | 4 ++-- src/food-market.public/src/pages/changelog.astro | 2 +- src/food-market.web/src/pages/NoOrganizationPage.tsx | 2 +- 11 files changed, 20 insertions(+), 14 deletions(-) diff --git a/deploy/telegram-bridge/bridge.py b/deploy/telegram-bridge/bridge.py index fe3f588..4e44bb7 100644 --- a/deploy/telegram-bridge/bridge.py +++ b/deploy/telegram-bridge/bridge.py @@ -9,7 +9,7 @@ Config (/etc/food-market/telegram.env or env vars): TELEGRAM_BOT_TOKEN — bot token (required) TELEGRAM_CHAT_ID — single whitelisted chat id (required) TELEGRAM_WEBHOOK_URL — public URL Telegram should POST to - (default: https://food-market.zat.kz/tg-webhook) + (default: https://food-market.kz/tg-webhook) TELEGRAM_WEBHOOK_SECRET — random secret; bridge validates the X-Telegram-Bot-Api-Secret-Token header on every incoming request and Telegram sends it back so @@ -143,7 +143,7 @@ def main() -> int: token = env.get("TELEGRAM_BOT_TOKEN", "").strip() chat_id_raw = env.get("TELEGRAM_CHAT_ID", "").strip() secret = env.get("TELEGRAM_WEBHOOK_SECRET", "").strip() - webhook_url = env.get("TELEGRAM_WEBHOOK_URL", "https://food-market.zat.kz/tg-webhook").strip() + webhook_url = env.get("TELEGRAM_WEBHOOK_URL", "https://food-market.kz/tg-webhook").strip() if not token or not chat_id_raw: print("ERROR: TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID required", file=sys.stderr) return 78 diff --git a/src/food-market.api/Program.cs b/src/food-market.api/Program.cs index 58a8843..dbb3d2e 100644 --- a/src/food-market.api/Program.cs +++ b/src/food-market.api/Program.cs @@ -96,6 +96,14 @@ builder.Configuration["OpenIddict:AccessTokenLifetime"] ?? "01:00:00")); opts.SetRefreshTokenLifetime(TimeSpan.Parse( builder.Configuration["OpenIddict:RefreshTokenLifetime"] ?? "30.00:00:00")); + // Явный Issuer = публичный URL админки. Без него OpenIddict + // вычисляет issuer из текущего HTTP-запроса, что ломается за + // nginx-прокси если Host/X-Forwarded-Proto не доходят. Берём + // из конфигурации (OpenIddict:Issuer / docker compose env). + if (builder.Configuration["OpenIddict:Issuer"] is { Length: > 0 } issuer) + { + opts.SetIssuer(new Uri(issuer)); + } }) .AddValidation(opts => { diff --git a/src/food-market.api/appsettings.json b/src/food-market.api/appsettings.json index fcec9bb..73a57fd 100644 --- a/src/food-market.api/appsettings.json +++ b/src/food-market.api/appsettings.json @@ -31,10 +31,8 @@ "AllowedOrigins": [ "http://localhost:5173", "http://localhost:4173", - "https://food-market.zat.kz", - "https://app.food-market.zat.kz", "https://food-market.kz", - "https://app.food-market.kz" + "https://admin.food-market.kz" ] }, "AllowedHosts": "*" diff --git a/src/food-market.public/Dockerfile b/src/food-market.public/Dockerfile index ebb2349..81ab677 100644 --- a/src/food-market.public/Dockerfile +++ b/src/food-market.public/Dockerfile @@ -11,7 +11,7 @@ COPY pnpm-lock.yaml* ./ RUN pnpm install --frozen-lockfile || pnpm install COPY . . ARG PUBLIC_SITE_URL=https://food-market.kz -ARG PUBLIC_APP_URL=https://food-market.zat.kz +ARG PUBLIC_APP_URL=https://food-market.kz ENV PUBLIC_SITE_URL=$PUBLIC_SITE_URL ENV PUBLIC_APP_URL=$PUBLIC_APP_URL RUN pnpm build diff --git a/src/food-market.public/public/robots.txt b/src/food-market.public/public/robots.txt index 1f08c26..850d5df 100644 --- a/src/food-market.public/public/robots.txt +++ b/src/food-market.public/public/robots.txt @@ -1,3 +1,3 @@ User-agent: * Allow: / -Sitemap: https://food-market.zat.kz/sitemap-index.xml +Sitemap: https://food-market.kz/sitemap-index.xml diff --git a/src/food-market.public/scripts/og.mjs b/src/food-market.public/scripts/og.mjs index c457796..c2e72e0 100644 --- a/src/food-market.public/scripts/og.mjs +++ b/src/food-market.public/scripts/og.mjs @@ -83,7 +83,7 @@ const tmpl = ({ title, sub }) => ({ props: { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between' }, children: [ - { type: 'div', props: { style: { color: '#0F172A', fontSize: '20px', fontWeight: 700 }, children: 'food-market.zat.kz' } }, + { type: 'div', props: { style: { color: '#0F172A', fontSize: '20px', fontWeight: 700 }, children: 'food-market.kz' } }, { type: 'div', props: { diff --git a/src/food-market.public/scripts/screenshots.mjs b/src/food-market.public/scripts/screenshots.mjs index 0cc9a49..0644de9 100644 --- a/src/food-market.public/scripts/screenshots.mjs +++ b/src/food-market.public/scripts/screenshots.mjs @@ -5,7 +5,7 @@ import { fileURLToPath } from 'node:url' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const OUT = path.resolve(__dirname, '..', 'public', 'screenshots') -const APP = 'https://app.food-market.zat.kz' +const APP = 'https://admin.food-market.kz' const EMAIL = 'admin@food-market.local' const PASSWORD = 'Admin12345!' diff --git a/src/food-market.public/src/components/Header.astro b/src/food-market.public/src/components/Header.astro index 0a4e864..9db63a2 100644 --- a/src/food-market.public/src/components/Header.astro +++ b/src/food-market.public/src/components/Header.astro @@ -1,6 +1,6 @@ --- import Logo from './Logo.astro' -const APP_URL = import.meta.env.PUBLIC_APP_URL || 'https://food-market.zat.kz' +const APP_URL = import.meta.env.PUBLIC_APP_URL || 'https://food-market.kz' ---
diff --git a/src/food-market.public/src/components/SignupForm.tsx b/src/food-market.public/src/components/SignupForm.tsx index 6eab639..c7c6104 100644 --- a/src/food-market.public/src/components/SignupForm.tsx +++ b/src/food-market.public/src/components/SignupForm.tsx @@ -2,8 +2,8 @@ import { useState } from 'react' import { validateEmail, validatePassword, validatePhone } from '@/lib/validation' // Админский / API endpoint — переключается через PUBLIC_APP_URL на этапе -// билда. Дефолт пока — текущий рабочий food-market.zat.kz. -const APP_URL = (import.meta.env.PUBLIC_APP_URL as string | undefined) ?? 'https://food-market.zat.kz' +// билда. Дефолт — admin.food-market.kz (там и API и админ-SPA). +const APP_URL = (import.meta.env.PUBLIC_APP_URL as string | undefined) ?? 'https://admin.food-market.kz' const API_URL = APP_URL interface Props { diff --git a/src/food-market.public/src/pages/changelog.astro b/src/food-market.public/src/pages/changelog.astro index ce36438..27f2927 100644 --- a/src/food-market.public/src/pages/changelog.astro +++ b/src/food-market.public/src/pages/changelog.astro @@ -1,7 +1,7 @@ --- import BaseLayout from '@/layouts/BaseLayout.astro' const releases = [ - { date: '2026-04', title: 'Phase 6 — Публичный сайт', items: ['Маркетинговый сайт food-market.zat.kz','Регистрация без админа платформы','Тарифы Старт / Бизнес-конструктор / Сеть'] }, + { date: '2026-04', title: 'Phase 6 — Публичный сайт', items: ['Маркетинговый сайт food-market.kz','Регистрация без админа платформы','Тарифы Старт / Бизнес-конструктор / Сеть'] }, { date: '2026-04', title: 'Phase 4 — SuperAdmin консоль', items: ['Управление организациями','Журнал действий','Read-only «открыть как…»','Edit-mode с reason + audit-trail','Настраиваемый retention period'] }, { date: '2026-04', title: 'Phase 3 — Цены и роли', items: ['Расширенная модель цен','Сотрудники и роли','Системные роли (Администратор, Кассир)'] }, { date: '2026-04', title: 'Phase 2 — Закупки и приёмки', items: ['Документ приёмки со сканером','Скользящее среднее себестоимости','Inline quick-add позиций'] }, diff --git a/src/food-market.web/src/pages/NoOrganizationPage.tsx b/src/food-market.web/src/pages/NoOrganizationPage.tsx index 822475a..92348cd 100644 --- a/src/food-market.web/src/pages/NoOrganizationPage.tsx +++ b/src/food-market.web/src/pages/NoOrganizationPage.tsx @@ -2,7 +2,7 @@ import { Logo } from '@/components/Logo' import { logout } from '@/lib/auth' import { useMe } from '@/lib/useMe' -const PUBLIC_SITE = (import.meta.env.VITE_PUBLIC_SITE_URL as string | undefined) ?? 'https://food-market.zat.kz' +const PUBLIC_SITE = (import.meta.env.VITE_PUBLIC_SITE_URL as string | undefined) ?? 'https://food-market.kz' /** Fallback-экран для AppUser без активного Employee в живой Organization. * Возможные причины: его org удалена SuperAdmin'ом, его Employee