0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-27 21:39:16 -05:00

refactor(core): move app to tenant instance

This commit is contained in:
Gao Sun 2023-01-07 18:17:43 +08:00
parent 954664bd28
commit 8d829b8f3d
No known key found for this signature in database
GPG key ID: 13EBE123E4773688
5 changed files with 107 additions and 44 deletions

View file

@ -58,6 +58,7 @@
"koa-proxies": "^0.12.1",
"koa-router": "^12.0.0",
"koa-send": "^5.0.1",
"lru-cache": "^7.14.1",
"nanoid": "^4.0.0",
"oidc-provider": "^7.13.0",
"p-retry": "^5.1.2",

View file

@ -1,26 +1,12 @@
import fs from 'fs/promises';
import https from 'https';
import http2 from 'http2';
import { deduplicate } from '@silverhand/essentials';
import chalk from 'chalk';
import type Koa from 'koa';
import compose from 'koa-compose';
import koaLogger from 'koa-logger';
import mount from 'koa-mount';
import envSet, { MountedApps } from '#src/env-set/index.js';
import koaCheckDemoApp from '#src/middleware/koa-check-demo-app.js';
import koaConnectorErrorHandler from '#src/middleware/koa-connector-error-handler.js';
import koaErrorHandler from '#src/middleware/koa-error-handler.js';
import koaI18next from '#src/middleware/koa-i18next.js';
import koaOIDCErrorHandler from '#src/middleware/koa-oidc-error-handler.js';
import koaRootProxy from '#src/middleware/koa-root-proxy.js';
import koaSlonikErrorHandler from '#src/middleware/koa-slonik-error-handler.js';
import koaSpaProxy from '#src/middleware/koa-spa-proxy.js';
import koaSpaSessionGuard from '#src/middleware/koa-spa-session-guard.js';
import koaWelcomeProxy from '#src/middleware/koa-welcome-proxy.js';
import initOidc from '#src/oidc/init.js';
import initRouter from '#src/routes/init.js';
import envSet from '#src/env-set/index.js';
import { tenantPool } from '#src/tenants/index.js';
const logListening = () => {
const { localhostUrl, endpoint } = envSet.values;
@ -30,39 +16,21 @@ const logListening = () => {
}
};
const defaultTenant = 'default';
export default async function initApp(app: Koa): Promise<void> {
app.use(koaLogger());
app.use(koaErrorHandler());
app.use(koaOIDCErrorHandler());
app.use(koaSlonikErrorHandler());
app.use(koaConnectorErrorHandler());
app.use(koaI18next());
app.use(async (ctx, next) => {
// TODO: add multi-tenancy logic
const tenant = tenantPool.get(defaultTenant);
const provider = initOidc(app);
initRouter(app, provider);
app.use(mount('/', koaRootProxy()));
app.use(mount('/' + MountedApps.Welcome, koaWelcomeProxy()));
app.use(
mount('/' + MountedApps.Console, koaSpaProxy(MountedApps.Console, 5002, MountedApps.Console))
);
app.use(
mount(
'/' + MountedApps.DemoApp,
compose([koaCheckDemoApp(), koaSpaProxy(MountedApps.DemoApp, 5003, MountedApps.DemoApp)])
)
);
app.use(compose([koaSpaSessionGuard(provider), koaSpaProxy()]));
return tenant.run(ctx, next);
});
const { isHttpsEnabled, httpsCert, httpsKey, port } = envSet.values;
if (isHttpsEnabled && httpsCert && httpsKey) {
https
.createServer(
http2
.createSecureServer(
{ cert: await fs.readFile(httpsCert), key: await fs.readFile(httpsKey) },
app.callback()
)
@ -73,6 +41,7 @@ export default async function initApp(app: Koa): Promise<void> {
return;
}
// Chrome doesn't allow insecure http/2 servers
app.listen(port, () => {
logListening();
});

View file

@ -0,0 +1,64 @@
import type { MiddlewareType } from 'koa';
import Koa from 'koa';
import compose from 'koa-compose';
import koaLogger from 'koa-logger';
import mount from 'koa-mount';
import type { Provider } from 'oidc-provider';
import { MountedApps } from '#src/env-set/index.js';
import koaCheckDemoApp from '#src/middleware/koa-check-demo-app.js';
import koaConnectorErrorHandler from '#src/middleware/koa-connector-error-handler.js';
import koaErrorHandler from '#src/middleware/koa-error-handler.js';
import koaI18next from '#src/middleware/koa-i18next.js';
import koaOIDCErrorHandler from '#src/middleware/koa-oidc-error-handler.js';
import koaRootProxy from '#src/middleware/koa-root-proxy.js';
import koaSlonikErrorHandler from '#src/middleware/koa-slonik-error-handler.js';
import koaSpaProxy from '#src/middleware/koa-spa-proxy.js';
import koaSpaSessionGuard from '#src/middleware/koa-spa-session-guard.js';
import koaWelcomeProxy from '#src/middleware/koa-welcome-proxy.js';
import initOidc from '#src/oidc/init.js';
import initRouter from '#src/routes/init.js';
export default class Tenant {
public readonly provider: Provider;
protected readonly app: Koa;
get run(): MiddlewareType {
return mount(this.app);
}
constructor(public id: string) {
const app = new Koa();
const provider = initOidc(app);
app.use(koaLogger());
app.use(koaErrorHandler());
app.use(koaOIDCErrorHandler());
app.use(koaSlonikErrorHandler());
app.use(koaConnectorErrorHandler());
app.use(koaI18next());
initRouter(app, provider);
app.use(mount('/', koaRootProxy()));
app.use(mount('/' + MountedApps.Welcome, koaWelcomeProxy()));
app.use(
mount('/' + MountedApps.Console, koaSpaProxy(MountedApps.Console, 5002, MountedApps.Console))
);
app.use(
mount(
'/' + MountedApps.DemoApp,
compose([koaCheckDemoApp(), koaSpaProxy(MountedApps.DemoApp, 5003, MountedApps.DemoApp)])
)
);
app.use(compose([koaSpaSessionGuard(provider), koaSpaProxy()]));
this.app = app;
this.provider = provider;
}
}

View file

@ -0,0 +1,22 @@
import LRUCache from 'lru-cache';
import Tenant from './Tenant.js';
class TenantPool {
protected cache = new LRUCache<string, Tenant>({ max: 500 });
get(tenantId: string): Tenant {
const tenant = this.cache.get(tenantId);
if (tenant) {
return tenant;
}
const newTenant = new Tenant(tenantId);
this.cache.set(tenantId, newTenant);
return newTenant;
}
}
export const tenantPool = new TenantPool();

7
pnpm-lock.yaml generated
View file

@ -303,6 +303,7 @@ importers:
koa-router: ^12.0.0
koa-send: ^5.0.1
lint-staged: ^13.0.0
lru-cache: ^7.14.1
nanoid: ^4.0.0
node-mocks-http: ^1.12.1
nodemon: ^2.0.19
@ -355,6 +356,7 @@ importers:
koa-proxies: 0.12.1_koa@2.13.4
koa-router: 12.0.0
koa-send: 5.0.1
lru-cache: 7.14.1
nanoid: 4.0.0
oidc-provider: 7.13.0
p-retry: 5.1.2
@ -10245,6 +10247,11 @@ packages:
dependencies:
yallist: 4.0.0
/lru-cache/7.14.1:
resolution: {integrity: sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==}
engines: {node: '>=12'}
dev: false
/lz-string/1.4.4:
resolution: {integrity: sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==}
hasBin: true