mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-12-23 06:31:47 +03:00
e516e0db23
- [x] separates modules into `fundamental`, `core`, `plugins` - [x] optional modules with `@OptionalModule` decorator to install modules with requirements met(`requires`, `if`) - [x] `module.contributesTo` defines optional features that will be enabled if module registered - [x] `AFFiNE.plugins.use('payment', {})` to enable a optional/plugin module - [x] `PaymentModule` is the first plugin module - [x] GraphQLSchema will not be generated for non-included modules - [x] Frontend can use `ServerConfigType` query to detect which features are enabled - [x] override existing provider globally
219 lines
7.0 KiB
TypeScript
219 lines
7.0 KiB
TypeScript
import type { INestApplication } from '@nestjs/common';
|
|
import test from 'ava';
|
|
import request from 'supertest';
|
|
|
|
import { AppModule } from '../src/app.module';
|
|
import { FeatureManagementService, FeatureType } from '../src/core/features';
|
|
import { QuotaService, QuotaType } from '../src/core/quota';
|
|
import {
|
|
checkBlobSize,
|
|
collectAllBlobSizes,
|
|
createTestingApp,
|
|
createWorkspace,
|
|
getWorkspaceBlobsSize,
|
|
listBlobs,
|
|
setBlob,
|
|
signUp,
|
|
} from './utils';
|
|
|
|
const OneMB = 1024 * 1024;
|
|
|
|
let app: INestApplication;
|
|
let quota: QuotaService;
|
|
let feature: FeatureManagementService;
|
|
|
|
test.beforeEach(async () => {
|
|
const { app: testApp } = await createTestingApp({
|
|
imports: [AppModule],
|
|
});
|
|
|
|
app = testApp;
|
|
quota = app.get(QuotaService);
|
|
feature = app.get(FeatureManagementService);
|
|
});
|
|
|
|
test.afterEach.always(async () => {
|
|
await app.close();
|
|
});
|
|
|
|
test('should set blobs', async t => {
|
|
const u1 = await signUp(app, 'u1', 'u1@affine.pro', '1');
|
|
|
|
const workspace = await createWorkspace(app, u1.token.token);
|
|
|
|
const buffer1 = Buffer.from([0, 0]);
|
|
const hash1 = await setBlob(app, u1.token.token, workspace.id, buffer1);
|
|
const buffer2 = Buffer.from([0, 1]);
|
|
const hash2 = await setBlob(app, u1.token.token, workspace.id, buffer2);
|
|
|
|
const server = app.getHttpServer();
|
|
|
|
const response1 = await request(server)
|
|
.get(`/api/workspaces/${workspace.id}/blobs/${hash1}`)
|
|
.auth(u1.token.token, { type: 'bearer' })
|
|
.buffer();
|
|
|
|
t.deepEqual(response1.body, buffer1, 'failed to get blob');
|
|
|
|
const response2 = await request(server)
|
|
.get(`/api/workspaces/${workspace.id}/blobs/${hash2}`)
|
|
.auth(u1.token.token, { type: 'bearer' })
|
|
.buffer();
|
|
|
|
t.deepEqual(response2.body, buffer2, 'failed to get blob');
|
|
});
|
|
|
|
test('should list blobs', async t => {
|
|
const u1 = await signUp(app, 'u1', 'u1@affine.pro', '1');
|
|
|
|
const workspace = await createWorkspace(app, u1.token.token);
|
|
const blobs = await listBlobs(app, u1.token.token, workspace.id);
|
|
t.is(blobs.length, 0, 'failed to list blobs');
|
|
|
|
const buffer1 = Buffer.from([0, 0]);
|
|
const hash1 = await setBlob(app, u1.token.token, workspace.id, buffer1);
|
|
const buffer2 = Buffer.from([0, 1]);
|
|
const hash2 = await setBlob(app, u1.token.token, workspace.id, buffer2);
|
|
|
|
const ret = await listBlobs(app, u1.token.token, workspace.id);
|
|
t.is(ret.length, 2, 'failed to list blobs');
|
|
// list blob result is not ordered
|
|
t.deepEqual(ret.sort(), [hash1, hash2].sort());
|
|
});
|
|
|
|
test('should calc blobs size', async t => {
|
|
const u1 = await signUp(app, 'u1', 'u1@affine.pro', '1');
|
|
|
|
const workspace = await createWorkspace(app, u1.token.token);
|
|
|
|
const buffer1 = Buffer.from([0, 0]);
|
|
await setBlob(app, u1.token.token, workspace.id, buffer1);
|
|
const buffer2 = Buffer.from([0, 1]);
|
|
await setBlob(app, u1.token.token, workspace.id, buffer2);
|
|
|
|
const size = await getWorkspaceBlobsSize(app, u1.token.token, workspace.id);
|
|
t.is(size, 4, 'failed to collect blob sizes');
|
|
});
|
|
|
|
test('should calc all blobs size', async t => {
|
|
const u1 = await signUp(app, 'u1', 'u1@affine.pro', '1');
|
|
|
|
const workspace1 = await createWorkspace(app, u1.token.token);
|
|
|
|
const buffer1 = Buffer.from([0, 0]);
|
|
await setBlob(app, u1.token.token, workspace1.id, buffer1);
|
|
const buffer2 = Buffer.from([0, 1]);
|
|
await setBlob(app, u1.token.token, workspace1.id, buffer2);
|
|
|
|
const workspace2 = await createWorkspace(app, u1.token.token);
|
|
|
|
const buffer3 = Buffer.from([0, 0]);
|
|
await setBlob(app, u1.token.token, workspace2.id, buffer3);
|
|
const buffer4 = Buffer.from([0, 1]);
|
|
await setBlob(app, u1.token.token, workspace2.id, buffer4);
|
|
|
|
const size = await collectAllBlobSizes(app, u1.token.token);
|
|
t.is(size, 8, 'failed to collect all blob sizes');
|
|
|
|
const size1 = await checkBlobSize(
|
|
app,
|
|
u1.token.token,
|
|
workspace1.id,
|
|
10 * 1024 * 1024 * 1024 - 8
|
|
);
|
|
t.is(size1, 0, 'failed to check blob size');
|
|
|
|
const size2 = await checkBlobSize(
|
|
app,
|
|
u1.token.token,
|
|
workspace1.id,
|
|
10 * 1024 * 1024 * 1024 - 7
|
|
);
|
|
t.is(size2, -1, 'failed to check blob size');
|
|
});
|
|
|
|
test('should be able calc quota after switch plan', async t => {
|
|
const u1 = await signUp(app, 'darksky', 'darksky@affine.pro', '1');
|
|
|
|
const workspace1 = await createWorkspace(app, u1.token.token);
|
|
|
|
const buffer1 = Buffer.from([0, 0]);
|
|
await setBlob(app, u1.token.token, workspace1.id, buffer1);
|
|
const buffer2 = Buffer.from([0, 1]);
|
|
await setBlob(app, u1.token.token, workspace1.id, buffer2);
|
|
|
|
const workspace2 = await createWorkspace(app, u1.token.token);
|
|
|
|
const buffer3 = Buffer.from([0, 0]);
|
|
await setBlob(app, u1.token.token, workspace2.id, buffer3);
|
|
const buffer4 = Buffer.from([0, 1]);
|
|
await setBlob(app, u1.token.token, workspace2.id, buffer4);
|
|
|
|
const size1 = await checkBlobSize(
|
|
app,
|
|
u1.token.token,
|
|
workspace1.id,
|
|
10 * 1024 * 1024 * 1024 - 8
|
|
);
|
|
t.is(size1, 0, 'failed to check free plan blob size');
|
|
|
|
quota.switchUserQuota(u1.id, QuotaType.ProPlanV1);
|
|
|
|
const size2 = await checkBlobSize(
|
|
app,
|
|
u1.token.token,
|
|
workspace1.id,
|
|
100 * 1024 * 1024 * 1024 - 8
|
|
);
|
|
t.is(size2, 0, 'failed to check pro plan blob size');
|
|
});
|
|
|
|
test('should reject blob exceeded limit', async t => {
|
|
const u1 = await signUp(app, 'darksky', 'darksky@affine.pro', '1');
|
|
|
|
const workspace1 = await createWorkspace(app, u1.token.token);
|
|
await quota.switchUserQuota(u1.id, QuotaType.RestrictedPlanV1);
|
|
|
|
const buffer1 = Buffer.from(Array.from({ length: OneMB + 1 }, () => 0));
|
|
await t.throwsAsync(setBlob(app, u1.token.token, workspace1.id, buffer1));
|
|
|
|
await quota.switchUserQuota(u1.id, QuotaType.FreePlanV1);
|
|
|
|
const buffer2 = Buffer.from(Array.from({ length: OneMB + 1 }, () => 0));
|
|
await t.notThrowsAsync(setBlob(app, u1.token.token, workspace1.id, buffer2));
|
|
|
|
const buffer3 = Buffer.from(Array.from({ length: 100 * OneMB + 1 }, () => 0));
|
|
await t.throwsAsync(setBlob(app, u1.token.token, workspace1.id, buffer3));
|
|
});
|
|
|
|
test('should reject blob exceeded quota', async t => {
|
|
const u1 = await signUp(app, 'darksky', 'darksky@affine.pro', '1');
|
|
|
|
const workspace = await createWorkspace(app, u1.token.token);
|
|
await quota.switchUserQuota(u1.id, QuotaType.RestrictedPlanV1);
|
|
|
|
const buffer = Buffer.from(Array.from({ length: OneMB }, () => 0));
|
|
|
|
for (let i = 0; i < 10; i++) {
|
|
await t.notThrowsAsync(setBlob(app, u1.token.token, workspace.id, buffer));
|
|
}
|
|
|
|
await t.throwsAsync(setBlob(app, u1.token.token, workspace.id, buffer));
|
|
});
|
|
|
|
test('should accept blob even storage out of quota if workspace has unlimited feature', async t => {
|
|
const u1 = await signUp(app, 'darksky', 'darksky@affine.pro', '1');
|
|
|
|
const workspace = await createWorkspace(app, u1.token.token);
|
|
await quota.switchUserQuota(u1.id, QuotaType.RestrictedPlanV1);
|
|
feature.addWorkspaceFeatures(workspace.id, FeatureType.UnlimitedWorkspace);
|
|
|
|
const buffer = Buffer.from(Array.from({ length: OneMB }, () => 0));
|
|
|
|
for (let i = 0; i < 10; i++) {
|
|
await t.notThrowsAsync(setBlob(app, u1.token.token, workspace.id, buffer));
|
|
}
|
|
|
|
await t.notThrowsAsync(setBlob(app, u1.token.token, workspace.id, buffer));
|
|
});
|