fix(auth): route admin/customer Telegram QR login to the shared auth origin
AUTH_API_URL was wired to ApiConfigService.getBaseUrl() (the per-tenant
content origin, e.g. api.gorbushka.market), so admin/customer QR-login
session creation POSTed to a host with no /users/sessions route.
Auth is a single shared cross-tenant service (like payment's
qr.vitanova.network), not tenant-scoped - confirmed against the
pre-tenant-refactor state (commit a59ffbca) where every brand's
environment file carried the identical fixed authApiUrl, and against a
live POST to users.vitanova.network:456/users/sessions.
Restores authApiUrl as a fixed constant in both environment files and
wires AUTH_API_URL/MARKETPLACES_AUTH_CONFIG.apiUrl to it, mirroring the
existing qrApiUrl/provideMarketplacesPayment pattern. Also provides
MARKETPLACES_AUTH_CONFIG.marketplaceDomain via TenantResolverService's
existing getBaseDomain() so the X-Marketplace-Domain header stays
normalized instead of falling back to raw, unnormalized
location.hostname (it was never provided before, so that fallback was
always in effect).
No package edits, no path/method/body change, no QR/Telegram flow
change. tenantApiTemplate/tenantApiBaseUrls/ApiConfigService/
TenantResolverService untouched - still drive content-API resolution
only.
Known remaining blocker (server-side, tracked in vitanovaPackages
BACKEND-TODO.md): users.vitanova.network:456 CORS-rejects the
admin.gorbushka.market origin outright (403 on preflight, no allow
headers) while novo.market gets a full grant - this fix alone will not
make browser login work on gorbushka domains until that origin
allowlist is updated.
This commit is contained in:
@@ -8,12 +8,11 @@ import { apiErrorInterceptor } from './core/interceptors/api-error.interceptor';
|
|||||||
import { apiBaseUrlInterceptor } from './interceptors/api-base-url.interceptor';
|
import { apiBaseUrlInterceptor } from './interceptors/api-base-url.interceptor';
|
||||||
import { apiHeadersInterceptor } from './interceptors/api-headers.interceptor';
|
import { apiHeadersInterceptor } from './interceptors/api-headers.interceptor';
|
||||||
import { mockDataInterceptor } from './interceptors/mock-data.interceptor';
|
import { mockDataInterceptor } from './interceptors/mock-data.interceptor';
|
||||||
import { adminAuthHeadersInterceptor, Ed25519VerificationService, NoopEd25519VerificationService, AUTH_API_URL, TELEGRAM_BOT_USERNAME } from '@marketplaces/auth';
|
import { adminAuthHeadersInterceptor, Ed25519VerificationService, NoopEd25519VerificationService, AUTH_API_URL, TELEGRAM_BOT_USERNAME, MARKETPLACES_AUTH_CONFIG, MarketplacesAuthConfig } from '@marketplaces/auth';
|
||||||
import { provideMarketplacesPayment } from '@marketplaces/payment';
|
import { provideMarketplacesPayment } from '@marketplaces/payment';
|
||||||
import { provideServiceWorker } from '@angular/service-worker';
|
import { provideServiceWorker } from '@angular/service-worker';
|
||||||
import { MediaRepository } from './core/media/media-repository';
|
import { MediaRepository } from './core/media/media-repository';
|
||||||
import { MockMediaRepository } from './core/media/mock-media-repository.service';
|
import { MockMediaRepository } from './core/media/mock-media-repository.service';
|
||||||
import { ApiConfigService } from './core/config/api-config.service';
|
|
||||||
import { TenantResolverService } from './core/config/tenant-resolver.service';
|
import { TenantResolverService } from './core/config/tenant-resolver.service';
|
||||||
import { environment } from '../environments/environment';
|
import { environment } from '../environments/environment';
|
||||||
import { MOCK_GATEWAY_PROVIDERS } from './mock-gateway.providers';
|
import { MOCK_GATEWAY_PROVIDERS } from './mock-gateway.providers';
|
||||||
@@ -31,12 +30,22 @@ export const appConfig: ApplicationConfig = {
|
|||||||
// other interceptor has run, and normalizes whatever actually came back.
|
// other interceptor has run, and normalizes whatever actually came back.
|
||||||
withInterceptors([mockDataInterceptor, apiBaseUrlInterceptor, apiHeadersInterceptor, adminAuthHeadersInterceptor, cacheInterceptor, apiErrorInterceptor])
|
withInterceptors([mockDataInterceptor, apiBaseUrlInterceptor, apiHeadersInterceptor, adminAuthHeadersInterceptor, cacheInterceptor, apiErrorInterceptor])
|
||||||
),
|
),
|
||||||
{
|
// authApiUrl ('https://users.vitanova.network:456') is a single shared
|
||||||
provide: AUTH_API_URL,
|
// cross-tenant service, same shape as qrApiUrl below - NOT the per-tenant
|
||||||
useFactory: (apiConfig: ApiConfigService) => apiConfig.getBaseUrl(),
|
// apiConfig.getBaseUrl(). That was the bug: AUTH_API_URL used to read the
|
||||||
deps: [ApiConfigService]
|
// tenant content origin (api.{baseDomain}), which has no /users/sessions
|
||||||
},
|
// endpoint. Confirmed against the pre-split reference build (novo.market)
|
||||||
|
// and a live POST against users.vitanova.network:456/users/sessions.
|
||||||
|
{ provide: AUTH_API_URL, useValue: environment.authApiUrl },
|
||||||
{ provide: TELEGRAM_BOT_USERNAME, useValue: environment.telegramBot },
|
{ provide: TELEGRAM_BOT_USERNAME, useValue: environment.telegramBot },
|
||||||
|
{
|
||||||
|
provide: MARKETPLACES_AUTH_CONFIG,
|
||||||
|
useFactory: (tenantResolver: TenantResolverService): MarketplacesAuthConfig => ({
|
||||||
|
apiUrl: environment.authApiUrl,
|
||||||
|
marketplaceDomain: () => tenantResolver.getBaseDomain(),
|
||||||
|
}),
|
||||||
|
deps: [TenantResolverService]
|
||||||
|
},
|
||||||
// useFactory, not useClass: @marketplaces/auth ships plain tsc output, not
|
// useFactory, not useClass: @marketplaces/auth ships plain tsc output, not
|
||||||
// Angular Package Format, so it carries no baked-in Ivy DI metadata for
|
// Angular Package Format, so it carries no baked-in Ivy DI metadata for
|
||||||
// this class. useClass forces Angular to JIT-compile it at runtime, which
|
// this class. useClass forces Angular to JIT-compile it at runtime, which
|
||||||
@@ -49,8 +58,8 @@ export const appConfig: ApplicationConfig = {
|
|||||||
// apiUrl: environment.qrApiUrl ('https://qr.vitanova.network/api') is the
|
// apiUrl: environment.qrApiUrl ('https://qr.vitanova.network/api') is the
|
||||||
// same "central payment service" the legacy /qr and
|
// same "central payment service" the legacy /qr and
|
||||||
// /card/{partnerId}/{orderId} endpoints already used (api.service.ts) -
|
// /card/{partnerId}/{orderId} endpoints already used (api.service.ts) -
|
||||||
// one service shared across every tenant, unlike the per-tenant
|
// one service shared across every tenant - same shape as AUTH_API_URL
|
||||||
// AUTH_API_URL above. Stripped the trailing /api here: the package's own
|
// above. Stripped the trailing /api here: the package's own
|
||||||
// default paymentsPath is '/api/v1/payments', so passing qrApiUrl
|
// default paymentsPath is '/api/v1/payments', so passing qrApiUrl
|
||||||
// unchanged would double it to .../api/api/v1/payments. Confirmed by
|
// unchanged would double it to .../api/api/v1/payments. Confirmed by
|
||||||
// reading the package's baseUrl() directly (apiUrl + paymentsPath,
|
// reading the package's baseUrl() directly (apiUrl + paymentsPath,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export const environment = {
|
|||||||
theme: 'dexar',
|
theme: 'dexar',
|
||||||
apiUrl: '/api',
|
apiUrl: '/api',
|
||||||
qrApiUrl: 'https://qr.vitanova.network/api',
|
qrApiUrl: 'https://qr.vitanova.network/api',
|
||||||
|
authApiUrl: 'https://users.vitanova.network:456',
|
||||||
logo: '/icons/icon-192x192.png',
|
logo: '/icons/icon-192x192.png',
|
||||||
contactEmail: 'info@dexarmarket.ru',
|
contactEmail: 'info@dexarmarket.ru',
|
||||||
supportEmail: 'info@dexarmarket.ru',
|
supportEmail: 'info@dexarmarket.ru',
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export const environment = {
|
|||||||
theme: 'dexar',
|
theme: 'dexar',
|
||||||
apiUrl: '/api',
|
apiUrl: '/api',
|
||||||
qrApiUrl: 'https://qr.vitanova.network/api',
|
qrApiUrl: 'https://qr.vitanova.network/api',
|
||||||
|
authApiUrl: 'https://users.vitanova.network:456',
|
||||||
logo: '/icons/icon-192x192.png',
|
logo: '/icons/icon-192x192.png',
|
||||||
contactEmail: 'info@dexarmarket.ru',
|
contactEmail: 'info@dexarmarket.ru',
|
||||||
supportEmail: 'info@dexarmarket.ru',
|
supportEmail: 'info@dexarmarket.ru',
|
||||||
|
|||||||
Reference in New Issue
Block a user