0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

refactor(core): init domain-based multi-tenancy env

This commit is contained in:
Gao Sun 2023-02-07 19:07:59 +08:00
parent d3e786ec80
commit 1e8c00c014
No known key found for this signature in database
GPG key ID: 13EBE123E4773688
5 changed files with 9 additions and 34 deletions

View file

@ -17,15 +17,11 @@ const logListening = (type: 'core' | 'admin' = 'core') => {
}; };
const getTenantId = () => { const getTenantId = () => {
if (!EnvSet.values.isMultiTenancy) { if (!EnvSet.values.isDomainBasedMultiTenancy) {
return defaultTenant; return (!EnvSet.values.isProduction && EnvSet.values.developmentTenantId) || defaultTenant;
} }
if (EnvSet.values.multiTenancyMode === 'domain') {
throw new Error('Not implemented'); throw new Error('Not implemented');
}
return !EnvSet.values.isProduction && EnvSet.values.developmentTenantId;
}; };
export default async function initApp(app: Koa): Promise<void> { export default async function initApp(app: Koa): Promise<void> {

View file

@ -1,5 +1,3 @@
import net from 'net';
import { tryThat } from '@logto/shared'; import { tryThat } from '@logto/shared';
import { assertEnv, getEnv, getEnvAsStringArray } from '@silverhand/essentials'; import { assertEnv, getEnv, getEnvAsStringArray } from '@silverhand/essentials';
@ -7,7 +5,6 @@ import UrlSet from './UrlSet.js';
import { isTrue } from './parameters.js'; import { isTrue } from './parameters.js';
import { throwErrorWithDsnMessage } from './throw-errors.js'; import { throwErrorWithDsnMessage } from './throw-errors.js';
const enableMultiTenancyKey = 'ENABLE_MULTI_TENANCY';
const developmentTenantIdKey = 'DEVELOPMENT_TENANT_ID'; const developmentTenantIdKey = 'DEVELOPMENT_TENANT_ID';
type MultiTenancyMode = 'domain' | 'env'; type MultiTenancyMode = 'domain' | 'env';
@ -21,11 +18,11 @@ export default class GlobalValues {
public readonly httpsKey = process.env.HTTPS_KEY_PATH; public readonly httpsKey = process.env.HTTPS_KEY_PATH;
public readonly isHttpsEnabled = Boolean(this.httpsCert && this.httpsKey); public readonly isHttpsEnabled = Boolean(this.httpsCert && this.httpsKey);
public readonly isMultiTenancy = isTrue(getEnv(enableMultiTenancyKey));
public readonly urlSet = new UrlSet(this.isHttpsEnabled, 3001); public readonly urlSet = new UrlSet(this.isHttpsEnabled, 3001);
public readonly adminUrlSet = new UrlSet(this.isHttpsEnabled, 3002, 'ADMIN_'); public readonly adminUrlSet = new UrlSet(this.isHttpsEnabled, 3002, 'ADMIN_');
public readonly isDomainBasedMultiTenancy = this.urlSet.endpoint.includes('*');
// eslint-disable-next-line unicorn/consistent-function-scoping // eslint-disable-next-line unicorn/consistent-function-scoping
public readonly databaseUrl = tryThat(() => assertEnv('DB_URL'), throwErrorWithDsnMessage); public readonly databaseUrl = tryThat(() => assertEnv('DB_URL'), throwErrorWithDsnMessage);
public readonly developmentTenantId = getEnv(developmentTenantIdKey); public readonly developmentTenantId = getEnv(developmentTenantIdKey);
@ -41,12 +38,4 @@ export default class GlobalValues {
public get endpoint(): string { public get endpoint(): string {
return this.urlSet.endpoint; return this.urlSet.endpoint;
} }
public get multiTenancyMode(): MultiTenancyMode {
const { hostname } = new URL(this.endpoint);
return this.isMultiTenancy && !net.isIP(hostname) && hostname !== 'localhost'
? 'domain'
: 'env';
}
} }

View file

@ -17,10 +17,7 @@ try {
}); });
await initI18n(); await initI18n();
await loadConnectorFactories(); await loadConnectorFactories();
if (EnvSet.values.isMultiTenancy) {
await checkRowLevelSecurity(EnvSet.default.queryClient); await checkRowLevelSecurity(EnvSet.default.queryClient);
}
// Import last until init completed // Import last until init completed
const { default: initApp } = await import('./app/init.js'); const { default: initApp } = await import('./app/init.js');

View file

@ -19,7 +19,7 @@ export default function koaConsoleRedirectProxy<
return; return;
} }
if (ctx.path === '/console/welcome' && hasUser) { if ((ctx.path === '/' || ctx.path === '/console/welcome') && hasUser) {
ctx.redirect('/console'); ctx.redirect('/console');
return; return;

View file

@ -23,18 +23,11 @@ import initRouter from '#src/routes/init.js';
import Libraries from './Libraries.js'; import Libraries from './Libraries.js';
import Queries from './Queries.js'; import Queries from './Queries.js';
import type TenantContext from './TenantContext.js'; import type TenantContext from './TenantContext.js';
import { defaultTenant } from './consts.js';
import { getTenantDatabaseDsn } from './utils.js'; import { getTenantDatabaseDsn } from './utils.js';
export default class Tenant implements TenantContext { export default class Tenant implements TenantContext {
static async create(id: string): Promise<Tenant> { static async create(id: string): Promise<Tenant> {
if (!EnvSet.values.isMultiTenancy) { if (!EnvSet.values.isDomainBasedMultiTenancy) {
if (id !== defaultTenant) {
throw new Error(
`Trying to create a tenant instance with ID ${id} in single-tenancy mode. This is a no-op.`
);
}
return new Tenant(EnvSet.default, id); return new Tenant(EnvSet.default, id);
} }
@ -56,7 +49,7 @@ export default class Tenant implements TenantContext {
return mount(this.app); return mount(this.app);
} }
constructor(public readonly envSet: EnvSet, public readonly id: string) { private constructor(public readonly envSet: EnvSet, public readonly id: string) {
const modelRouters = createModelRouters(envSet.queryClient); const modelRouters = createModelRouters(envSet.queryClient);
const queries = new Queries(envSet.pool); const queries = new Queries(envSet.pool);
const libraries = new Libraries(queries, modelRouters); const libraries = new Libraries(queries, modelRouters);