fix(plugins): match remote HMAC tenants with the same host rules as get_user
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,6 +4,10 @@ import { PrismaService } from '../prisma/prisma.service';
|
||||
import { applyKhanegiNavSample } from './khanegi-nav-sample';
|
||||
import { rewriteLegacyUploadUrl } from '../uploads/uploads.util';
|
||||
import { PLUGIN_STORE_SETTING_KEY } from '../program-settings/runtime-setting-keys';
|
||||
import {
|
||||
findTenantForHost as matchTenantForHost,
|
||||
normalizeTenantHost,
|
||||
} from '../auth/tenant-host.util';
|
||||
|
||||
type UiSetting = { key: string; value: string };
|
||||
|
||||
@@ -28,7 +32,7 @@ export class GetUserService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async resolveByHost(hostHeader?: string, domainQuery?: string) {
|
||||
const host = this.normalizeHost(domainQuery || hostHeader || '');
|
||||
const host = normalizeTenantHost(domainQuery || hostHeader || '');
|
||||
if (!host) {
|
||||
throw new NotFoundException('domain required');
|
||||
}
|
||||
@@ -374,75 +378,12 @@ export class GetUserService {
|
||||
}
|
||||
|
||||
/**
|
||||
* اول دامنهٔ اصلی (Tenant.domain)، بعد aliases داخل domains[].
|
||||
* اگر چند نسخه یک دامنه را داشته باشند، نسخهٔ primary برنده است.
|
||||
* همان منطق HMAC ریموت: دامنهٔ اصلی، aliases، بعد admin/app/node URL.
|
||||
*/
|
||||
private findTenantForHost<
|
||||
T extends {
|
||||
domain: string;
|
||||
domains: unknown;
|
||||
},
|
||||
>(tenants: T[], host: string): T | undefined {
|
||||
const normalizedHost = this.normalizeHost(host);
|
||||
const hostNoWww = normalizedHost.replace(/^www\./, '');
|
||||
|
||||
const primary = tenants.find((item) => {
|
||||
const d = this.normalizeHost(item.domain);
|
||||
return d === normalizedHost || d.replace(/^www\./, '') === hostNoWww;
|
||||
});
|
||||
if (primary) return primary;
|
||||
|
||||
return tenants.find((item) => this.matchesAliasHost(item, normalizedHost));
|
||||
}
|
||||
|
||||
private matchesAliasHost(
|
||||
tenant: {
|
||||
domain: string;
|
||||
domains: unknown;
|
||||
},
|
||||
private findTenantForHost<T extends { domain: string; domains: unknown }>(
|
||||
tenants: T[],
|
||||
host: string,
|
||||
) {
|
||||
const hostNoWww = host.replace(/^www\./, '');
|
||||
for (const value of this.readDomains(tenant.domains)) {
|
||||
const normalized = this.normalizeHost(value);
|
||||
if (!normalized) continue;
|
||||
if (normalized === host || normalized.replace(/^www\./, '') === hostNoWww) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private matchesHost(
|
||||
tenant: {
|
||||
domain: string;
|
||||
domains: unknown;
|
||||
},
|
||||
host: string,
|
||||
) {
|
||||
return Boolean(this.findTenantForHost([tenant], host));
|
||||
}
|
||||
|
||||
private readDomains(raw: unknown): string[] {
|
||||
if (!raw) return [];
|
||||
if (Array.isArray(raw)) return raw.map(String);
|
||||
if (typeof raw === 'string') {
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
return Array.isArray(parsed) ? parsed.map(String) : [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
private normalizeHost(value: string) {
|
||||
return value
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/^https?:\/\//, '')
|
||||
.split('/')[0]
|
||||
.split(':')[0];
|
||||
): T | undefined {
|
||||
return matchTenantForHost(tenants, host);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user