fix and update
This commit is contained in:
@@ -77,7 +77,7 @@ export function buildFedcmProviderConfig(endpoints: FedcmEndpoints) {
|
||||
login_url: endpoints.loginUrl,
|
||||
branding: {
|
||||
background_color: '#ffffff',
|
||||
color: '#3390ec',
|
||||
color: '#1f2430',
|
||||
icons: [{ url: `${endpoints.frontendUrl}/favicon.ico`, size: 32 }]
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { CoreGrpcService } from '../core-grpc.service';
|
||||
import { normalizePublicBaseUrl, isInternalHostname } from './public-url';
|
||||
import { normalizePublicBaseUrl, pickBestPublicBase, isInternalHostname } from './public-url';
|
||||
|
||||
function normalizeBaseUrl(url: string) {
|
||||
return normalizePublicBaseUrl(url);
|
||||
@@ -23,68 +23,49 @@ function sanitizeStoredPublicUrl(url: string) {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export async function resolveOAuthIssuer(core: CoreGrpcService, fallback = 'http://localhost:3000'): Promise<string> {
|
||||
const envIssuer = process.env.PUBLIC_API_URL?.trim();
|
||||
try {
|
||||
const response = (await firstValueFrom(core.settings.GetSetting({ key: 'PUBLIC_API_URL' }))) as { value?: string };
|
||||
const fromDb = sanitizeStoredPublicUrl(response.value ?? '');
|
||||
if (fromDb) {
|
||||
return fromDb;
|
||||
}
|
||||
} catch {
|
||||
// fallback ниже
|
||||
}
|
||||
|
||||
if (envIssuer) {
|
||||
return normalizeBaseUrl(envIssuer);
|
||||
}
|
||||
|
||||
async function resolveProjectDomainUrl(core: CoreGrpcService, withIdpApiPath = false): Promise<string | undefined> {
|
||||
try {
|
||||
const response = (await firstValueFrom(core.settings.GetSetting({ key: 'PROJECT_DOMAIN' }))) as { value?: string };
|
||||
const domain = response.value?.trim();
|
||||
if (domain) {
|
||||
if (domain.startsWith('http://') || domain.startsWith('https://')) {
|
||||
return appendIdpApiPath(domain);
|
||||
}
|
||||
return appendIdpApiPath(`https://${domain.replace(/^\/+/, '')}`);
|
||||
if (!domain) {
|
||||
return undefined;
|
||||
}
|
||||
if (domain.startsWith('http://') || domain.startsWith('https://')) {
|
||||
return withIdpApiPath ? appendIdpApiPath(domain) : normalizeBaseUrl(domain);
|
||||
}
|
||||
const base = `https://${domain.replace(/^\/+/, '')}`;
|
||||
return withIdpApiPath ? appendIdpApiPath(base) : base;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export async function resolveOAuthIssuer(core: CoreGrpcService, fallback = 'http://localhost:3000'): Promise<string> {
|
||||
const envIssuer = sanitizeStoredPublicUrl(process.env.PUBLIC_API_URL?.trim() ?? '');
|
||||
let fromDb: string | undefined;
|
||||
try {
|
||||
const response = (await firstValueFrom(core.settings.GetSetting({ key: 'PUBLIC_API_URL' }))) as { value?: string };
|
||||
fromDb = sanitizeStoredPublicUrl(response.value ?? '');
|
||||
} catch {
|
||||
// fallback ниже
|
||||
}
|
||||
|
||||
return normalizeBaseUrl(fallback);
|
||||
const fromDomain = await resolveProjectDomainUrl(core, true);
|
||||
return pickBestPublicBase([fromDb, envIssuer, fromDomain], fallback);
|
||||
}
|
||||
|
||||
export async function resolveFrontendUrl(core: CoreGrpcService, fallback = 'http://localhost:3002'): Promise<string> {
|
||||
const envFrontend = process.env.PUBLIC_FRONTEND_URL?.trim();
|
||||
if (envFrontend) {
|
||||
return normalizeBaseUrl(envFrontend);
|
||||
}
|
||||
|
||||
const envFrontend = sanitizeStoredPublicUrl(process.env.PUBLIC_FRONTEND_URL?.trim() ?? '');
|
||||
let fromDb: string | undefined;
|
||||
try {
|
||||
const response = (await firstValueFrom(core.settings.GetSetting({ key: 'PUBLIC_FRONTEND_URL' }))) as { value?: string };
|
||||
const fromDb = sanitizeStoredPublicUrl(response.value ?? '');
|
||||
if (fromDb) {
|
||||
return fromDb;
|
||||
}
|
||||
fromDb = sanitizeStoredPublicUrl(response.value ?? '');
|
||||
} catch {
|
||||
// fallback ниже
|
||||
}
|
||||
|
||||
try {
|
||||
const response = (await firstValueFrom(core.settings.GetSetting({ key: 'PROJECT_DOMAIN' }))) as { value?: string };
|
||||
const domain = response.value?.trim();
|
||||
if (domain) {
|
||||
if (domain.startsWith('http://') || domain.startsWith('https://')) {
|
||||
return normalizeBaseUrl(domain);
|
||||
}
|
||||
return `https://${domain.replace(/^\/+/, '')}`;
|
||||
}
|
||||
} catch {
|
||||
// fallback ниже
|
||||
}
|
||||
|
||||
return normalizeBaseUrl(fallback);
|
||||
const fromDomain = await resolveProjectDomainUrl(core, false);
|
||||
return pickBestPublicBase([fromDb, envFrontend, fromDomain], fallback);
|
||||
}
|
||||
|
||||
export function buildOpenIdConfiguration(issuer: string) {
|
||||
|
||||
@@ -103,14 +103,47 @@ export function resolvePublicFrontendBaseFromRequest(req?: Request): string | nu
|
||||
* из настроек (PUBLIC_API_URL / PUBLIC_FRONTEND_URL), а на хост запроса
|
||||
* переключаемся только если в настройках указан внутренний Docker-хост.
|
||||
*/
|
||||
export function isLocalDevHostname(hostname: string) {
|
||||
const host = hostname.trim().toLowerCase();
|
||||
return host === 'localhost' || host === '127.0.0.1' || host === '[::1]';
|
||||
}
|
||||
|
||||
export function isLocalDevBaseUrl(url: string) {
|
||||
try {
|
||||
return isLocalDevHostname(new URL(url).hostname);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Выбирает публичный URL: приоритет у реального домена, не localhost из .env/seed. */
|
||||
export function pickBestPublicBase(candidates: Array<string | null | undefined>, fallback: string) {
|
||||
const normalized = candidates
|
||||
.map((candidate) => candidate?.trim())
|
||||
.filter((candidate): candidate is string => Boolean(candidate))
|
||||
.map((candidate) => normalizePublicBaseUrl(candidate));
|
||||
|
||||
const productionReachable = normalized.find(
|
||||
(candidate) => isBrowserReachableBaseUrl(candidate) && !isLocalDevBaseUrl(candidate)
|
||||
);
|
||||
if (productionReachable) {
|
||||
return productionReachable;
|
||||
}
|
||||
|
||||
const reachable = normalized.find((candidate) => isBrowserReachableBaseUrl(candidate));
|
||||
if (reachable) {
|
||||
return reachable;
|
||||
}
|
||||
|
||||
if (normalized[0]) {
|
||||
return normalized[0];
|
||||
}
|
||||
|
||||
return normalizePublicBaseUrl(fallback);
|
||||
}
|
||||
|
||||
export function preferCanonicalBase(stored: string, fromRequest: string | null) {
|
||||
if (stored && isBrowserReachableBaseUrl(stored)) {
|
||||
return normalizePublicBaseUrl(stored);
|
||||
}
|
||||
if (fromRequest && isBrowserReachableBaseUrl(fromRequest)) {
|
||||
return normalizePublicBaseUrl(fromRequest);
|
||||
}
|
||||
return normalizePublicBaseUrl(stored);
|
||||
return pickBestPublicBase([stored, fromRequest], stored || fromRequest || '');
|
||||
}
|
||||
|
||||
export function preferBrowserReachableBase(stored: string, fromRequest: string | null) {
|
||||
|
||||
Reference in New Issue
Block a user