Skip to content

Commit 42b5ef7

Browse files
authored
fix(server): redirect to setup page if not initialized (#7871)
1 parent ad42418 commit 42b5ef7

File tree

2 files changed

+54
-8
lines changed

2 files changed

+54
-8
lines changed

packages/backend/server/src/app.module.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
import { join } from 'node:path';
1+
import { join, resolve } from 'node:path';
2+
import { fileURLToPath } from 'node:url';
23

34
import {
45
DynamicModule,
56
ForwardReference,
67
Logger,
8+
MiddlewareConsumer,
79
Module,
10+
NestModule,
811
} from '@nestjs/common';
912
import { ScheduleModule } from '@nestjs/schedule';
1013
import { ServeStaticModule } from '@nestjs/serve-static';
@@ -16,7 +19,7 @@ import { ADD_ENABLED_FEATURES, ServerConfigModule } from './core/config';
1619
import { DocModule } from './core/doc';
1720
import { FeatureModule } from './core/features';
1821
import { QuotaModule } from './core/quota';
19-
import { CustomSetupModule } from './core/setup';
22+
import { CustomSetupModule, SetupMiddleware } from './core/setup';
2023
import { StorageModule } from './core/storage';
2124
import { SyncModule } from './core/sync';
2225
import { UserModule } from './core/user';
@@ -135,16 +138,26 @@ export class AppModuleBuilder {
135138
}
136139

137140
compile() {
141+
const configure = (consumer: MiddlewareConsumer) => {
142+
if (this.config.isSelfhosted) {
143+
consumer.apply(SetupMiddleware).forRoutes('*');
144+
}
145+
};
146+
138147
@Module({
139148
imports: this.modules,
140149
controllers: this.config.isSelfhosted ? [] : [AppController],
141150
})
142-
class AppModule {}
151+
class AppModule implements NestModule {
152+
configure = configure;
153+
}
143154

144155
return AppModule;
145156
}
146157
}
147158

159+
const pwd = resolve(fileURLToPath(import.meta.url), '../../');
160+
148161
function buildAppModule() {
149162
AFFiNE = mergeConfigOverride(AFFiNE);
150163
const factor = new AppModuleBuilder(AFFiNE);
@@ -179,12 +192,12 @@ function buildAppModule() {
179192
config => config.isSelfhosted,
180193
CustomSetupModule,
181194
ServeStaticModule.forRoot({
182-
rootPath: join('/app', 'static'),
183-
exclude: ['/admin*'],
195+
rootPath: join(pwd, 'static', 'admin'),
196+
renderPath: /^\/admin\/?/,
184197
}),
185198
ServeStaticModule.forRoot({
186-
rootPath: join('/app', 'static', 'admin'),
187-
serveRoot: '/admin',
199+
rootPath: join(pwd, 'static'),
200+
renderPath: '*',
188201
})
189202
);
190203

packages/backend/server/src/core/setup/index.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,42 @@
1-
import { Module } from '@nestjs/common';
1+
import { Injectable, Module, NestMiddleware } from '@nestjs/common';
2+
import { PrismaClient } from '@prisma/client';
3+
import type { Request, Response } from 'express';
24

35
import { AuthModule } from '../auth';
46
import { UserModule } from '../user';
57
import { CustomSetupController } from './controller';
68

9+
@Injectable()
10+
export class SetupMiddleware implements NestMiddleware {
11+
private initialized: boolean | null = null;
12+
constructor(private readonly db: PrismaClient) {}
13+
14+
use(req: Request, res: Response, next: (error?: Error | any) => void) {
15+
// never throw
16+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
17+
this.allow().then(allowed => {
18+
if (allowed) {
19+
next();
20+
} else if (!req.path.startsWith('/admin/setup')) {
21+
res.redirect('/admin/setup');
22+
}
23+
});
24+
}
25+
26+
async allow() {
27+
try {
28+
if (this.initialized === null) {
29+
this.initialized = (await this.db.user.count()) > 0;
30+
}
31+
} catch (e) {
32+
// avoid block the whole app
33+
return true;
34+
}
35+
36+
return this.initialized;
37+
}
38+
}
39+
740
@Module({
841
imports: [AuthModule, UserModule],
942
controllers: [CustomSetupController],

0 commit comments

Comments
 (0)