mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-19 02:51:47 +08:00
refactor(server): standalone runtime module (#9120)
This commit is contained in:
@@ -19,6 +19,7 @@ import { MailModule } from './base/mailer';
|
|||||||
import { MetricsModule } from './base/metrics';
|
import { MetricsModule } from './base/metrics';
|
||||||
import { MutexModule } from './base/mutex';
|
import { MutexModule } from './base/mutex';
|
||||||
import { PrismaModule } from './base/prisma';
|
import { PrismaModule } from './base/prisma';
|
||||||
|
import { RuntimeModule } from './base/runtime';
|
||||||
import { StorageProviderModule } from './base/storage';
|
import { StorageProviderModule } from './base/storage';
|
||||||
import { RateLimiterModule } from './base/throttler';
|
import { RateLimiterModule } from './base/throttler';
|
||||||
import { WebSocketModule } from './base/websocket';
|
import { WebSocketModule } from './base/websocket';
|
||||||
@@ -39,6 +40,7 @@ import { ENABLED_PLUGINS } from './plugins/registry';
|
|||||||
|
|
||||||
export const FunctionalityModules = [
|
export const FunctionalityModules = [
|
||||||
ConfigModule.forRoot(),
|
ConfigModule.forRoot(),
|
||||||
|
RuntimeModule,
|
||||||
EventModule,
|
EventModule,
|
||||||
CacheModule,
|
CacheModule,
|
||||||
MutexModule,
|
MutexModule,
|
||||||
@@ -74,11 +76,13 @@ function filterOptionalModule(
|
|||||||
|
|
||||||
if (nonMetRequirements.length) {
|
if (nonMetRequirements.length) {
|
||||||
const name = 'module' in module ? module.module.name : module.name;
|
const name = 'module' in module ? module.module.name : module.name;
|
||||||
new Logger(name).warn(
|
if (!config.node.test) {
|
||||||
`${name} is not enabled because of the required configuration is not satisfied.`,
|
new Logger(name).warn(
|
||||||
'Unsatisfied configuration:',
|
`${name} is not enabled because of the required configuration is not satisfied.`,
|
||||||
...nonMetRequirements.map(config => ` AFFiNE.${config}`)
|
'Unsatisfied configuration:',
|
||||||
);
|
...nonMetRequirements.map(config => ` AFFiNE.${config}`)
|
||||||
|
);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { merge } from 'lodash-es';
|
|||||||
|
|
||||||
import { AFFiNEConfig } from './def';
|
import { AFFiNEConfig } from './def';
|
||||||
import { Config } from './provider';
|
import { Config } from './provider';
|
||||||
import { Runtime } from './runtime/service';
|
|
||||||
|
|
||||||
export * from './def';
|
export * from './def';
|
||||||
export * from './default';
|
export * from './default';
|
||||||
@@ -17,10 +16,10 @@ function createConfigProvider(
|
|||||||
): FactoryProvider<Config> {
|
): FactoryProvider<Config> {
|
||||||
return {
|
return {
|
||||||
provide: Config,
|
provide: Config,
|
||||||
useFactory: (runtime: Runtime) => {
|
useFactory: () => {
|
||||||
return Object.freeze(merge({}, globalThis.AFFiNE, override, { runtime }));
|
return Object.freeze(merge({}, globalThis.AFFiNE, override));
|
||||||
},
|
},
|
||||||
inject: [Runtime],
|
inject: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,10 +30,8 @@ export class ConfigModule {
|
|||||||
return {
|
return {
|
||||||
global: true,
|
global: true,
|
||||||
module: ConfigModule,
|
module: ConfigModule,
|
||||||
providers: [provider, Runtime],
|
providers: [provider],
|
||||||
exports: [provider],
|
exports: [provider],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Runtime };
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { ApplyType } from '../utils/types';
|
import { ApplyType } from '../utils/types';
|
||||||
import { AFFiNEConfig } from './def';
|
import { AFFiNEConfig } from './def';
|
||||||
import type { Runtime } from './runtime/service';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @example
|
* @example
|
||||||
@@ -14,6 +13,4 @@ import type { Runtime } from './runtime/service';
|
|||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
export class Config extends ApplyType<AFFiNEConfig>() {
|
export class Config extends ApplyType<AFFiNEConfig>() {}
|
||||||
runtime!: Runtime;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ export {
|
|||||||
OptionalModule,
|
OptionalModule,
|
||||||
} from './nestjs';
|
} from './nestjs';
|
||||||
export { type PrismaTransaction } from './prisma';
|
export { type PrismaTransaction } from './prisma';
|
||||||
|
export { Runtime } from './runtime';
|
||||||
export * from './storage';
|
export * from './storage';
|
||||||
export { type StorageProvider, StorageProviderFactory } from './storage';
|
export { type StorageProvider, StorageProviderFactory } from './storage';
|
||||||
export { CloudThrottlerGuard, SkipThrottle, Throttle } from './throttler';
|
export { CloudThrottlerGuard, SkipThrottle, Throttle } from './throttler';
|
||||||
|
|||||||
+6
-6
@@ -1,10 +1,10 @@
|
|||||||
import { OnEvent } from '../../event';
|
import { FlattenedAppRuntimeConfig } from '../config/types';
|
||||||
import { Payload } from '../../event/def';
|
import { OnEvent } from '../event';
|
||||||
import { FlattenedAppRuntimeConfig } from '../types';
|
import { Payload } from '../event/def';
|
||||||
|
|
||||||
declare module '../../event/def' {
|
declare module '../event/def' {
|
||||||
interface EventDefinitions {
|
interface EventDefinitions {
|
||||||
runtimeConfig: {
|
runtime: {
|
||||||
[K in keyof FlattenedAppRuntimeConfig]: {
|
[K in keyof FlattenedAppRuntimeConfig]: {
|
||||||
changed: Payload<FlattenedAppRuntimeConfig[K]>;
|
changed: Payload<FlattenedAppRuntimeConfig[K]>;
|
||||||
};
|
};
|
||||||
@@ -18,5 +18,5 @@ declare module '../../event/def' {
|
|||||||
export const OnRuntimeConfigChange_DO_NOT_USE = (
|
export const OnRuntimeConfigChange_DO_NOT_USE = (
|
||||||
nameWithModule: keyof FlattenedAppRuntimeConfig
|
nameWithModule: keyof FlattenedAppRuntimeConfig
|
||||||
) => {
|
) => {
|
||||||
return OnEvent(`runtimeConfig.${nameWithModule}.changed`);
|
return OnEvent(`runtime.${nameWithModule}.changed`);
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { Global, Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { Runtime } from './service';
|
||||||
|
|
||||||
|
@Global()
|
||||||
|
@Module({
|
||||||
|
providers: [Runtime],
|
||||||
|
exports: [Runtime],
|
||||||
|
})
|
||||||
|
export class RuntimeModule {}
|
||||||
|
export { Runtime };
|
||||||
+8
-5
@@ -8,11 +8,14 @@ import {
|
|||||||
import { PrismaClient } from '@prisma/client';
|
import { PrismaClient } from '@prisma/client';
|
||||||
import { difference, keyBy } from 'lodash-es';
|
import { difference, keyBy } from 'lodash-es';
|
||||||
|
|
||||||
import { Cache } from '../../cache';
|
import { Cache } from '../cache';
|
||||||
import { InvalidRuntimeConfigType, RuntimeConfigNotFound } from '../../error';
|
import { defaultRuntimeConfig, runtimeConfigType } from '../config/register';
|
||||||
import { defer } from '../../utils/promise';
|
import {
|
||||||
import { defaultRuntimeConfig, runtimeConfigType } from '../register';
|
AppRuntimeConfigModules,
|
||||||
import { AppRuntimeConfigModules, FlattenedAppRuntimeConfig } from '../types';
|
FlattenedAppRuntimeConfig,
|
||||||
|
} from '../config/types';
|
||||||
|
import { InvalidRuntimeConfigType, RuntimeConfigNotFound } from '../error';
|
||||||
|
import { defer } from '../utils/promise';
|
||||||
|
|
||||||
function validateConfigType<K extends keyof FlattenedAppRuntimeConfig>(
|
function validateConfigType<K extends keyof FlattenedAppRuntimeConfig>(
|
||||||
key: K,
|
key: K,
|
||||||
@@ -20,6 +20,7 @@ import {
|
|||||||
InternalServerError,
|
InternalServerError,
|
||||||
InvalidEmail,
|
InvalidEmail,
|
||||||
InvalidEmailToken,
|
InvalidEmailToken,
|
||||||
|
Runtime,
|
||||||
SignUpForbidden,
|
SignUpForbidden,
|
||||||
Throttle,
|
Throttle,
|
||||||
URLHelper,
|
URLHelper,
|
||||||
@@ -57,7 +58,8 @@ export class AuthController {
|
|||||||
private readonly auth: AuthService,
|
private readonly auth: AuthService,
|
||||||
private readonly user: UserService,
|
private readonly user: UserService,
|
||||||
private readonly token: TokenService,
|
private readonly token: TokenService,
|
||||||
private readonly config: Config
|
private readonly config: Config,
|
||||||
|
private readonly runtime: Runtime
|
||||||
) {
|
) {
|
||||||
if (config.node.dev) {
|
if (config.node.dev) {
|
||||||
// set DNS servers in dev mode
|
// set DNS servers in dev mode
|
||||||
@@ -159,12 +161,12 @@ export class AuthController {
|
|||||||
// send email magic link
|
// send email magic link
|
||||||
const user = await this.user.findUserByEmail(email);
|
const user = await this.user.findUserByEmail(email);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
const allowSignup = await this.config.runtime.fetch('auth/allowSignup');
|
const allowSignup = await this.runtime.fetch('auth/allowSignup');
|
||||||
if (!allowSignup) {
|
if (!allowSignup) {
|
||||||
throw new SignUpForbidden();
|
throw new SignUpForbidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
const requireEmailDomainVerification = await this.config.runtime.fetch(
|
const requireEmailDomainVerification = await this.runtime.fetch(
|
||||||
'auth/requireEmailDomainVerification'
|
'auth/requireEmailDomainVerification'
|
||||||
);
|
);
|
||||||
if (requireEmailDomainVerification) {
|
if (requireEmailDomainVerification) {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {
|
|||||||
import { RuntimeConfig, RuntimeConfigType } from '@prisma/client';
|
import { RuntimeConfig, RuntimeConfigType } from '@prisma/client';
|
||||||
import { GraphQLJSON, GraphQLJSONObject } from 'graphql-scalars';
|
import { GraphQLJSON, GraphQLJSONObject } from 'graphql-scalars';
|
||||||
|
|
||||||
import { Config, URLHelper } from '../../base';
|
import { Config, Runtime, URLHelper } from '../../base';
|
||||||
import { Public } from '../auth';
|
import { Public } from '../auth';
|
||||||
import { Admin } from '../common';
|
import { Admin } from '../common';
|
||||||
import { FeatureType } from '../features';
|
import { FeatureType } from '../features';
|
||||||
@@ -76,6 +76,7 @@ export class ServerFlagsType implements ServerFlags {
|
|||||||
export class ServerConfigResolver {
|
export class ServerConfigResolver {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly config: Config,
|
private readonly config: Config,
|
||||||
|
private readonly runtime: Runtime,
|
||||||
private readonly url: URLHelper,
|
private readonly url: URLHelper,
|
||||||
private readonly server: ServerService
|
private readonly server: ServerService
|
||||||
) {}
|
) {}
|
||||||
@@ -103,7 +104,7 @@ export class ServerConfigResolver {
|
|||||||
description: 'credentials requirement',
|
description: 'credentials requirement',
|
||||||
})
|
})
|
||||||
async credentialsRequirement() {
|
async credentialsRequirement() {
|
||||||
const config = await this.config.runtime.fetchAll({
|
const config = await this.runtime.fetchAll({
|
||||||
'auth/password.max': true,
|
'auth/password.max': true,
|
||||||
'auth/password.min': true,
|
'auth/password.min': true,
|
||||||
});
|
});
|
||||||
@@ -120,7 +121,7 @@ export class ServerConfigResolver {
|
|||||||
description: 'server flags',
|
description: 'server flags',
|
||||||
})
|
})
|
||||||
async flags(): Promise<ServerFlagsType> {
|
async flags(): Promise<ServerFlagsType> {
|
||||||
const records = await this.config.runtime.list('flags');
|
const records = await this.runtime.list('flags');
|
||||||
|
|
||||||
return records.reduce((flags, record) => {
|
return records.reduce((flags, record) => {
|
||||||
flags[record.key as keyof ServerFlagsType] = record.value as any;
|
flags[record.key as keyof ServerFlagsType] = record.value as any;
|
||||||
@@ -184,13 +185,13 @@ interface ServerDatabaseConfig {
|
|||||||
@Admin()
|
@Admin()
|
||||||
@Resolver(() => ServerRuntimeConfigType)
|
@Resolver(() => ServerRuntimeConfigType)
|
||||||
export class ServerRuntimeConfigResolver {
|
export class ServerRuntimeConfigResolver {
|
||||||
constructor(private readonly config: Config) {}
|
constructor(private readonly runtime: Runtime) {}
|
||||||
|
|
||||||
@Query(() => [ServerRuntimeConfigType], {
|
@Query(() => [ServerRuntimeConfigType], {
|
||||||
description: 'get all server runtime configurable settings',
|
description: 'get all server runtime configurable settings',
|
||||||
})
|
})
|
||||||
serverRuntimeConfig(): Promise<ServerRuntimeConfigType[]> {
|
serverRuntimeConfig(): Promise<ServerRuntimeConfigType[]> {
|
||||||
return this.config.runtime.list();
|
return this.runtime.list();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mutation(() => ServerRuntimeConfigType, {
|
@Mutation(() => ServerRuntimeConfigType, {
|
||||||
@@ -200,7 +201,7 @@ export class ServerRuntimeConfigResolver {
|
|||||||
@Args('id') id: string,
|
@Args('id') id: string,
|
||||||
@Args({ type: () => GraphQLJSON, name: 'value' }) value: any
|
@Args({ type: () => GraphQLJSON, name: 'value' }) value: any
|
||||||
): Promise<ServerRuntimeConfigType> {
|
): Promise<ServerRuntimeConfigType> {
|
||||||
return await this.config.runtime.set(id as any, value);
|
return await this.runtime.set(id as any, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mutation(() => [ServerRuntimeConfigType], {
|
@Mutation(() => [ServerRuntimeConfigType], {
|
||||||
@@ -211,7 +212,7 @@ export class ServerRuntimeConfigResolver {
|
|||||||
): Promise<ServerRuntimeConfigType[]> {
|
): Promise<ServerRuntimeConfigType[]> {
|
||||||
const keys = Object.keys(updates);
|
const keys = Object.keys(updates);
|
||||||
const results = await Promise.all(
|
const results = await Promise.all(
|
||||||
keys.map(key => this.config.runtime.set(key as any, updates[key]))
|
keys.map(key => this.runtime.set(key as any, updates[key]))
|
||||||
);
|
);
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
Config,
|
Config,
|
||||||
mergeUpdatesInApplyWay as yotcoMergeUpdates,
|
mergeUpdatesInApplyWay as yotcoMergeUpdates,
|
||||||
metrics,
|
metrics,
|
||||||
|
Runtime,
|
||||||
} from '../../base';
|
} from '../../base';
|
||||||
import { PermissionService } from '../permission';
|
import { PermissionService } from '../permission';
|
||||||
import { QuotaService } from '../quota';
|
import { QuotaService } from '../quota';
|
||||||
@@ -35,6 +36,7 @@ export class DocStorageOptions implements IDocStorageOptions {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly config: Config,
|
private readonly config: Config,
|
||||||
|
private readonly runtime: Runtime,
|
||||||
private readonly permission: PermissionService,
|
private readonly permission: PermissionService,
|
||||||
private readonly quota: QuotaService
|
private readonly quota: QuotaService
|
||||||
) {}
|
) {}
|
||||||
@@ -43,9 +45,7 @@ export class DocStorageOptions implements IDocStorageOptions {
|
|||||||
const doc = await this.recoverDoc(updates);
|
const doc = await this.recoverDoc(updates);
|
||||||
const yjsResult = Buffer.from(Y.encodeStateAsUpdate(doc));
|
const yjsResult = Buffer.from(Y.encodeStateAsUpdate(doc));
|
||||||
|
|
||||||
const useYocto = await this.config.runtime.fetch(
|
const useYocto = await this.runtime.fetch('doc/experimentalMergeWithYOcto');
|
||||||
'doc/experimentalMergeWithYOcto'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (useYocto) {
|
if (useYocto) {
|
||||||
metrics.jwst.counter('codec_merge_counter').add(1);
|
metrics.jwst.counter('codec_merge_counter').add(1);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
|
||||||
import { Config, type EventPayload, OnEvent } from '../../base';
|
import { type EventPayload, OnEvent, Runtime } from '../../base';
|
||||||
import { UserService } from '../user/service';
|
import { UserService } from '../user/service';
|
||||||
import { FeatureService } from './service';
|
import { FeatureService } from './service';
|
||||||
import { FeatureType } from './types';
|
import { FeatureType } from './types';
|
||||||
@@ -19,7 +19,7 @@ export class FeatureManagementService {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly feature: FeatureService,
|
private readonly feature: FeatureService,
|
||||||
private readonly user: UserService,
|
private readonly user: UserService,
|
||||||
private readonly config: Config
|
private readonly runtime: Runtime
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
// ======== Admin ========
|
// ======== Admin ========
|
||||||
@@ -95,7 +95,7 @@ export class FeatureManagementService {
|
|||||||
email: string,
|
email: string,
|
||||||
type: EarlyAccessType = EarlyAccessType.App
|
type: EarlyAccessType = EarlyAccessType.App
|
||||||
) {
|
) {
|
||||||
const earlyAccessControlEnabled = await this.config.runtime.fetch(
|
const earlyAccessControlEnabled = await this.runtime.fetch(
|
||||||
'flags/earlyAccessControl'
|
'flags/earlyAccessControl'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ import { Socket } from 'socket.io';
|
|||||||
import {
|
import {
|
||||||
AlreadyInSpace,
|
AlreadyInSpace,
|
||||||
CallMetric,
|
CallMetric,
|
||||||
Config,
|
|
||||||
DocNotFound,
|
DocNotFound,
|
||||||
GatewayErrorWrapper,
|
GatewayErrorWrapper,
|
||||||
metrics,
|
metrics,
|
||||||
NotInSpace,
|
NotInSpace,
|
||||||
|
Runtime,
|
||||||
SpaceAccessDenied,
|
SpaceAccessDenied,
|
||||||
VersionRejected,
|
VersionRejected,
|
||||||
} from '../../base';
|
} from '../../base';
|
||||||
@@ -139,7 +139,7 @@ export class SpaceSyncGateway
|
|||||||
private connectionCount = 0;
|
private connectionCount = 0;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly config: Config,
|
private readonly runtime: Runtime,
|
||||||
private readonly permissions: PermissionService,
|
private readonly permissions: PermissionService,
|
||||||
private readonly workspace: PgWorkspaceDocStorageAdapter,
|
private readonly workspace: PgWorkspaceDocStorageAdapter,
|
||||||
private readonly userspace: PgUserspaceDocStorageAdapter
|
private readonly userspace: PgUserspaceDocStorageAdapter
|
||||||
@@ -175,7 +175,7 @@ export class SpaceSyncGateway
|
|||||||
}
|
}
|
||||||
|
|
||||||
async assertVersion(client: Socket, version?: string) {
|
async assertVersion(client: Socket, version?: string) {
|
||||||
const shouldCheckClientVersion = await this.config.runtime.fetch(
|
const shouldCheckClientVersion = await this.runtime.fetch(
|
||||||
'flags/syncClientVersionCheck'
|
'flags/syncClientVersionCheck'
|
||||||
);
|
);
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
EventEmitter,
|
EventEmitter,
|
||||||
type EventPayload,
|
type EventPayload,
|
||||||
OnEvent,
|
OnEvent,
|
||||||
|
Runtime,
|
||||||
WrongSignInCredentials,
|
WrongSignInCredentials,
|
||||||
WrongSignInMethod,
|
WrongSignInMethod,
|
||||||
} from '../../base';
|
} from '../../base';
|
||||||
@@ -33,6 +34,7 @@ export class UserService {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly config: Config,
|
private readonly config: Config,
|
||||||
|
private readonly runtime: Runtime,
|
||||||
private readonly crypto: CryptoHelper,
|
private readonly crypto: CryptoHelper,
|
||||||
private readonly prisma: PrismaClient,
|
private readonly prisma: PrismaClient,
|
||||||
private readonly emitter: EventEmitter,
|
private readonly emitter: EventEmitter,
|
||||||
@@ -60,7 +62,7 @@ export class UserService {
|
|||||||
validators.assertValidEmail(data.email);
|
validators.assertValidEmail(data.email);
|
||||||
|
|
||||||
if (data.password) {
|
if (data.password) {
|
||||||
const config = await this.config.runtime.fetchAll({
|
const config = await this.runtime.fetchAll({
|
||||||
'auth/password.max': true,
|
'auth/password.max': true,
|
||||||
'auth/password.min': true,
|
'auth/password.min': true,
|
||||||
});
|
});
|
||||||
@@ -242,7 +244,7 @@ export class UserService {
|
|||||||
select: Prisma.UserSelect = this.defaultUserSelect
|
select: Prisma.UserSelect = this.defaultUserSelect
|
||||||
) {
|
) {
|
||||||
if (data.password) {
|
if (data.password) {
|
||||||
const config = await this.config.runtime.fetchAll({
|
const config = await this.runtime.fetchAll({
|
||||||
'auth/password.max': true,
|
'auth/password.max': true,
|
||||||
'auth/password.min': true,
|
'auth/password.min': true,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import type {
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Config,
|
|
||||||
getRequestResponseFromContext,
|
getRequestResponseFromContext,
|
||||||
GuardProvider,
|
GuardProvider,
|
||||||
|
Runtime,
|
||||||
} from '../../base';
|
} from '../../base';
|
||||||
import { CaptchaService } from './service';
|
import { CaptchaService } from './service';
|
||||||
|
|
||||||
@@ -21,13 +21,13 @@ export class CaptchaGuardProvider
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly captcha: CaptchaService,
|
private readonly captcha: CaptchaService,
|
||||||
private readonly config: Config
|
private readonly runtime: Runtime
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
async canActivate(context: ExecutionContext) {
|
async canActivate(context: ExecutionContext) {
|
||||||
if (!(await this.config.runtime.fetch('plugins.captcha/enable'))) {
|
if (!(await this.runtime.fetch('plugins.captcha/enable'))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import Stripe from 'stripe';
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Config,
|
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
InternalServerError,
|
InternalServerError,
|
||||||
InvalidCheckoutParameters,
|
InvalidCheckoutParameters,
|
||||||
|
Runtime,
|
||||||
SubscriptionAlreadyExists,
|
SubscriptionAlreadyExists,
|
||||||
SubscriptionPlanNotFound,
|
SubscriptionPlanNotFound,
|
||||||
URLHelper,
|
URLHelper,
|
||||||
@@ -56,7 +56,7 @@ export class UserSubscriptionManager extends SubscriptionManager {
|
|||||||
constructor(
|
constructor(
|
||||||
stripe: Stripe,
|
stripe: Stripe,
|
||||||
db: PrismaClient,
|
db: PrismaClient,
|
||||||
private readonly config: Config,
|
private readonly runtime: Runtime,
|
||||||
private readonly feature: FeatureManagementService,
|
private readonly feature: FeatureManagementService,
|
||||||
private readonly event: EventEmitter,
|
private readonly event: EventEmitter,
|
||||||
private readonly url: URLHelper
|
private readonly url: URLHelper
|
||||||
@@ -617,7 +617,7 @@ export class UserSubscriptionManager extends SubscriptionManager {
|
|||||||
{ proEarlyAccess, proSubscribed, onetime }: PriceStrategyStatus
|
{ proEarlyAccess, proSubscribed, onetime }: PriceStrategyStatus
|
||||||
) {
|
) {
|
||||||
if (lookupKey.recurring === SubscriptionRecurring.Lifetime) {
|
if (lookupKey.recurring === SubscriptionRecurring.Lifetime) {
|
||||||
return this.config.runtime.fetch('plugins.payment/showLifetimePrice');
|
return this.runtime.fetch('plugins.payment/showLifetimePrice');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lookupKey.variant === SubscriptionVariant.Onetime) {
|
if (lookupKey.variant === SubscriptionVariant.Onetime) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { INestApplication } from '@nestjs/common';
|
|||||||
import type { TestFn } from 'ava';
|
import type { TestFn } from 'ava';
|
||||||
import ava from 'ava';
|
import ava from 'ava';
|
||||||
|
|
||||||
import { Config, ConfigModule } from '../src/base/config';
|
import { Runtime } from '../src/base';
|
||||||
import { AuthService } from '../src/core/auth/service';
|
import { AuthService } from '../src/core/auth/service';
|
||||||
import {
|
import {
|
||||||
FeatureManagementService,
|
FeatureManagementService,
|
||||||
@@ -26,15 +26,7 @@ const test = ava as TestFn<{
|
|||||||
|
|
||||||
test.beforeEach(async t => {
|
test.beforeEach(async t => {
|
||||||
const { app } = await createTestingApp({
|
const { app } = await createTestingApp({
|
||||||
imports: [
|
imports: [FeatureModule],
|
||||||
ConfigModule.forRoot({
|
|
||||||
server: {
|
|
||||||
host: 'example.org',
|
|
||||||
https: true,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
FeatureModule,
|
|
||||||
],
|
|
||||||
providers: [WorkspaceResolver],
|
providers: [WorkspaceResolver],
|
||||||
tapModule: module => {
|
tapModule: module => {
|
||||||
module
|
module
|
||||||
@@ -43,8 +35,8 @@ test.beforeEach(async t => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const config = app.get(Config);
|
const runtime = app.get(Runtime);
|
||||||
await config.runtime.set('flags/earlyAccessControl', true);
|
await runtime.set('flags/earlyAccessControl', true);
|
||||||
t.context.app = app;
|
t.context.app = app;
|
||||||
t.context.auth = app.get(AuthService);
|
t.context.auth = app.get(AuthService);
|
||||||
t.context.feature = app.get(FeatureService);
|
t.context.feature = app.get(FeatureService);
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import Sinon from 'sinon';
|
|||||||
import Stripe from 'stripe';
|
import Stripe from 'stripe';
|
||||||
|
|
||||||
import { AppModule } from '../../src/app.module';
|
import { AppModule } from '../../src/app.module';
|
||||||
import { EventEmitter } from '../../src/base';
|
import { EventEmitter, Runtime } from '../../src/base';
|
||||||
import { Config, ConfigModule, Runtime } from '../../src/base/config';
|
import { ConfigModule } from '../../src/base/config';
|
||||||
import { CurrentUser } from '../../src/core/auth';
|
import { CurrentUser } from '../../src/core/auth';
|
||||||
import { AuthService } from '../../src/core/auth/service';
|
import { AuthService } from '../../src/core/auth/service';
|
||||||
import {
|
import {
|
||||||
@@ -543,8 +543,8 @@ test('should get correct pro plan price for checking out', async t => {
|
|||||||
// any user, lifetime recurring
|
// any user, lifetime recurring
|
||||||
{
|
{
|
||||||
feature.isEarlyAccessUser.resolves(false);
|
feature.isEarlyAccessUser.resolves(false);
|
||||||
const config = app.get(Config);
|
const runtime = app.get(Runtime);
|
||||||
await config.runtime.set('plugins.payment/showLifetimePrice', true);
|
await runtime.set('plugins.payment/showLifetimePrice', true);
|
||||||
|
|
||||||
await service.checkout(
|
await service.checkout(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import type { Response } from 'supertest';
|
|||||||
import supertest from 'supertest';
|
import supertest from 'supertest';
|
||||||
|
|
||||||
import { AppModule, FunctionalityModules } from '../../src/app.module';
|
import { AppModule, FunctionalityModules } from '../../src/app.module';
|
||||||
import { Config, GlobalExceptionFilter } from '../../src/base';
|
import { GlobalExceptionFilter, Runtime } from '../../src/base';
|
||||||
import { GqlModule } from '../../src/base/graphql';
|
import { GqlModule } from '../../src/base/graphql';
|
||||||
import { AuthGuard, AuthModule } from '../../src/core/auth';
|
import { AuthGuard, AuthModule } from '../../src/core/auth';
|
||||||
import { UserFeaturesInit1698652531198 } from '../../src/data/migrations/1698652531198-user-features-init';
|
import { UserFeaturesInit1698652531198 } from '../../src/data/migrations/1698652531198-user-features-init';
|
||||||
@@ -111,9 +111,9 @@ export async function createTestingModule(
|
|||||||
if (init) {
|
if (init) {
|
||||||
await m.init();
|
await m.init();
|
||||||
|
|
||||||
const config = m.get(Config);
|
const runtime = m.get(Runtime);
|
||||||
// by pass password min length validation
|
// by pass password min length validation
|
||||||
await config.runtime.set('auth/password.min', 1);
|
await runtime.set('auth/password.min', 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
@@ -145,9 +145,9 @@ export async function createTestingApp(moduleDef: TestingModuleMeatdata = {}) {
|
|||||||
|
|
||||||
await app.init();
|
await app.init();
|
||||||
|
|
||||||
const config = app.get(Config);
|
const runtime = app.get(Runtime);
|
||||||
// by pass password min length validation
|
// by pass password min length validation
|
||||||
await config.runtime.set('auth/password.min', 1);
|
await runtime.set('auth/password.min', 1);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
module: m,
|
module: m,
|
||||||
|
|||||||
Reference in New Issue
Block a user