test: build HMAC tenant fixtures from domain, drop product URLs
HMAC identity tests should not hardcode gholak/montzar hosts. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,65 +1,66 @@
|
||||
import { findTenantForHost, scoreTenantHost } from './tenant-host.util';
|
||||
import {
|
||||
findTenantForHost,
|
||||
scoreTenantHost,
|
||||
type TenantHostFields,
|
||||
} from './tenant-host.util';
|
||||
|
||||
const gholak = {
|
||||
domain: 'app.gholaktala.ir',
|
||||
function fromDomain(
|
||||
domain: string,
|
||||
extra: Partial<TenantHostFields> = {},
|
||||
): TenantHostFields {
|
||||
return {
|
||||
domain,
|
||||
domains: [],
|
||||
appUrl: 'https://app.gholaktala.ir',
|
||||
adminUrl: 'https://k.montzar.ir/admin',
|
||||
nodeServer: 'https://new.gholaktala.ir/server',
|
||||
};
|
||||
|
||||
const montzar = {
|
||||
domain: 'k.montzar.ir',
|
||||
domains: ['montzar.ir'],
|
||||
appUrl: 'https://k.montzar.ir',
|
||||
adminUrl: 'https://k.montzar.ir',
|
||||
nodeServer: 'https://new.gholaktala.ir/server',
|
||||
};
|
||||
|
||||
const otherOnSameBox = {
|
||||
domain: 'examplegold.ir',
|
||||
domains: [],
|
||||
appUrl: 'https://examplegold.ir',
|
||||
appUrl: `https://${domain}`,
|
||||
adminUrl: null,
|
||||
nodeServer: 'https://new.gholaktala.ir/server',
|
||||
nodeServer: null,
|
||||
...extra,
|
||||
};
|
||||
}
|
||||
|
||||
describe('findTenantForHost', () => {
|
||||
const tenants = [gholak, otherOnSameBox, montzar];
|
||||
|
||||
it('hmac does not treat shared adminUrl as gholaktala', () => {
|
||||
expect(scoreTenantHost(gholak, 'k.montzar.ir', 'hmac')).toBe(0);
|
||||
expect(findTenantForHost(tenants, 'k.montzar.ir', 'hmac')?.domain).toBe(
|
||||
'k.montzar.ir',
|
||||
);
|
||||
it('hmac matches the tenant whose domain is the host', () => {
|
||||
const host = 'shop.example.ir';
|
||||
const mine = fromDomain(host);
|
||||
const other = fromDomain('other.example.ir', {
|
||||
adminUrl: `https://${host}/admin`,
|
||||
});
|
||||
|
||||
it('hmac without montzar tenant does not fall back to gholak adminUrl', () => {
|
||||
expect(
|
||||
findTenantForHost([gholak, otherOnSameBox], 'k.montzar.ir', 'hmac'),
|
||||
).toBeUndefined();
|
||||
expect(scoreTenantHost(other, host, 'hmac')).toBe(0);
|
||||
expect(findTenantForHost([other, mine], host, 'hmac')?.domain).toBe(host);
|
||||
});
|
||||
|
||||
it('full get_user still maps k.montzar.ir to montzar by primary domain', () => {
|
||||
expect(findTenantForHost(tenants, 'k.montzar.ir')?.domain).toBe(
|
||||
'k.montzar.ir',
|
||||
);
|
||||
it('hmac does not use another tenant adminUrl as identity', () => {
|
||||
const host = 'panel.example.ir';
|
||||
const other = fromDomain('app.other.ir', {
|
||||
adminUrl: `https://${host}/admin`,
|
||||
});
|
||||
|
||||
it('maps new.gholaktala.ir to gholaktala via subdomain, not nodeServer', () => {
|
||||
const gholakBare = { ...gholak, domain: 'gholaktala.ir' };
|
||||
expect(
|
||||
findTenantForHost([montzar, otherOnSameBox, gholakBare], 'new.gholaktala.ir')
|
||||
?.domain,
|
||||
).toBe('gholaktala.ir');
|
||||
expect(scoreTenantHost(gholakBare, 'new.gholaktala.ir')).toBe(75);
|
||||
expect(findTenantForHost([other], host, 'hmac')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('does not pick a random tenant when only nodeServer matches several rows', () => {
|
||||
const sharedOnly = [
|
||||
{ ...montzar, domain: 'a.ir', domains: [] },
|
||||
{ ...gholak, domain: 'b.ir', domains: [] },
|
||||
];
|
||||
expect(findTenantForHost(sharedOnly, 'new.gholaktala.ir')).toBeUndefined();
|
||||
it('full match uses primary domain when present', () => {
|
||||
const host = 'shop.example.ir';
|
||||
expect(findTenantForHost([fromDomain(host)], host)?.domain).toBe(host);
|
||||
});
|
||||
|
||||
it('subdomain of the tenant domain beats a shared nodeServer', () => {
|
||||
const root = 'shop.example.ir';
|
||||
const api = `new.${root}`;
|
||||
const mine = fromDomain(root, { nodeServer: `https://${api}/server` });
|
||||
const roommate = fromDomain('roommate.ir', {
|
||||
nodeServer: `https://${api}/server`,
|
||||
});
|
||||
|
||||
expect(findTenantForHost([roommate, mine], api)?.domain).toBe(root);
|
||||
expect(scoreTenantHost(mine, api)).toBe(75);
|
||||
});
|
||||
|
||||
it('does not pick a tenant when only a shared nodeServer matches', () => {
|
||||
const api = 'box.example.ir';
|
||||
const left = fromDomain('a.ir', { nodeServer: `https://${api}/server` });
|
||||
const right = fromDomain('b.ir', { nodeServer: `https://${api}/server` });
|
||||
|
||||
expect(findTenantForHost([left, right], api)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -54,7 +54,7 @@ function hostsEqual(left: string, right: string): boolean {
|
||||
return left.replace(/^www\./, '') === right.replace(/^www\./, '');
|
||||
}
|
||||
|
||||
/** new.gholaktala.ir belongs to tenant domain gholaktala.ir — not via shared nodeServer. */
|
||||
/** new.shop.ir belongs to tenant domain shop.ir — not via shared nodeServer. */
|
||||
function isSubdomainOf(host: string, parent: string): boolean {
|
||||
const child = normalizeTenantHost(host);
|
||||
const root = normalizeTenantHost(parent).replace(/^www\./, '');
|
||||
@@ -66,8 +66,7 @@ export type TenantHostMatchMode = 'full' | 'hmac';
|
||||
|
||||
/**
|
||||
* full: get_user — دامنه، alias، app/admin/node.
|
||||
* hmac: فقط دامنهٔ اصلی نسخه (و سابدامنهٔ همان). adminUrl مشترک
|
||||
* (k.montzar.ir روی نسخهٔ app.gholaktala.ir) هویت نیست.
|
||||
* hmac: فقط دامنهٔ اصلی نسخه (و سابدامنهٔ همان). adminUrl هویت نیست.
|
||||
*/
|
||||
export function scoreTenantHost(
|
||||
tenant: TenantHostFields,
|
||||
|
||||
Reference in New Issue
Block a user