mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-01 22:29:44 +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:
@@ -27,6 +27,16 @@ export class MockTeamWorkspace extends Mocker<
|
||||
quantity,
|
||||
},
|
||||
});
|
||||
await this.db.entitlement.create({
|
||||
data: {
|
||||
targetType: 'workspace',
|
||||
targetId: id,
|
||||
source: 'cloud_subscription',
|
||||
plan: 'team',
|
||||
status: 'active',
|
||||
quantity,
|
||||
},
|
||||
});
|
||||
|
||||
await this.db.workspaceFeature.create({
|
||||
data: {
|
||||
|
||||
@@ -45,6 +45,55 @@ export class MockWorkspace extends Mocker<MockWorkspaceInput, MockedWorkspace> {
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
const runtimeStateColumns = await this.db.$queryRaw<
|
||||
Array<{ exists: boolean }>
|
||||
>`
|
||||
SELECT EXISTS (
|
||||
SELECT 1
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'workspace_runtime_states'
|
||||
AND column_name = 'known'
|
||||
) AS "exists"
|
||||
`;
|
||||
if (runtimeStateColumns[0]?.exists) {
|
||||
await this.db.$executeRaw`
|
||||
INSERT INTO workspace_runtime_states (
|
||||
workspace_id,
|
||||
known,
|
||||
readonly,
|
||||
readonly_reasons,
|
||||
last_reconciled_at,
|
||||
stale_after,
|
||||
updated_at
|
||||
)
|
||||
VALUES (${workspace.id}, true, false, ARRAY[]::TEXT[], now(), NULL, now())
|
||||
ON CONFLICT (workspace_id)
|
||||
DO UPDATE SET
|
||||
known = true,
|
||||
readonly = false,
|
||||
readonly_reasons = ARRAY[]::TEXT[],
|
||||
last_reconciled_at = now(),
|
||||
stale_after = NULL,
|
||||
updated_at = now()
|
||||
`;
|
||||
} else {
|
||||
await this.db.$executeRaw`
|
||||
INSERT INTO workspace_runtime_states (
|
||||
workspace_id,
|
||||
readonly,
|
||||
readonly_reasons,
|
||||
stale_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (${workspace.id}, false, ARRAY[]::TEXT[], NULL, now())
|
||||
ON CONFLICT (workspace_id)
|
||||
DO UPDATE SET
|
||||
readonly = false,
|
||||
readonly_reasons = ARRAY[]::TEXT[],
|
||||
stale_at = NULL,
|
||||
updated_at = now()
|
||||
`;
|
||||
}
|
||||
|
||||
// create a rootDoc snapshot
|
||||
if (snapshot) {
|
||||
|
||||
Reference in New Issue
Block a user