mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-19 02:56:23 +08:00
feat(server): entitlement based model (#14996)
#### PR Dependency Tree * **PR #14996** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Admin mutations to grant/revoke commercial entitlements. * New Doc comment-update permission. * Realtime user/workspace quota-state endpoints and live-update rooms. * **Bug Fixes** * More accurate readable-doc filtering and permission evaluation. * **Refactor** * Workspace feature management moved to entitlement-based model; permission and quota pipelines redesigned. * Admin workspace UI now edits flags only (feature toggles removed). * **Tests** * Extensive new and updated tests for permissions, entitlements, quota, projection, and backfills. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14996?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -15,6 +15,9 @@ const workspace = await module.create(Mockers.Workspace, {
|
||||
owner,
|
||||
});
|
||||
|
||||
const waitNextMillisecond = () =>
|
||||
new Promise(resolve => setTimeout(resolve, 1));
|
||||
|
||||
test.after.always(async () => {
|
||||
await module.close();
|
||||
});
|
||||
@@ -77,7 +80,6 @@ test('should get a comment', async t => {
|
||||
docId,
|
||||
userId: owner.id,
|
||||
});
|
||||
|
||||
const comment2 = await models.comment.get(comment1.id);
|
||||
t.deepEqual(comment2, comment1);
|
||||
t.deepEqual(comment2?.content, {
|
||||
@@ -146,7 +148,7 @@ test('should resolve a comment', async t => {
|
||||
docId,
|
||||
userId: owner.id,
|
||||
});
|
||||
|
||||
await waitNextMillisecond();
|
||||
const comment2 = await models.comment.resolve({
|
||||
id: comment.id,
|
||||
resolved: true,
|
||||
@@ -158,6 +160,7 @@ test('should resolve a comment', async t => {
|
||||
// updatedAt should be changed
|
||||
t.true(comment3!.updatedAt.getTime() > comment3!.createdAt.getTime());
|
||||
|
||||
await waitNextMillisecond();
|
||||
const comment4 = await models.comment.resolve({
|
||||
id: comment.id,
|
||||
resolved: false,
|
||||
@@ -272,6 +275,7 @@ test('should update a reply', async t => {
|
||||
commentId: comment.id,
|
||||
});
|
||||
|
||||
await waitNextMillisecond();
|
||||
const reply2 = await models.comment.updateReply({
|
||||
id: reply.id,
|
||||
content: {
|
||||
@@ -322,6 +326,7 @@ test('should list comments with replies', async t => {
|
||||
userId: owner.id,
|
||||
});
|
||||
|
||||
await waitNextMillisecond();
|
||||
const comment2 = await models.comment.create({
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
@@ -342,6 +347,7 @@ test('should list comments with replies', async t => {
|
||||
userId: owner.id,
|
||||
});
|
||||
|
||||
await waitNextMillisecond();
|
||||
const reply1 = await models.comment.createReply({
|
||||
userId: owner.id,
|
||||
content: {
|
||||
@@ -351,6 +357,7 @@ test('should list comments with replies', async t => {
|
||||
commentId: comment1.id,
|
||||
});
|
||||
|
||||
await waitNextMillisecond();
|
||||
const reply2 = await models.comment.createReply({
|
||||
userId: owner.id,
|
||||
content: {
|
||||
@@ -421,7 +428,9 @@ test('should list changes', async t => {
|
||||
docId,
|
||||
userId: owner.id,
|
||||
});
|
||||
const comment1Cursor = comment1.updatedAt;
|
||||
|
||||
await waitNextMillisecond();
|
||||
const comment2 = await models.comment.create({
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
@@ -432,6 +441,7 @@ test('should list changes', async t => {
|
||||
userId: owner.id,
|
||||
});
|
||||
|
||||
await waitNextMillisecond();
|
||||
const reply1 = await models.comment.createReply({
|
||||
userId: owner.id,
|
||||
content: {
|
||||
@@ -441,6 +451,7 @@ test('should list changes', async t => {
|
||||
commentId: comment1.id,
|
||||
});
|
||||
|
||||
await waitNextMillisecond();
|
||||
const reply2 = await models.comment.createReply({
|
||||
userId: owner.id,
|
||||
content: {
|
||||
@@ -465,7 +476,7 @@ test('should list changes', async t => {
|
||||
t.is((changes1[2].item as Reply).commentId, comment1.id);
|
||||
|
||||
const changes2 = await models.comment.listChanges(workspace.id, docId, {
|
||||
commentUpdatedAt: comment1.updatedAt,
|
||||
commentUpdatedAt: comment1Cursor,
|
||||
replyUpdatedAt: reply1.updatedAt,
|
||||
});
|
||||
t.is(changes2.length, 2);
|
||||
@@ -476,6 +487,7 @@ test('should list changes', async t => {
|
||||
t.is(changes2[1].commentId, comment1.id);
|
||||
|
||||
// update comment1
|
||||
await waitNextMillisecond();
|
||||
const comment1Updated = await models.comment.update({
|
||||
id: comment1.id,
|
||||
content: {
|
||||
@@ -493,8 +505,10 @@ test('should list changes', async t => {
|
||||
t.is(changes3[0].id, comment1Updated.id);
|
||||
|
||||
// delete comment1 and reply1, update reply2
|
||||
await waitNextMillisecond();
|
||||
await models.comment.delete(comment1.id);
|
||||
await models.comment.deleteReply(reply1.id);
|
||||
await waitNextMillisecond();
|
||||
await models.comment.updateReply({
|
||||
id: reply2.id,
|
||||
content: {
|
||||
|
||||
Reference in New Issue
Block a user