mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 12:55:00 +00:00
feat(server): align pro plan for free in selfhost (#9973)
close AF-2099
This commit is contained in:
@@ -42,3 +42,16 @@ Generated by [AVA](https://avajs.dev).
|
||||
name: 'Free',
|
||||
storageQuota: 10737418240,
|
||||
}
|
||||
|
||||
## should use pro plan as free for selfhost instance
|
||||
|
||||
> use pro plan as free plan for selfhosted instance
|
||||
|
||||
{
|
||||
blobLimit: 104857600,
|
||||
copilotActionLimit: 10,
|
||||
historyPeriod: 2592000000,
|
||||
memberLimit: 10,
|
||||
name: 'Pro',
|
||||
storageQuota: 107374182400,
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,8 @@
|
||||
import { User } from '@prisma/client';
|
||||
import ava, { TestFn } from 'ava';
|
||||
|
||||
import { FeatureType, UserFeatureModel, UserModel } from '../../models';
|
||||
import { ConfigModule } from '../../base/config';
|
||||
import { FeatureType, Models, UserFeatureModel, UserModel } from '../../models';
|
||||
import { createTestingModule, TestingModule } from '../utils';
|
||||
|
||||
interface Context {
|
||||
@@ -123,3 +124,25 @@ test('should not switch user quota if the new quota is the same as the current o
|
||||
|
||||
t.not(quota?.reason, 'test not switch');
|
||||
});
|
||||
|
||||
test('should use pro plan as free for selfhost instance', async t => {
|
||||
await using module = await createTestingModule({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
isSelfhosted: true,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
const models = module.get(Models);
|
||||
const u1 = await models.user.create({
|
||||
email: 'u1@affine.pro',
|
||||
registered: true,
|
||||
});
|
||||
|
||||
const quota = await models.userFeature.getQuota(u1.id);
|
||||
t.snapshot(
|
||||
quota?.configs,
|
||||
'use pro plan as free plan for selfhosted instance'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -90,6 +90,7 @@ test('should get feature if extra fields exist in feature config', async t => {
|
||||
test('should create feature', async t => {
|
||||
const { feature } = t.context;
|
||||
|
||||
// @ts-expect-error internal
|
||||
const newFeature = await feature.upsert(
|
||||
'new_feature' as any,
|
||||
{},
|
||||
@@ -104,6 +105,7 @@ test('should update feature', async t => {
|
||||
const { feature } = t.context;
|
||||
const freePlanFeature = await feature.get('free_plan_v1');
|
||||
|
||||
// @ts-expect-error internal
|
||||
const newFreePlanFeature = await feature.upsert(
|
||||
'free_plan_v1',
|
||||
{
|
||||
@@ -123,6 +125,7 @@ test('should update feature', async t => {
|
||||
test('should throw if feature config is invalid when updating', async t => {
|
||||
const { feature } = t.context;
|
||||
await t.throwsAsync(
|
||||
// @ts-expect-error internal
|
||||
feature.upsert('free_plan_v1', {} as any, FeatureType.Quota, 1),
|
||||
{
|
||||
message: 'Invalid feature config for free_plan_v1',
|
||||
|
||||
@@ -52,10 +52,12 @@ const initTestingDB = async (ref: ModuleRef) => {
|
||||
|
||||
export type TestingModule = BaseTestingModule & {
|
||||
initTestingDB(): Promise<void>;
|
||||
[Symbol.asyncDispose](): Promise<void>;
|
||||
};
|
||||
|
||||
export type TestingApp = INestApplication & {
|
||||
initTestingDB(): Promise<void>;
|
||||
[Symbol.asyncDispose](): Promise<void>;
|
||||
};
|
||||
|
||||
function dedupeModules(modules: NonNullable<ModuleMetadata['imports']>) {
|
||||
@@ -83,7 +85,7 @@ class MockResolver {
|
||||
export async function createTestingModule(
|
||||
moduleDef: TestingModuleMeatdata = {},
|
||||
autoInitialize = true
|
||||
) {
|
||||
): Promise<TestingModule> {
|
||||
// setting up
|
||||
let imports = moduleDef.imports ?? [];
|
||||
imports =
|
||||
@@ -129,6 +131,9 @@ export async function createTestingModule(
|
||||
// by pass password min length validation
|
||||
await runtime.set('auth/password.min', 1);
|
||||
};
|
||||
testingModule[Symbol.asyncDispose] = async () => {
|
||||
await m.close();
|
||||
};
|
||||
|
||||
if (autoInitialize) {
|
||||
await testingModule.initTestingDB();
|
||||
@@ -138,7 +143,9 @@ export async function createTestingModule(
|
||||
return testingModule;
|
||||
}
|
||||
|
||||
export async function createTestingApp(moduleDef: TestingModuleMeatdata = {}) {
|
||||
export async function createTestingApp(
|
||||
moduleDef: TestingModuleMeatdata = {}
|
||||
): Promise<{ module: TestingModule; app: TestingApp }> {
|
||||
const m = await createTestingModule(moduleDef, false);
|
||||
|
||||
const app = m.createNestApplication({
|
||||
@@ -169,7 +176,10 @@ export async function createTestingApp(moduleDef: TestingModuleMeatdata = {}) {
|
||||
await app.init();
|
||||
|
||||
app.initTestingDB = m.initTestingDB.bind(m);
|
||||
|
||||
app[Symbol.asyncDispose] = async () => {
|
||||
await m[Symbol.asyncDispose]();
|
||||
await app.close();
|
||||
};
|
||||
return {
|
||||
module: m,
|
||||
app: app,
|
||||
|
||||
Reference in New Issue
Block a user