update
This commit is contained in:
@@ -34,12 +34,15 @@ PORT=3000
|
|||||||
DATABASE_URL="file:./dev.db"
|
DATABASE_URL="file:./dev.db"
|
||||||
JWT_ACCESS_SECRET=change_this_access_secret
|
JWT_ACCESS_SECRET=change_this_access_secret
|
||||||
JWT_REFRESH_SECRET=change_this_refresh_secret
|
JWT_REFRESH_SECRET=change_this_refresh_secret
|
||||||
|
DEFAULT_ADMIN_USERNAME=admin
|
||||||
|
DEFAULT_ADMIN_PASSWORD=admin123456
|
||||||
```
|
```
|
||||||
|
|
||||||
说明:
|
说明:
|
||||||
|
|
||||||
- 当前项目 Prisma 使用 `SQLite`(`server/prisma/schema.prisma`)。
|
- 当前项目 Prisma 使用 `SQLite`(`server/prisma/schema.prisma`)。
|
||||||
- `DATABASE_URL="file:./dev.db"` 对应数据库文件在容器内路径 `/app/server/prisma/dev.db`。
|
- `DATABASE_URL="file:./dev.db"` 对应数据库文件在容器内路径 `/app/server/prisma/dev.db`。
|
||||||
|
- 应用启动后会自动检查管理员账号;若 `DEFAULT_ADMIN_USERNAME` 不存在,则自动创建该账号。
|
||||||
|
|
||||||
## 3. 构建镜像
|
## 3. 构建镜像
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ JWT_ACCESS_SECRET=change_this_access_secret
|
|||||||
JWT_REFRESH_SECRET=change_this_refresh_secret
|
JWT_REFRESH_SECRET=change_this_refresh_secret
|
||||||
JWT_ACCESS_EXPIRES_IN=2h
|
JWT_ACCESS_EXPIRES_IN=2h
|
||||||
JWT_REFRESH_EXPIRES_IN=7d
|
JWT_REFRESH_EXPIRES_IN=7d
|
||||||
|
DEFAULT_ADMIN_USERNAME=admin
|
||||||
|
DEFAULT_ADMIN_PASSWORD=admin123456
|
||||||
|
|
||||||
GITLAB_BASE_URL=
|
GITLAB_BASE_URL=
|
||||||
GITLAB_API_BASE=
|
GITLAB_API_BASE=
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common';
|
import { INestApplication, Injectable, Logger, OnModuleInit } from '@nestjs/common';
|
||||||
import { PrismaClient } from '@prisma/client';
|
import { AdminUserStatus, PrismaClient } from '@prisma/client';
|
||||||
|
import argon2 from 'argon2';
|
||||||
|
import { randomUUID } from 'crypto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PrismaService extends PrismaClient implements OnModuleInit {
|
export class PrismaService extends PrismaClient implements OnModuleInit {
|
||||||
|
private readonly logger = new Logger(PrismaService.name);
|
||||||
|
|
||||||
async onModuleInit(): Promise<void> {
|
async onModuleInit(): Promise<void> {
|
||||||
await this.$connect();
|
await this.$connect();
|
||||||
await this.$queryRawUnsafe('PRAGMA journal_mode = WAL;');
|
await this.$queryRawUnsafe('PRAGMA journal_mode = WAL;');
|
||||||
|
await this.ensureDefaultAdminUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
async enableShutdownHooks(app: INestApplication): Promise<void> {
|
async enableShutdownHooks(app: INestApplication): Promise<void> {
|
||||||
@@ -13,4 +18,31 @@ export class PrismaService extends PrismaClient implements OnModuleInit {
|
|||||||
await app.close();
|
await app.close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async ensureDefaultAdminUser(): Promise<void> {
|
||||||
|
const username = process.env.DEFAULT_ADMIN_USERNAME?.trim() || 'admin';
|
||||||
|
const password = process.env.DEFAULT_ADMIN_PASSWORD || 'admin123456';
|
||||||
|
|
||||||
|
const existingAdmin = await this.adminUser.findUnique({
|
||||||
|
where: { username },
|
||||||
|
select: { id: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existingAdmin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const passwordHash = await argon2.hash(password, { type: argon2.argon2id });
|
||||||
|
await this.adminUser.create({
|
||||||
|
data: {
|
||||||
|
id: `u_admin_${randomUUID().replace(/-/g, '')}`,
|
||||||
|
username,
|
||||||
|
passwordHash,
|
||||||
|
displayName: 'System Admin',
|
||||||
|
status: AdminUserStatus.active,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
this.logger.log(`Default admin user initialized: ${username}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user