refactor(server): config system (#11081)

This commit is contained in:
forehalo
2025-03-27 12:32:28 +00:00
parent 7091111f85
commit 0ea38680fa
274 changed files with 7583 additions and 5841 deletions

View File

@@ -1,10 +1,11 @@
import { OptionalModule } from '../../base';
import { Module } from '@nestjs/common';
import { PermissionModule } from '../../core/permission';
import { QuotaModule } from '../../core/quota';
import { LicenseResolver } from './resolver';
import { LicenseService } from './service';
@OptionalModule({
@Module({
imports: [QuotaModule, PermissionModule],
providers: [LicenseService, LicenseResolver],
})

View File

@@ -9,7 +9,7 @@ import {
Resolver,
} from '@nestjs/graphql';
import { ActionForbidden, Config } from '../../base';
import { UseNamedGuard } from '../../base';
import { CurrentUser } from '../../core/auth';
import { AccessController } from '../../core/permission';
import { WorkspaceType } from '../../core/workspaces';
@@ -34,10 +34,10 @@ export class License {
expiredAt!: Date | null;
}
@UseNamedGuard('selfhost')
@Resolver(() => WorkspaceType)
export class LicenseResolver {
constructor(
private readonly config: Config,
private readonly service: LicenseService,
private readonly ac: AccessController
) {}
@@ -51,13 +51,6 @@ export class LicenseResolver {
@CurrentUser() user: CurrentUser,
@Parent() workspace: WorkspaceType
): Promise<License | null> {
// NOTE(@forehalo):
// we can't simply disable license resolver for non-selfhosted server
// it will make the gql codegen messed up.
if (!this.config.isSelfhosted) {
return null;
}
await this.ac
.user(user.id)
.workspace(workspace.id)
@@ -71,10 +64,6 @@ export class LicenseResolver {
@Args('workspaceId') workspaceId: string,
@Args('license') license: string
) {
if (!this.config.isSelfhosted) {
throw new ActionForbidden();
}
await this.ac
.user(user.id)
.workspace(workspaceId)
@@ -88,10 +77,6 @@ export class LicenseResolver {
@CurrentUser() user: CurrentUser,
@Args('workspaceId') workspaceId: string
) {
if (!this.config.isSelfhosted) {
throw new ActionForbidden();
}
await this.ac
.user(user.id)
.workspace(workspaceId)
@@ -105,10 +90,6 @@ export class LicenseResolver {
@CurrentUser() user: CurrentUser,
@Args('workspaceId') workspaceId: string
) {
if (!this.config.isSelfhosted) {
throw new ActionForbidden();
}
await this.ac
.user(user.id)
.workspace(workspaceId)

View File

@@ -1,9 +1,8 @@
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { Injectable, Logger } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { InstalledLicense, PrismaClient } from '@prisma/client';
import {
Config,
EventBus,
InternalServerError,
LicenseNotFound,
@@ -22,35 +21,22 @@ interface License {
}
@Injectable()
export class LicenseService implements OnModuleInit {
export class LicenseService {
private readonly logger = new Logger(LicenseService.name);
constructor(
private readonly config: Config,
private readonly db: PrismaClient,
private readonly event: EventBus,
private readonly models: Models
) {}
async onModuleInit() {
if (this.config.isSelfhosted) {
this.event.on(
'workspace.subscription.activated',
this.onWorkspaceSubscriptionUpdated
);
this.event.on(
'workspace.subscription.canceled',
this.onWorkspaceSubscriptionCanceled
);
}
}
private readonly onWorkspaceSubscriptionUpdated = async ({
@OnEvent('workspace.subscription.activated')
async onWorkspaceSubscriptionUpdated({
workspaceId,
plan,
recurring,
quantity,
}: Events['workspace.subscription.activated']) => {
}: Events['workspace.subscription.activated']) {
switch (plan) {
case SubscriptionPlan.SelfHostedTeam:
await this.models.workspaceFeature.add(
@@ -66,12 +52,13 @@ export class LicenseService implements OnModuleInit {
default:
break;
}
};
}
private readonly onWorkspaceSubscriptionCanceled = async ({
@OnEvent('workspace.subscription.canceled')
async onWorkspaceSubscriptionCanceled({
workspaceId,
plan,
}: Events['workspace.subscription.canceled']) => {
}: Events['workspace.subscription.canceled']) {
switch (plan) {
case SubscriptionPlan.SelfHostedTeam:
await this.models.workspaceFeature.remove(workspaceId, 'team_plan_v1');
@@ -79,7 +66,7 @@ export class LicenseService implements OnModuleInit {
default:
break;
}
};
}
async getLicense(workspaceId: string) {
return this.db.installedLicense.findUnique({
@@ -201,10 +188,6 @@ export class LicenseService implements OnModuleInit {
@OnEvent('workspace.members.updated')
async updateTeamSeats(payload: Events['workspace.members.updated']) {
if (!this.config.isSelfhosted) {
return;
}
const { workspaceId, count } = payload;
const license = await this.db.installedLicense.findUnique({
@@ -251,12 +234,8 @@ export class LicenseService implements OnModuleInit {
throw new Error('Timeout checking seat update result.');
}
@Cron(CronExpression.EVERY_10_MINUTES)
@Cron(CronExpression.EVERY_10_MINUTES, { disabled: !env.selfhosted })
async licensesHealthCheck() {
if (!this.config.isSelfhosted) {
return;
}
const licenses = await this.db.installedLicense.findMany({
where: {
validatedAt: {