From 0b9d30b55a709603ce67a812dafc78adea47a233 Mon Sep 17 00:00:00 2001 From: forehalo Date: Fri, 7 Feb 2025 11:40:59 +0000 Subject: [PATCH] refactor: rename all page query to doc (#10019) --- packages/backend/server/schema.prisma | 40 +- .../server/src/__tests__/models/page.spec.ts | 4 +- .../backend/server/src/__tests__/team.e2e.ts | 68 +-- .../server/src/__tests__/utils/permission.ts | 22 +- .../server/src/__tests__/utils/workspace.ts | 16 +- .../server/src/__tests__/workspace.e2e.ts | 45 +- .../__tests__/workspace/controller.spec.ts | 16 +- packages/backend/server/src/base/error/def.ts | 20 +- .../server/src/base/error/errors.gen.ts | 30 +- .../server/src/core/permission/index.ts | 2 +- .../server/src/core/permission/service.ts | 84 +-- .../server/src/core/permission/types.ts | 2 +- .../server/src/core/workspaces/controller.ts | 10 +- .../server/src/core/workspaces/index.ts | 6 +- .../workspaces/resolvers/{page.ts => doc.ts} | 479 +++++++++--------- .../src/core/workspaces/resolvers/index.ts | 2 +- packages/backend/server/src/models/page.ts | 62 +-- packages/backend/server/src/schema.gql | 70 ++- .../share-menu/share-page.tsx | 4 +- .../hooks/affine/use-all-page-list-config.tsx | 6 +- .../components/page-list/docs/select-page.tsx | 6 +- .../page-list/use-filtered-page-metas.tsx | 4 +- .../explorer/nodes/collection/index.tsx | 6 +- .../explorer/views/nodes/collection/index.tsx | 6 +- .../share-doc/entities/share-docs-list.ts | 3 +- .../modules/share-doc/entities/share-info.ts | 8 +- .../modules/share-doc/stores/share-docs.ts | 2 +- .../src/modules/share-doc/stores/share.ts | 6 +- .../get-workspace-public-page-by-id.gql | 2 +- .../graphql/get-workspace-public-pages.gql | 2 +- .../frontend/graphql/src/graphql/index.ts | 14 +- .../graphql/src/graphql/public-page.gql | 4 +- .../src/graphql/revoke-public-page.gql | 2 +- packages/frontend/graphql/src/schema.ts | 248 ++++----- 34 files changed, 658 insertions(+), 643 deletions(-) rename packages/backend/server/src/core/workspaces/resolvers/{page.ts => doc.ts} (71%) diff --git a/packages/backend/server/schema.prisma b/packages/backend/server/schema.prisma index 9ffabef6fc..043c9ccb0a 100644 --- a/packages/backend/server/schema.prisma +++ b/packages/backend/server/schema.prisma @@ -25,16 +25,16 @@ model User { features UserFeature[] userStripeCustomer UserStripeCustomer? workspacePermissions WorkspaceUserPermission[] - pagePermissions WorkspacePageUserPermission[] + docPermissions WorkspaceDocUserPermission[] connectedAccounts ConnectedAccount[] sessions UserSession[] aiSessions AiSession[] updatedRuntimeConfigs RuntimeConfig[] userSnapshots UserSnapshot[] - createdSnapshot Snapshot[] @relation("createdSnapshot") - updatedSnapshot Snapshot[] @relation("updatedSnapshot") - createdUpdate Update[] @relation("createdUpdate") - createdHistory SnapshotHistory[] @relation("createdHistory") + createdSnapshot Snapshot[] @relation("createdSnapshot") + updatedSnapshot Snapshot[] @relation("updatedSnapshot") + createdUpdate Update[] @relation("createdUpdate") + createdHistory SnapshotHistory[] @relation("createdHistory") @@index([email]) @@map("users") @@ -102,11 +102,11 @@ model Workspace { enableAi Boolean @default(true) @map("enable_ai") enableUrlPreview Boolean @default(false) @map("enable_url_preview") - features WorkspaceFeature[] - pages WorkspacePage[] - permissions WorkspaceUserPermission[] - pagePermissions WorkspacePageUserPermission[] - blobs Blob[] + features WorkspaceFeature[] + docs WorkspaceDoc[] + permissions WorkspaceUserPermission[] + docPermissions WorkspaceDocUserPermission[] + blobs Blob[] @@map("workspaces") } @@ -116,18 +116,18 @@ model Workspace { // We won't make sure every page has a corresponding record in this table. // Only the ones that have ever changed will have records here, // and for others we will make sure it's has a default value return in our business logic. -model WorkspacePage { - workspaceId String @map("workspace_id") @db.VarChar - pageId String @map("page_id") @db.VarChar - public Boolean @default(false) +model WorkspaceDoc { + workspaceId String @map("workspace_id") @db.VarChar + docId String @map("page_id") @db.VarChar + public Boolean @default(false) // Workspace user's default role in this page, default is `Manager` - defaultRole Int @default(30) @db.SmallInt + defaultRole Int @default(30) @db.SmallInt // Page/Edgeless - mode Int @default(0) @db.SmallInt + mode Int @default(0) @db.SmallInt workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) - @@id([workspaceId, pageId]) + @@id([workspaceId, docId]) @@map("workspace_pages") } @@ -162,9 +162,9 @@ model WorkspaceUserPermission { @@map("workspace_user_permissions") } -model WorkspacePageUserPermission { +model WorkspaceDocUserPermission { workspaceId String @map("workspace_id") @db.VarChar - pageId String @map("page_id") @db.VarChar + docId String @map("page_id") @db.VarChar userId String @map("user_id") @db.VarChar // External/Reader/Editor/Manager/Owner type Int @db.SmallInt @@ -173,7 +173,7 @@ model WorkspacePageUserPermission { user User @relation(fields: [userId], references: [id], onDelete: Cascade) workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) - @@id([workspaceId, pageId, userId]) + @@id([workspaceId, docId, userId]) @@map("workspace_page_user_permissions") } diff --git a/packages/backend/server/src/__tests__/models/page.spec.ts b/packages/backend/server/src/__tests__/models/page.spec.ts index d8bfd2bb4f..7005f514f0 100644 --- a/packages/backend/server/src/__tests__/models/page.spec.ts +++ b/packages/backend/server/src/__tests__/models/page.spec.ts @@ -49,7 +49,7 @@ test.after(async t => { test('should create page with default mode and public false', async t => { const page = await t.context.page.upsert(workspace.id, 'page1'); t.is(page.workspaceId, workspace.id); - t.is(page.pageId, 'page1'); + t.is(page.docId, 'page1'); t.is(page.mode, PublicPageMode.Page); t.is(page.public, false); }); @@ -110,7 +110,7 @@ test('should get public pages of a workspace', async t => { await t.context.page.upsert(workspace.id, 'page3'); const pages = await t.context.page.findPublics(workspace.id); t.is(pages.length, 2); - t.deepEqual(pages.map(p => p.pageId).sort(), ['page1', 'page2']); + t.deepEqual(pages.map(p => p.docId).sort(), ['page1', 'page2']); }); test('should grant a member to access a page', async t => { diff --git a/packages/backend/server/src/__tests__/team.e2e.ts b/packages/backend/server/src/__tests__/team.e2e.ts index 4bbd7383bc..c8ee885582 100644 --- a/packages/backend/server/src/__tests__/team.e2e.ts +++ b/packages/backend/server/src/__tests__/team.e2e.ts @@ -23,6 +23,7 @@ import { createInviteLink, createTestingApp, createWorkspace, + docGrantedUsersList, getInviteInfo, getInviteLink, getWorkspace, @@ -31,7 +32,6 @@ import { inviteUser, inviteUsers, leaveWorkspace, - pageGrantedUsersList, revokeDocUserRoles, revokeInviteLink, revokeMember, @@ -39,7 +39,7 @@ import { signUp, sleep, TestingApp, - updatePageDefaultRole, + updateDocDefaultRole, UserAuthedType, } from './utils'; @@ -817,13 +817,13 @@ test('should be able to grant and revoke users role in page', async t => { read, external, } = await init(app, 5); - const pageId = nanoid(); + const docId = nanoid(); const res = await grantDocUserRoles( app, admin.token.token, ws.id, - pageId, + docId, [read.id, write.id], DocRole.Manager ); @@ -840,7 +840,7 @@ test('should be able to grant and revoke users role in page', async t => { app, admin.token.token, ws.id, - pageId, + docId, [read.id], DocRole.Reader ); @@ -849,7 +849,7 @@ test('should be able to grant and revoke users role in page', async t => { app, read.token.token, ws.id, - pageId, + docId, [external.id], DocRole.Editor ); @@ -859,15 +859,15 @@ test('should be able to grant and revoke users role in page', async t => { }, }); - const pageUsersList = await pageGrantedUsersList( + const docUsersList = await docGrantedUsersList( app, admin.token.token, ws.id, - pageId + docId ); - t.is(pageUsersList.data.workspace.pageGrantedUsersList.totalCount, 3); + t.is(docUsersList.data.workspace.doc.grantedUsersList.totalCount, 3); const externalRole = - pageUsersList.data.workspace.pageGrantedUsersList.edges.find( + docUsersList.data.workspace.doc.grantedUsersList.edges.find( (edge: any) => edge.node.user.id === external.id )?.node.role; t.is(externalRole, DocRole[DocRole.Editor]); @@ -877,18 +877,18 @@ test('should be able to grant and revoke users role in page', async t => { test('should be able to change the default role in page', async t => { const { app } = t.context; const { teamWorkspace: ws, admin } = await init(app, 5); - const pageId = nanoid(); - const res = await updatePageDefaultRole( + const docId = nanoid(); + const res = await updateDocDefaultRole( app, admin.token.token, ws.id, - pageId, + docId, DocRole.Reader ); t.deepEqual(res.body, { data: { - updatePageDefaultRole: true, + updateDocDefaultRole: true, }, }); }); @@ -902,53 +902,53 @@ test('default page role should be able to override the workspace role', async t external, } = await init(app, 5); - const pageId = nanoid(); + const docId = nanoid(); - const res = await updatePageDefaultRole( + const res = await updateDocDefaultRole( app, admin.token.token, workspace.id, - pageId, + docId, DocRole.Manager ); t.deepEqual(res.body, { data: { - updatePageDefaultRole: true, + updateDocDefaultRole: true, }, }); // reader can manage the page if the page default role is Manager { - const readerRes = await updatePageDefaultRole( + const readerRes = await updateDocDefaultRole( app, read.token.token, workspace.id, - pageId, + docId, DocRole.Manager ); t.deepEqual(readerRes.body, { data: { - updatePageDefaultRole: true, + updateDocDefaultRole: true, }, }); } // external can't manage the page even if the page default role is Manager { - const externalRes = await updatePageDefaultRole( + const externalRes = await updateDocDefaultRole( app, external.token.token, workspace.id, - pageId, + docId, DocRole.Manager ); t.like(externalRes.body, { errors: [ { - message: `You do not have permission to access doc ${pageId} under Space ${workspace.id}.`, + message: `You do not have permission to access doc ${docId} under Space ${workspace.id}.`, }, ], }); @@ -958,13 +958,13 @@ test('default page role should be able to override the workspace role', async t test('should be able to grant and revoke doc user role', async t => { const { app } = t.context; const { teamWorkspace: ws, admin, read, external } = await init(app, 5); - const pageId = nanoid(); + const docId = nanoid(); const res = await grantDocUserRoles( app, admin.token.token, ws.id, - pageId, + docId, [external.id], DocRole.Manager ); @@ -981,7 +981,7 @@ test('should be able to grant and revoke doc user role', async t => { app, external.token.token, ws.id, - pageId, + docId, [read.id], DocRole.Manager ); @@ -999,7 +999,7 @@ test('should be able to grant and revoke doc user role', async t => { app, admin.token.token, ws.id, - pageId, + docId, external.id ); @@ -1014,14 +1014,14 @@ test('should be able to grant and revoke doc user role', async t => { app, external.token.token, ws.id, - pageId, + docId, read.id ); t.like(externalRes.body, { errors: [ { - message: `You do not have permission to access doc ${pageId} under Space ${ws.id}.`, + message: `You do not have permission to access doc ${docId} under Space ${ws.id}.`, }, ], }); @@ -1031,7 +1031,7 @@ test('should be able to grant and revoke doc user role', async t => { test('update page default role should throw error if the space does not exist', async t => { const { app } = t.context; const { admin } = await init(app, 5); - const pageId = nanoid(); + const docId = nanoid(); const nonExistWorkspaceId = 'non-exist-workspace'; const res = await request(app.getHttpServer()) .post('/graphql') @@ -1040,9 +1040,9 @@ test('update page default role should throw error if the space does not exist', .send({ query: ` mutation { - updatePageDefaultRole(input: { + updateDocDefaultRole(input: { workspaceId: "${nonExistWorkspaceId}", - docId: "${pageId}", + docId: "${docId}", role: Manager, }) } @@ -1052,7 +1052,7 @@ test('update page default role should throw error if the space does not exist', t.like(res.body, { errors: [ { - message: `You do not have permission to access doc ${pageId} under Space ${nonExistWorkspaceId}.`, + message: `You do not have permission to access doc ${docId} under Space ${nonExistWorkspaceId}.`, }, ], }); diff --git a/packages/backend/server/src/__tests__/utils/permission.ts b/packages/backend/server/src/__tests__/utils/permission.ts index 91d0f46947..06535f25b5 100644 --- a/packages/backend/server/src/__tests__/utils/permission.ts +++ b/packages/backend/server/src/__tests__/utils/permission.ts @@ -54,7 +54,7 @@ export function revokeDocUserRoles( }); } -export function updatePageDefaultRole( +export function updateDocDefaultRole( app: INestApplication, token: string, workspaceId: string, @@ -68,7 +68,7 @@ export function updatePageDefaultRole( .send({ query: ` mutation { - updatePageDefaultRole(input: { + updateDocDefaultRole(input: { workspaceId: "${workspaceId}", docId: "${docId}", role: ${DocRole[role]} @@ -78,7 +78,7 @@ export function updatePageDefaultRole( }); } -export async function pageGrantedUsersList( +export async function docGrantedUsersList( app: INestApplication, token: string, workspaceId: string, @@ -94,14 +94,16 @@ export async function pageGrantedUsersList( query: ` query { workspace(id: "${workspaceId}") { - pageGrantedUsersList(pageId: "${docId}", pagination: { first: ${first}, offset: ${offset} }) { - totalCount - edges { + doc(docId: "${docId}") { + grantedUsersList(pagination: { first: ${first}, offset: ${offset} }) { + totalCount + edges { cursor - node { - role - user { - id + node { + role + user { + id + } } } } diff --git a/packages/backend/server/src/__tests__/utils/workspace.ts b/packages/backend/server/src/__tests__/utils/workspace.ts index 93765687c5..9edb5abc3a 100644 --- a/packages/backend/server/src/__tests__/utils/workspace.ts +++ b/packages/backend/server/src/__tests__/utils/workspace.ts @@ -103,11 +103,11 @@ export async function updateWorkspace( return res.body.data.updateWorkspace.public; } -export async function publishPage( +export async function publishDoc( app: INestApplication, token: string, workspaceId: string, - pageId: string + docId: string ) { const res = await request(app.getHttpServer()) .post(gql) @@ -116,7 +116,7 @@ export async function publishPage( .send({ query: ` mutation { - publishPage(workspaceId: "${workspaceId}", pageId: "${pageId}") { + publishDoc(workspaceId: "${workspaceId}", docId: "${docId}") { id mode } @@ -124,14 +124,14 @@ export async function publishPage( `, }) .expect(200); - return res.body.errors?.[0]?.message || res.body.data?.publishPage; + return res.body.errors?.[0]?.message || res.body.data?.publishDoc; } -export async function revokePublicPage( +export async function revokePublicDoc( app: INestApplication, token: string, workspaceId: string, - pageId: string + docId: string ) { const res = await request(app.getHttpServer()) .post(gql) @@ -140,7 +140,7 @@ export async function revokePublicPage( .send({ query: ` mutation { - revokePublicPage(workspaceId: "${workspaceId}", pageId: "${pageId}") { + revokePublicDoc(workspaceId: "${workspaceId}", docId: "${docId}") { id mode public @@ -149,7 +149,7 @@ export async function revokePublicPage( `, }) .expect(200); - return res.body.errors?.[0]?.message || res.body.data?.revokePublicPage; + return res.body.errors?.[0]?.message || res.body.data?.revokePublicDoc; } export async function grantMember( diff --git a/packages/backend/server/src/__tests__/workspace.e2e.ts b/packages/backend/server/src/__tests__/workspace.e2e.ts index adbdb360bf..5a7b9f7df9 100644 --- a/packages/backend/server/src/__tests__/workspace.e2e.ts +++ b/packages/backend/server/src/__tests__/workspace.e2e.ts @@ -10,8 +10,8 @@ import { createWorkspace, getWorkspacePublicPages, inviteUser, - publishPage, - revokePublicPage, + publishDoc, + revokePublicDoc, signUp, TestingApp, updateWorkspace, @@ -83,8 +83,8 @@ test('should share a page', async t => { const workspace = await createWorkspace(app, u1.token.token); - const share = await publishPage(app, u1.token.token, workspace.id, 'page1'); - t.is(share.id, 'page1', 'failed to share page'); + const share = await publishDoc(app, u1.token.token, workspace.id, 'doc1'); + t.is(share.id, 'doc1', 'failed to share doc'); const pages = await getWorkspacePublicPages( app, u1.token.token, @@ -93,8 +93,8 @@ test('should share a page', async t => { t.is(pages.length, 1, 'failed to get shared pages'); t.deepEqual( pages[0], - { id: 'page1', mode: 'Page' }, - 'failed to get shared page: page1' + { id: 'doc1', mode: 'Page' }, + 'failed to get shared doc: doc1' ); const resp1 = await request(app.getHttpServer()) @@ -107,53 +107,48 @@ test('should share a page', async t => { t.is(resp2.statusCode, 200, 'failed to get root doc with public pages'); const resp3 = await request(app.getHttpServer()) - .get(`/api/workspaces/${workspace.id}/docs/page1`) + .get(`/api/workspaces/${workspace.id}/docs/doc1`) .auth(u1.token.token, { type: 'bearer' }); // 404 because we don't put the page doc to server t.is(resp3.statusCode, 404, 'failed to get shared doc with u1 token'); const resp4 = await request(app.getHttpServer()).get( - `/api/workspaces/${workspace.id}/docs/page1` + `/api/workspaces/${workspace.id}/docs/doc1` ); // 404 because we don't put the page doc to server t.is(resp4.statusCode, 404, 'should not get shared doc without token'); - const msg1 = await publishPage(app, u2.token.token, 'not_exists_ws', 'page2'); + const msg1 = await publishDoc(app, u2.token.token, 'not_exists_ws', 'doc2'); t.is( msg1, - 'You do not have permission to access doc page2 under Space not_exists_ws.', - 'unauthorized user can share page' + 'You do not have permission to access doc doc2 under Space not_exists_ws.', + 'unauthorized user can share doc' ); - const msg2 = await revokePublicPage( + const msg2 = await revokePublicDoc( app, u2.token.token, 'not_exists_ws', - 'page2' + 'doc2' ); t.is( msg2, - 'You do not have permission to access doc page2 under Space not_exists_ws.', - 'unauthorized user can share page' + 'You do not have permission to access doc doc2 under Space not_exists_ws.', + 'unauthorized user can share doc' ); - const revoke = await revokePublicPage( + const revoke = await revokePublicDoc( app, u1.token.token, workspace.id, - 'page1' + 'doc1' ); - t.false(revoke.public, 'failed to revoke page'); + t.false(revoke.public, 'failed to revoke doc'); const pages2 = await getWorkspacePublicPages( app, u1.token.token, workspace.id ); t.is(pages2.length, 0, 'failed to get shared pages'); - const msg4 = await revokePublicPage( - app, - u1.token.token, - workspace.id, - 'page3' - ); - t.is(msg4, 'Page is not public'); + const msg4 = await revokePublicDoc(app, u1.token.token, workspace.id, 'doc3'); + t.is(msg4, 'Doc is not public'); const pages3 = await getWorkspacePublicPages( app, diff --git a/packages/backend/server/src/__tests__/workspace/controller.spec.ts b/packages/backend/server/src/__tests__/workspace/controller.spec.ts index 6d60f139fe..b37dee6a62 100644 --- a/packages/backend/server/src/__tests__/workspace/controller.spec.ts +++ b/packages/backend/server/src/__tests__/workspace/controller.spec.ts @@ -41,7 +41,7 @@ test.before(async t => { t.context.storage = app.get(WorkspaceBlobStorage); t.context.workspace = app.get(PgWorkspaceDocStorageAdapter); - await db.workspacePage.create({ + await db.workspaceDoc.create({ data: { workspace: { create: { @@ -49,12 +49,12 @@ test.before(async t => { public: true, }, }, - pageId: 'private', + docId: 'private', public: false, }, }); - await db.workspacePage.create({ + await db.workspaceDoc.create({ data: { workspace: { create: { @@ -62,12 +62,12 @@ test.before(async t => { public: false, }, }, - pageId: 'public', + docId: 'public', public: true, }, }); - await db.workspacePage.create({ + await db.workspaceDoc.create({ data: { workspace: { create: { @@ -75,7 +75,7 @@ test.before(async t => { public: false, }, }, - pageId: 'private', + docId: 'private', public: false, }, }); @@ -261,8 +261,8 @@ test('should be able to change page publish mode', async t => { t.is(res.status, HttpStatus.OK); t.is(res.get('publish-mode'), 'page'); - await db.workspacePage.update({ - where: { workspaceId_pageId: { workspaceId: 'private', pageId: 'public' } }, + await db.workspaceDoc.update({ + where: { workspaceId_docId: { workspaceId: 'private', docId: 'public' } }, data: { mode: 1 }, }); diff --git a/packages/backend/server/src/base/error/def.ts b/packages/backend/server/src/base/error/def.ts index 8c17bd8bab..4e76e38e00 100644 --- a/packages/backend/server/src/base/error/def.ts +++ b/packages/backend/server/src/base/error/def.ts @@ -428,13 +428,13 @@ export const USER_FRIENDLY_ERRORS = { message: ({ spaceId, blobId }) => `Blob ${blobId} not found in Space ${spaceId}.`, }, - expect_to_publish_page: { + expect_to_publish_doc: { type: 'invalid_input', - message: 'Expected to publish a page, not a Space.', + message: 'Expected to publish a doc, not a Space.', }, - expect_to_revoke_public_page: { + expect_to_revoke_public_doc: { type: 'invalid_input', - message: 'Expected to revoke a public page, not a Space.', + message: 'Expected to revoke a public doc, not a Space.', }, expect_to_grant_doc_user_roles: { type: 'invalid_input', @@ -454,9 +454,9 @@ export const USER_FRIENDLY_ERRORS = { message: ({ spaceId, docId }) => `Expect update roles on doc ${docId} under Space ${spaceId}, not a Space.`, }, - page_is_not_public: { + doc_is_not_public: { type: 'bad_request', - message: 'Page is not public.', + message: 'Doc is not public.', }, failed_to_save_updates: { type: 'internal_server_error', @@ -470,13 +470,13 @@ export const USER_FRIENDLY_ERRORS = { type: 'action_forbidden', message: 'A Team workspace is required to perform this action.', }, - page_default_role_can_not_be_owner: { + doc_default_role_can_not_be_owner: { type: 'invalid_input', - message: 'Page default role can not be owner.', + message: 'Doc default role can not be owner.', }, - can_not_batch_grant_page_owner_permissions: { + can_not_batch_grant_doc_owner_permissions: { type: 'invalid_input', - message: 'Can not batch grant page owner permissions.', + message: 'Can not batch grant doc owner permissions.', }, // Subscription Errors diff --git a/packages/backend/server/src/base/error/errors.gen.ts b/packages/backend/server/src/base/error/errors.gen.ts index 56848ebe80..fab04144b6 100644 --- a/packages/backend/server/src/base/error/errors.gen.ts +++ b/packages/backend/server/src/base/error/errors.gen.ts @@ -337,15 +337,15 @@ export class BlobNotFound extends UserFriendlyError { } } -export class ExpectToPublishPage extends UserFriendlyError { +export class ExpectToPublishDoc extends UserFriendlyError { constructor(message?: string) { - super('invalid_input', 'expect_to_publish_page', message); + super('invalid_input', 'expect_to_publish_doc', message); } } -export class ExpectToRevokePublicPage extends UserFriendlyError { +export class ExpectToRevokePublicDoc extends UserFriendlyError { constructor(message?: string) { - super('invalid_input', 'expect_to_revoke_public_page', message); + super('invalid_input', 'expect_to_revoke_public_doc', message); } } @ObjectType() @@ -382,9 +382,9 @@ export class ExpectToUpdateDocUserRole extends UserFriendlyError { } } -export class PageIsNotPublic extends UserFriendlyError { +export class DocIsNotPublic extends UserFriendlyError { constructor(message?: string) { - super('bad_request', 'page_is_not_public', message); + super('bad_request', 'doc_is_not_public', message); } } @@ -406,15 +406,15 @@ export class ActionForbiddenOnNonTeamWorkspace extends UserFriendlyError { } } -export class PageDefaultRoleCanNotBeOwner extends UserFriendlyError { +export class DocDefaultRoleCanNotBeOwner extends UserFriendlyError { constructor(message?: string) { - super('invalid_input', 'page_default_role_can_not_be_owner', message); + super('invalid_input', 'doc_default_role_can_not_be_owner', message); } } -export class CanNotBatchGrantPageOwnerPermissions extends UserFriendlyError { +export class CanNotBatchGrantDocOwnerPermissions extends UserFriendlyError { constructor(message?: string) { - super('invalid_input', 'can_not_batch_grant_page_owner_permissions', message); + super('invalid_input', 'can_not_batch_grant_doc_owner_permissions', message); } } @ObjectType() @@ -764,17 +764,17 @@ export enum ErrorNames { INVALID_HISTORY_TIMESTAMP, DOC_HISTORY_NOT_FOUND, BLOB_NOT_FOUND, - EXPECT_TO_PUBLISH_PAGE, - EXPECT_TO_REVOKE_PUBLIC_PAGE, + EXPECT_TO_PUBLISH_DOC, + EXPECT_TO_REVOKE_PUBLIC_DOC, EXPECT_TO_GRANT_DOC_USER_ROLES, EXPECT_TO_REVOKE_DOC_USER_ROLES, EXPECT_TO_UPDATE_DOC_USER_ROLE, - PAGE_IS_NOT_PUBLIC, + DOC_IS_NOT_PUBLIC, FAILED_TO_SAVE_UPDATES, FAILED_TO_UPSERT_SNAPSHOT, ACTION_FORBIDDEN_ON_NON_TEAM_WORKSPACE, - PAGE_DEFAULT_ROLE_CAN_NOT_BE_OWNER, - CAN_NOT_BATCH_GRANT_PAGE_OWNER_PERMISSIONS, + DOC_DEFAULT_ROLE_CAN_NOT_BE_OWNER, + CAN_NOT_BATCH_GRANT_DOC_OWNER_PERMISSIONS, UNSUPPORTED_SUBSCRIPTION_PLAN, FAILED_TO_CHECKOUT, INVALID_CHECKOUT_PARAMETERS, diff --git a/packages/backend/server/src/core/permission/index.ts b/packages/backend/server/src/core/permission/index.ts index 6cbfa85011..fab3588cd5 100644 --- a/packages/backend/server/src/core/permission/index.ts +++ b/packages/backend/server/src/core/permission/index.ts @@ -16,7 +16,7 @@ export { fixupDocRole, mapDocRoleToPermissions, mapWorkspaceRoleToPermissions, - PublicPageMode, + PublicDocMode, WORKSPACE_ACTIONS, type WorkspaceActionPermissions, WorkspaceRole, diff --git a/packages/backend/server/src/core/permission/service.ts b/packages/backend/server/src/core/permission/service.ts index bcaf45b912..fada8a0cb3 100644 --- a/packages/backend/server/src/core/permission/service.ts +++ b/packages/backend/server/src/core/permission/service.ts @@ -1,10 +1,10 @@ import { Injectable, Logger } from '@nestjs/common'; -import type { Prisma, WorkspacePageUserPermission } from '@prisma/client'; +import type { Prisma, WorkspaceDocUserPermission } from '@prisma/client'; import { PrismaClient, WorkspaceMemberStatus } from '@prisma/client'; import { groupBy } from 'lodash-es'; import { - CanNotBatchGrantPageOwnerPermissions, + CanNotBatchGrantDocOwnerPermissions, DocAccessDenied, EventBus, OnEvent, @@ -17,7 +17,7 @@ import { docActionRequiredRole, docActionRequiredWorkspaceRole, DocRole, - PublicPageMode, + PublicDocMode, WorkspaceRole, } from './types'; @@ -38,10 +38,10 @@ export class PermissionService { return; } - await this.prisma.workspacePageUserPermission.createMany({ + await this.prisma.workspaceDocUserPermission.createMany({ data: { workspaceId, - pageId: docId, + docId, userId: editor, type: DocRole.Owner, createdAt: new Date(), @@ -172,7 +172,7 @@ export class PermissionService { // if workspace is public or have any public page, then allow to access const [isPublicWorkspace, publicPages] = await Promise.all([ this.tryCheckWorkspace(ws, user, WorkspaceRole.Collaborator), - this.prisma.workspacePage.count({ + this.prisma.workspaceDoc.count({ where: { workspaceId: ws, public: true, @@ -555,17 +555,17 @@ export class PermissionService { async tryCheckPage( ws: string, - page: string, + doc: string, action: DocAction, user?: string ) { const role = docActionRequiredRole(action); // check whether page is public if (action === 'Doc.Read') { - const count = await this.prisma.workspacePage.count({ + const count = await this.prisma.workspaceDoc.count({ where: { workspaceId: ws, - pageId: page, + docId: doc, public: true, }, }); @@ -579,20 +579,20 @@ export class PermissionService { if (user) { const [roleEntity, pageEntity, workspaceRoleEntity] = await Promise.all([ - this.prisma.workspacePageUserPermission.findFirst({ + this.prisma.workspaceDocUserPermission.findFirst({ where: { workspaceId: ws, - pageId: page, + docId: doc, userId: user, }, select: { type: true, }, }), - this.prisma.workspacePage.findFirst({ + this.prisma.workspaceDoc.findFirst({ where: { workspaceId: ws, - pageId: page, + docId: doc, }, select: { defaultRole: true, @@ -629,7 +629,7 @@ export class PermissionService { } this.logger.log("User's role is lower than required", { workspaceId: ws, - docId: page, + docId: doc, userId: user, workspaceRole: workspaceRoleEntity ? WorkspaceRole[workspaceRoleEntity.type] @@ -651,24 +651,24 @@ export class PermissionService { ); } - async isPublicPage(ws: string, page: string) { - return this.prisma.workspacePage + async isPublicPage(ws: string, doc: string) { + return this.prisma.workspaceDoc .count({ where: { workspaceId: ws, - pageId: page, + docId: doc, public: true, }, }) .then(count => count > 0); } - async publishPage(ws: string, page: string, mode = PublicPageMode.Page) { - return this.prisma.workspacePage.upsert({ + async publishPage(ws: string, doc: string, mode = PublicDocMode.Page) { + return this.prisma.workspaceDoc.upsert({ where: { - workspaceId_pageId: { + workspaceId_docId: { workspaceId: ws, - pageId: page, + docId: doc, }, }, update: { @@ -677,19 +677,19 @@ export class PermissionService { }, create: { workspaceId: ws, - pageId: page, + docId: doc, mode, public: true, }, }); } - async revokePublicPage(ws: string, page: string) { - return this.prisma.workspacePage.upsert({ + async revokePublicPage(ws: string, doc: string) { + return this.prisma.workspaceDoc.upsert({ where: { - workspaceId_pageId: { + workspaceId_docId: { workspaceId: ws, - pageId: page, + docId: doc, }, }, update: { @@ -697,20 +697,20 @@ export class PermissionService { }, create: { workspaceId: ws, - pageId: page, + docId: doc, public: false, }, }); } - async grantPage(ws: string, page: string, user: string, permission: DocRole) { + async grantPage(ws: string, doc: string, user: string, permission: DocRole) { const [p] = await this.prisma.$transaction( [ - this.prisma.workspacePageUserPermission.upsert({ + this.prisma.workspaceDocUserPermission.upsert({ where: { - workspaceId_pageId_userId: { + workspaceId_docId_userId: { workspaceId: ws, - pageId: page, + docId: doc, userId: user, }, }, @@ -719,7 +719,7 @@ export class PermissionService { }, create: { workspaceId: ws, - pageId: page, + docId: doc, userId: user, type: permission, }, @@ -727,10 +727,10 @@ export class PermissionService { // If the new permission is owner, we need to revoke old owner permission === DocRole.Owner - ? this.prisma.workspacePageUserPermission.updateMany({ + ? this.prisma.workspaceDocUserPermission.updateMany({ where: { workspaceId: ws, - pageId: page, + docId: doc, type: DocRole.Owner, userId: { not: user, @@ -744,14 +744,14 @@ export class PermissionService { ].filter(Boolean) as Prisma.PrismaPromise[] ); - return p as WorkspacePageUserPermission; + return p as WorkspaceDocUserPermission; } - async revokePage(ws: string, page: string, user: string) { - const result = await this.prisma.workspacePageUserPermission.deleteMany({ + async revokePage(ws: string, doc: string, user: string) { + const result = await this.prisma.workspaceDocUserPermission.deleteMany({ where: { workspaceId: ws, - pageId: page, + docId: doc, userId: user, type: { // We shouldn't revoke owner permission, should auto deleted by workspace/user delete cascading @@ -765,7 +765,7 @@ export class PermissionService { async batchGrantPage( workspaceId: string, - pageId: string, + docId: string, userIds: string[], role: DocRole ) { @@ -774,14 +774,14 @@ export class PermissionService { } if (role === DocRole.Owner) { - throw new CanNotBatchGrantPageOwnerPermissions(); + throw new CanNotBatchGrantDocOwnerPermissions(); } - const result = await this.prisma.workspacePageUserPermission.createMany({ + const result = await this.prisma.workspaceDocUserPermission.createMany({ skipDuplicates: true, data: userIds.map(id => ({ workspaceId, - pageId, + docId, userId: id, type: role, })), diff --git a/packages/backend/server/src/core/permission/types.ts b/packages/backend/server/src/core/permission/types.ts index 2e97636279..9db31efcd3 100644 --- a/packages/backend/server/src/core/permission/types.ts +++ b/packages/backend/server/src/core/permission/types.ts @@ -1,6 +1,6 @@ import { LeafPaths, LeafVisitor } from '../../base'; -export enum PublicPageMode { +export enum PublicDocMode { Page, Edgeless, } diff --git a/packages/backend/server/src/core/workspaces/controller.ts b/packages/backend/server/src/core/workspaces/controller.ts index 3638571391..dd55a5c3c4 100644 --- a/packages/backend/server/src/core/workspaces/controller.ts +++ b/packages/backend/server/src/core/workspaces/controller.ts @@ -13,7 +13,7 @@ import { } from '../../base'; import { CurrentUser, Public } from '../auth'; import { PgWorkspaceDocStorageAdapter } from '../doc'; -import { PermissionService, PublicPageMode } from '../permission'; +import { PermissionService, PublicDocMode } from '../permission'; import { WorkspaceBlobStorage } from '../storage'; import { DocID } from '../utils/doc'; @@ -109,16 +109,16 @@ export class WorkspacesController { if (!docId.isWorkspace) { // fetch the publish page mode for publish page - const publishPage = await this.prisma.workspacePage.findUnique({ + const publishPage = await this.prisma.workspaceDoc.findUnique({ where: { - workspaceId_pageId: { + workspaceId_docId: { workspaceId: docId.workspace, - pageId: docId.guid, + docId: docId.guid, }, }, }); const publishPageMode = - publishPage?.mode === PublicPageMode.Edgeless ? 'edgeless' : 'page'; + publishPage?.mode === PublicDocMode.Edgeless ? 'edgeless' : 'page'; res.setHeader('publish-mode', publishPageMode); } diff --git a/packages/backend/server/src/core/workspaces/index.ts b/packages/backend/server/src/core/workspaces/index.ts index f284de71db..fb5423cb40 100644 --- a/packages/backend/server/src/core/workspaces/index.ts +++ b/packages/backend/server/src/core/workspaces/index.ts @@ -10,9 +10,10 @@ import { UserModule } from '../user'; import { WorkspacesController } from './controller'; import { DocHistoryResolver, - PagePermissionResolver, + DocResolver, TeamWorkspaceResolver, WorkspaceBlobResolver, + WorkspaceDocResolver, WorkspaceResolver, WorkspaceService, } from './resolvers'; @@ -31,7 +32,8 @@ import { providers: [ WorkspaceResolver, TeamWorkspaceResolver, - PagePermissionResolver, + WorkspaceDocResolver, + DocResolver, DocHistoryResolver, WorkspaceBlobResolver, WorkspaceService, diff --git a/packages/backend/server/src/core/workspaces/resolvers/page.ts b/packages/backend/server/src/core/workspaces/resolvers/doc.ts similarity index 71% rename from packages/backend/server/src/core/workspaces/resolvers/page.ts rename to packages/backend/server/src/core/workspaces/resolvers/doc.ts index a188f35829..1475acfbe4 100644 --- a/packages/backend/server/src/core/workspaces/resolvers/page.ts +++ b/packages/backend/server/src/core/workspaces/resolvers/doc.ts @@ -10,18 +10,18 @@ import { ResolveField, Resolver, } from '@nestjs/graphql'; -import type { WorkspacePage as PrismaWorkspacePage } from '@prisma/client'; +import type { WorkspaceDoc as PrismaWorkspaceDoc } from '@prisma/client'; import { PrismaClient } from '@prisma/client'; import { DocAccessDenied, + DocDefaultRoleCanNotBeOwner, + DocIsNotPublic, ExpectToGrantDocUserRoles, - ExpectToPublishPage, + ExpectToPublishDoc, ExpectToRevokeDocUserRoles, - ExpectToRevokePublicPage, + ExpectToRevokePublicDoc, ExpectToUpdateDocUserRole, - PageDefaultRoleCanNotBeOwner, - PageIsNotPublic, paginate, Paginated, PaginationInput, @@ -36,27 +36,27 @@ import { fixupDocRole, mapDocRoleToPermissions, PermissionService, - PublicPageMode, + PublicDocMode, } from '../../permission'; import { PublicUserType } from '../../user'; import { DocID } from '../../utils/doc'; import { WorkspaceType } from '../types'; -registerEnumType(PublicPageMode, { - name: 'PublicPageMode', - description: 'The mode which the public page default in', +registerEnumType(PublicDocMode, { + name: 'PublicDocMode', + description: 'The mode which the public doc default in', }); @ObjectType() -class WorkspacePage implements Partial { +class DocType implements Partial { @Field(() => String, { name: 'id' }) - pageId!: string; + docId!: string; @Field() workspaceId!: string; - @Field(() => PublicPageMode) - mode!: PublicPageMode; + @Field(() => PublicDocMode) + mode!: PublicDocMode; @Field() public!: boolean; @@ -105,7 +105,7 @@ class RevokeDocUserRoleInput { } @InputType() -class UpdatePageDefaultRoleInput { +class UpdateDocDefaultRoleInput { @Field(() => String) docId!: string; @@ -144,13 +144,7 @@ const DocPermissions = registerObjectType( ); @ObjectType() -class DocType { - @Field(() => String) - id!: string; - - @Field(() => Boolean) - public!: boolean; - +export class DocRolePermissions { @Field(() => DocRole) role!: DocRole; @@ -159,8 +153,207 @@ class DocType { } @Resolver(() => WorkspaceType) -export class PagePermissionResolver { - private readonly logger = new Logger(PagePermissionResolver.name); +export class WorkspaceDocResolver { + private readonly logger = new Logger(WorkspaceDocResolver.name); + + constructor( + private readonly prisma: PrismaClient, + private readonly permission: PermissionService + ) {} + + @ResolveField(() => [DocType], { + complexity: 2, + deprecationReason: 'use [WorkspaceType.publicDocs] instead', + }) + async publicPages(@Parent() workspace: WorkspaceType) { + return this.publicDocs(workspace); + } + + @ResolveField(() => [DocType], { + description: 'Get public docs of a workspace', + complexity: 2, + }) + async publicDocs(@Parent() workspace: WorkspaceType) { + return this.prisma.workspaceDoc.findMany({ + where: { + workspaceId: workspace.id, + public: true, + }, + }); + } + + @ResolveField(() => DocType, { + description: 'Get public page of a workspace by page id.', + complexity: 2, + nullable: true, + deprecationReason: 'use [WorkspaceType.publicDoc] instead', + }) + async publicPage( + @Parent() workspace: WorkspaceType, + @Args('pageId') pageId: string + ) { + return this.publicDoc(workspace, pageId); + } + + @ResolveField(() => DocType, { + description: 'Get public page of a workspace by page id.', + complexity: 2, + nullable: true, + }) + async publicDoc( + @Parent() workspace: WorkspaceType, + @Args('docId') docId: string + ) { + return this.prisma.workspaceDoc.findFirst({ + where: { + workspaceId: workspace.id, + docId, + public: true, + }, + }); + } + + @ResolveField(() => DocType, { + description: 'Get get with given id', + complexity: 2, + }) + async doc( + @Parent() workspace: WorkspaceType, + @Args('docId') docId: string + ): Promise { + const doc = await this.prisma.workspaceDoc.findFirst({ + where: { + workspaceId: workspace.id, + docId, + }, + }); + + return ( + doc ?? { + docId, + workspaceId: workspace.id, + public: false, + mode: PublicDocMode.Page, + } + ); + } + + @Mutation(() => DocType, { + deprecationReason: 'use publishDoc instead', + }) + async publishPage( + @CurrentUser() user: CurrentUser, + @Args('workspaceId') workspaceId: string, + @Args('pageId') pageId: string, + @Args({ + name: 'mode', + type: () => PublicDocMode, + nullable: true, + defaultValue: PublicDocMode.Page, + }) + mode: PublicDocMode + ) { + return this.publishDoc(user, workspaceId, pageId, mode); + } + + @Mutation(() => DocType) + async publishDoc( + @CurrentUser() user: CurrentUser, + @Args('workspaceId') workspaceId: string, + @Args('docId') rawDocId: string, + @Args({ + name: 'mode', + type: () => PublicDocMode, + nullable: true, + defaultValue: PublicDocMode.Page, + }) + mode: PublicDocMode + ) { + const docId = new DocID(rawDocId, workspaceId); + + if (docId.isWorkspace) { + this.logger.error('Expect to publish doc, but it is a workspace', { + workspaceId, + docId: rawDocId, + }); + throw new ExpectToPublishDoc(); + } + + await this.permission.checkPagePermission( + docId.workspace, + docId.guid, + 'Doc.Publish', + user.id + ); + + this.logger.log('Publish page', { + workspaceId, + docId: rawDocId, + mode, + }); + + return this.permission.publishPage(docId.workspace, docId.guid, mode); + } + + @Mutation(() => DocType, { + deprecationReason: 'use revokePublicDoc instead', + }) + async revokePublicPage( + @CurrentUser() user: CurrentUser, + @Args('workspaceId') workspaceId: string, + @Args('docId') docId: string + ) { + return this.revokePublicDoc(user, workspaceId, docId); + } + + @Mutation(() => DocType) + async revokePublicDoc( + @CurrentUser() user: CurrentUser, + @Args('workspaceId') workspaceId: string, + @Args('docId') rawDocId: string + ) { + const docId = new DocID(rawDocId, workspaceId); + + if (docId.isWorkspace) { + this.logger.error('Expect to revoke public doc, but it is a workspace', { + workspaceId, + docId: rawDocId, + }); + throw new ExpectToRevokePublicDoc('Expect doc not to be workspace'); + } + + await this.permission.checkPagePermission( + docId.workspace, + docId.guid, + 'Doc.Publish', + user.id + ); + + const isPublic = await this.permission.isPublicPage( + docId.workspace, + docId.guid + ); + + if (!isPublic) { + this.logger.log('Expect to revoke public doc, but it is not public', { + workspaceId, + docId: rawDocId, + }); + throw new DocIsNotPublic('Doc is not public'); + } + + this.logger.log('Revoke public doc', { + workspaceId, + docId: rawDocId, + }); + + return this.permission.revokePublicPage(docId.workspace, docId.guid); + } +} + +@Resolver(() => DocType) +export class DocResolver { + private readonly logger = new Logger(DocResolver.name); constructor( private readonly prisma: PrismaClient, @@ -168,96 +361,31 @@ export class PagePermissionResolver { private readonly models: Models ) {} - /** - * @deprecated - */ - @ResolveField(() => [String], { - description: 'Shared pages of workspace', - complexity: 2, - deprecationReason: 'use WorkspaceType.publicPages', - }) - async sharedPages(@Parent() workspace: WorkspaceType) { - const data = await this.prisma.workspacePage.findMany({ - where: { - workspaceId: workspace.id, - public: true, - }, - }); - - return data.map(row => row.pageId); - } - - @ResolveField(() => [WorkspacePage], { - description: 'Public pages of a workspace', - complexity: 2, - }) - async publicPages(@Parent() workspace: WorkspaceType) { - return this.prisma.workspacePage.findMany({ - where: { - workspaceId: workspace.id, - public: true, - }, - }); - } - - @ResolveField(() => WorkspacePage, { - description: 'Get public page of a workspace by page id.', - complexity: 2, - nullable: true, - }) - async publicPage( - @Parent() workspace: WorkspaceType, - @Args('pageId') pageId: string - ) { - return this.prisma.workspacePage.findFirst({ - where: { - workspaceId: workspace.id, - pageId, - public: true, - }, - }); - } - - @ResolveField(() => DocType, { - description: 'Check if current user has permission to access the page', - complexity: 2, - }) - async pagePermission( - @Parent() workspace: WorkspaceType, - @Args('pageId') pageId: string, - @CurrentUser() user: CurrentUser - ): Promise { - const page = await this.prisma.workspacePage.findFirst({ - where: { - workspaceId: workspace.id, - pageId, - }, - select: { - public: true, - }, - }); - + @ResolveField(() => DocPermissions) + async permissions( + @CurrentUser() user: CurrentUser, + @Parent() doc: DocType + ): Promise { const [permission, workspacePermission] = await this.prisma.$transaction( tx => Promise.all([ - tx.workspacePageUserPermission.findFirst({ + tx.workspaceDocUserPermission.findFirst({ where: { - workspaceId: workspace.id, - pageId, + workspaceId: doc.workspaceId, + docId: doc.docId, userId: user.id, }, }), tx.workspaceUserPermission.findFirst({ where: { - workspaceId: workspace.id, + workspaceId: doc.workspaceId, userId: user.id, }, }), ]) ); + return { - id: pageId, - public: page?.public ?? false, role: permission?.type ?? DocRole.External, permissions: mapDocRoleToPermissions( fixupDocRole(workspacePermission?.type, permission?.type) @@ -266,29 +394,27 @@ export class PagePermissionResolver { } @ResolveField(() => PaginatedGrantedDocUserType, { - description: 'Page granted users list', + description: 'paginated doc granted users list', complexity: 4, }) - async pageGrantedUsersList( + async grantedUsersList( @CurrentUser() user: CurrentUser, - @Parent() workspace: WorkspaceType, - @Args('pageId') pageId: string, + @Parent() doc: DocType, @Args('pagination') pagination: PaginationInput ): Promise { await this.permission.checkPagePermission( - workspace.id, - pageId, + doc.workspaceId, + doc.docId, 'Doc.Users.Read', user.id ); - const docId = new DocID(pageId, workspace.id); const [permissions, totalCount] = await this.prisma.$transaction(tx => { return Promise.all([ - tx.workspacePageUserPermission.findMany({ + tx.workspaceDocUserPermission.findMany({ where: { - workspaceId: workspace.id, - pageId: docId.guid, + workspaceId: doc.workspaceId, + docId: doc.docId, createdAt: pagination.after ? { gt: pagination.after, @@ -306,10 +432,10 @@ export class PagePermissionResolver { take: pagination.first, skip: pagination.offset, }), - tx.workspacePageUserPermission.count({ + tx.workspaceDocUserPermission.count({ where: { - workspaceId: workspace.id, - pageId: docId.guid, + workspaceId: doc.workspaceId, + docId: doc.docId, }, }), ]); @@ -338,121 +464,6 @@ export class PagePermissionResolver { ); } - /** - * @deprecated - */ - @Mutation(() => Boolean, { - name: 'sharePage', - deprecationReason: 'renamed to publishPage', - }) - async deprecatedSharePage( - @CurrentUser() user: CurrentUser, - @Args('workspaceId') workspaceId: string, - @Args('pageId') pageId: string - ) { - await this.publishPage(user, workspaceId, pageId, PublicPageMode.Page); - return true; - } - - @Mutation(() => WorkspacePage) - async publishPage( - @CurrentUser() user: CurrentUser, - @Args('workspaceId') workspaceId: string, - @Args('pageId') pageId: string, - @Args({ - name: 'mode', - type: () => PublicPageMode, - nullable: true, - defaultValue: PublicPageMode.Page, - }) - mode: PublicPageMode - ) { - const docId = new DocID(pageId, workspaceId); - - if (docId.isWorkspace) { - this.logger.error('Expect to publish page, but it is a workspace', { - workspaceId, - pageId, - }); - throw new ExpectToPublishPage(); - } - - await this.permission.checkPagePermission( - docId.workspace, - docId.guid, - 'Doc.Publish', - user.id - ); - - this.logger.log('Publish page', { - workspaceId, - pageId, - mode, - }); - - return this.permission.publishPage(docId.workspace, docId.guid, mode); - } - - /** - * @deprecated - */ - @Mutation(() => Boolean, { - name: 'revokePage', - deprecationReason: 'use revokePublicPage', - }) - async deprecatedRevokePage( - @CurrentUser() user: CurrentUser, - @Args('workspaceId') workspaceId: string, - @Args('pageId') pageId: string - ) { - await this.revokePublicPage(user, workspaceId, pageId); - return true; - } - - @Mutation(() => WorkspacePage) - async revokePublicPage( - @CurrentUser() user: CurrentUser, - @Args('workspaceId') workspaceId: string, - @Args('pageId') pageId: string - ) { - const docId = new DocID(pageId, workspaceId); - - if (docId.isWorkspace) { - this.logger.error('Expect to revoke public page, but it is a workspace', { - workspaceId, - pageId, - }); - throw new ExpectToRevokePublicPage('Expect page not to be workspace'); - } - - await this.permission.checkPagePermission( - docId.workspace, - docId.guid, - 'Doc.Publish', - user.id - ); - - const isPublic = await this.permission.isPublicPage( - docId.workspace, - docId.guid - ); - - if (!isPublic) { - this.logger.log('Expect to revoke public page, but it is not public', { - workspaceId, - pageId, - }); - throw new PageIsNotPublic('Page is not public'); - } - - this.logger.log('Revoke public page', { - workspaceId, - pageId, - }); - - return this.permission.revokePublicPage(docId.workspace, docId.guid); - } - @Mutation(() => Boolean) async grantDocUserRoles( @CurrentUser() user: CurrentUser, @@ -580,13 +591,13 @@ export class PagePermissionResolver { } @Mutation(() => Boolean) - async updatePageDefaultRole( + async updateDocDefaultRole( @CurrentUser() user: CurrentUser, - @Args('input') input: UpdatePageDefaultRoleInput + @Args('input') input: UpdateDocDefaultRoleInput ) { if (input.role === DocRole.Owner) { - this.logger.log('Page default role can not be owner', input); - throw new PageDefaultRoleCanNotBeOwner(); + this.logger.log('Doc default role can not be owner', input); + throw new DocDefaultRoleCanNotBeOwner(); } const doc = new DocID(input.docId, input.workspaceId); const pairs = { @@ -622,11 +633,11 @@ export class PagePermissionResolver { } throw error; } - await this.prisma.workspacePage.upsert({ + await this.prisma.workspaceDoc.upsert({ where: { - workspaceId_pageId: { + workspaceId_docId: { workspaceId: doc.workspace, - pageId: doc.guid, + docId: doc.guid, }, }, update: { @@ -634,7 +645,7 @@ export class PagePermissionResolver { }, create: { workspaceId: doc.workspace, - pageId: doc.guid, + docId: doc.guid, defaultRole: input.role, }, }); diff --git a/packages/backend/server/src/core/workspaces/resolvers/index.ts b/packages/backend/server/src/core/workspaces/resolvers/index.ts index f005d40359..3bf14d4a5b 100644 --- a/packages/backend/server/src/core/workspaces/resolvers/index.ts +++ b/packages/backend/server/src/core/workspaces/resolvers/index.ts @@ -1,6 +1,6 @@ export * from './blob'; +export * from './doc'; export * from './history'; -export * from './page'; export * from './service'; export * from './team'; export * from './workspace'; diff --git a/packages/backend/server/src/models/page.ts b/packages/backend/server/src/models/page.ts index b17dc23eb7..269b01ccae 100644 --- a/packages/backend/server/src/models/page.ts +++ b/packages/backend/server/src/models/page.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { Transactional } from '@nestjs-cls/transactional'; import { - type WorkspacePage as Page, - type WorkspacePageUserPermission as PageUserPermission, + type WorkspaceDoc as Page, + type WorkspaceDocUserPermission as PageUserPermission, } from '@prisma/client'; import { WorkspaceRole } from '../core/permission'; @@ -21,12 +21,12 @@ export class PageModel extends BaseModel { /** * Create or update the page. */ - async upsert(workspaceId: string, pageId: string, data?: UpdatePageInput) { - return await this.db.workspacePage.upsert({ + async upsert(workspaceId: string, docId: string, data?: UpdatePageInput) { + return await this.db.workspaceDoc.upsert({ where: { - workspaceId_pageId: { + workspaceId_docId: { workspaceId, - pageId, + docId, }, }, update: { @@ -35,7 +35,7 @@ export class PageModel extends BaseModel { create: { ...data, workspaceId, - pageId, + docId, }, }); } @@ -45,12 +45,12 @@ export class PageModel extends BaseModel { * @param isPublic: if true, only return the public page. If false, only return the private page. * If not set, return public or private both. */ - async get(workspaceId: string, pageId: string, isPublic?: boolean) { - return await this.db.workspacePage.findUnique({ + async get(workspaceId: string, docId: string, isPublic?: boolean) { + return await this.db.workspaceDoc.findUnique({ where: { - workspaceId_pageId: { + workspaceId_docId: { workspaceId, - pageId, + docId, }, public: isPublic, }, @@ -61,7 +61,7 @@ export class PageModel extends BaseModel { * Find the workspace public pages. */ async findPublics(workspaceId: string) { - return await this.db.workspacePage.findMany({ + return await this.db.workspaceDoc.findMany({ where: { workspaceId, public: true, @@ -73,7 +73,7 @@ export class PageModel extends BaseModel { * Get the workspace public pages count. */ async getPublicsCount(workspaceId: string) { - return await this.db.workspacePage.count({ + return await this.db.workspaceDoc.count({ where: { workspaceId, public: true, @@ -91,15 +91,15 @@ export class PageModel extends BaseModel { @Transactional() async grantMember( workspaceId: string, - pageId: string, + docId: string, userId: string, permission: WorkspaceRole = WorkspaceRole.Collaborator ): Promise { - let data = await this.db.workspacePageUserPermission.findUnique({ + let data = await this.db.workspaceDocUserPermission.findUnique({ where: { - workspaceId_pageId_userId: { + workspaceId_docId_userId: { workspaceId, - pageId, + docId, userId, }, }, @@ -109,11 +109,11 @@ export class PageModel extends BaseModel { if (!data || data.type !== permission) { if (data) { // Update the permission - data = await this.db.workspacePageUserPermission.update({ + data = await this.db.workspaceDocUserPermission.update({ where: { - workspaceId_pageId_userId: { + workspaceId_docId_userId: { workspaceId, - pageId, + docId, userId, }, }, @@ -121,10 +121,10 @@ export class PageModel extends BaseModel { }); } else { // Create a new permission - data = await this.db.workspacePageUserPermission.create({ + data = await this.db.workspaceDocUserPermission.create({ data: { workspaceId, - pageId, + docId, userId, type: permission, }, @@ -133,17 +133,17 @@ export class PageModel extends BaseModel { // If the new permission is owner, we need to revoke old owner if (permission === WorkspaceRole.Owner) { - await this.db.workspacePageUserPermission.updateMany({ + await this.db.workspaceDocUserPermission.updateMany({ where: { workspaceId, - pageId, + docId, type: WorkspaceRole.Owner, userId: { not: userId }, }, data: { type: WorkspaceRole.Admin }, }); this.logger.log( - `Change owner of workspace ${workspaceId} page ${pageId} to user ${userId}` + `Change owner of workspace ${workspaceId} doc ${docId} to user ${userId}` ); } return data; @@ -159,14 +159,14 @@ export class PageModel extends BaseModel { */ async isMember( workspaceId: string, - pageId: string, + docId: string, userId: string, permission: WorkspaceRole = WorkspaceRole.Collaborator ) { - const count = await this.db.workspacePageUserPermission.count({ + const count = await this.db.workspaceDocUserPermission.count({ where: { workspaceId, - pageId, + docId, userId, type: { gte: permission, @@ -180,11 +180,11 @@ export class PageModel extends BaseModel { * Delete a page member * Except the owner, the owner can't be deleted. */ - async deleteMember(workspaceId: string, pageId: string, userId: string) { - const { count } = await this.db.workspacePageUserPermission.deleteMany({ + async deleteMember(workspaceId: string, docId: string, userId: string) { + const { count } = await this.db.workspaceDocUserPermission.deleteMany({ where: { workspaceId, - pageId, + docId, userId, type: { // We shouldn't revoke owner permission, should auto deleted by workspace/user delete cascading diff --git a/packages/backend/server/src/schema.gql b/packages/backend/server/src/schema.gql index 4d3e7f5b5f..5d83e2ba79 100644 --- a/packages/backend/server/src/schema.gql +++ b/packages/backend/server/src/schema.gql @@ -230,10 +230,13 @@ enum DocRole { } type DocType { + """paginated doc granted users list""" + grantedUsersList(pagination: PaginationInput!): PaginatedGrantedDocUserType! id: String! + mode: PublicDocMode! permissions: DocPermissions! public: Boolean! - role: DocRole! + workspaceId: String! } type EditorType { @@ -254,7 +257,7 @@ enum ErrorNames { CANNOT_DELETE_ALL_ADMIN_ACCOUNT CANNOT_DELETE_OWN_ACCOUNT CANT_UPDATE_ONETIME_PAYMENT_SUBSCRIPTION - CAN_NOT_BATCH_GRANT_PAGE_OWNER_PERMISSIONS + CAN_NOT_BATCH_GRANT_DOC_OWNER_PERMISSIONS CAPTCHA_VERIFICATION_FAILED COPILOT_ACTION_TAKEN COPILOT_FAILED_TO_CREATE_MESSAGE @@ -268,16 +271,18 @@ enum ErrorNames { COPILOT_SESSION_NOT_FOUND CUSTOMER_PORTAL_CREATE_FAILED DOC_ACCESS_DENIED + DOC_DEFAULT_ROLE_CAN_NOT_BE_OWNER DOC_HISTORY_NOT_FOUND + DOC_IS_NOT_PUBLIC DOC_NOT_FOUND EARLY_ACCESS_REQUIRED EMAIL_ALREADY_USED EMAIL_TOKEN_NOT_FOUND EMAIL_VERIFICATION_REQUIRED EXPECT_TO_GRANT_DOC_USER_ROLES - EXPECT_TO_PUBLISH_PAGE + EXPECT_TO_PUBLISH_DOC EXPECT_TO_REVOKE_DOC_USER_ROLES - EXPECT_TO_REVOKE_PUBLIC_PAGE + EXPECT_TO_REVOKE_PUBLIC_DOC EXPECT_TO_UPDATE_DOC_USER_ROLE FAILED_TO_CHECKOUT FAILED_TO_SAVE_UPDATES @@ -306,8 +311,6 @@ enum ErrorNames { NO_COPILOT_PROVIDER_AVAILABLE OAUTH_ACCOUNT_ALREADY_CONNECTED OAUTH_STATE_EXPIRED - PAGE_DEFAULT_ROLE_CAN_NOT_BE_OWNER - PAGE_IS_NOT_PUBLIC PASSWORD_REQUIRED QUERY_TOO_LONG RUNTIME_CONFIG_NOT_FOUND @@ -621,7 +624,8 @@ type Mutation { invite(email: String!, permission: Permission @deprecated(reason: "never used"), sendInviteMail: Boolean, workspaceId: String!): String! inviteBatch(emails: [String!]!, sendInviteMail: Boolean, workspaceId: String!): [InviteResult!]! leaveWorkspace(sendLeaveMail: Boolean, workspaceId: String!, workspaceName: String @deprecated(reason: "no longer used")): Boolean! - publishPage(mode: PublicPageMode = Page, pageId: String!, workspaceId: String!): WorkspacePage! + publishDoc(docId: String!, mode: PublicDocMode = Page, workspaceId: String!): DocType! + publishPage(mode: PublicDocMode = Page, pageId: String!, workspaceId: String!): DocType! @deprecated(reason: "use publishDoc instead") recoverDoc(guid: String!, timestamp: DateTime!, workspaceId: String!): DateTime! releaseDeletedBlobs(workspaceId: String!): Boolean! @@ -632,23 +636,22 @@ type Mutation { revoke(userId: String!, workspaceId: String!): Boolean! revokeDocUserRoles(input: RevokeDocUserRoleInput!): Boolean! revokeInviteLink(workspaceId: String!): Boolean! - revokePage(pageId: String!, workspaceId: String!): Boolean! @deprecated(reason: "use revokePublicPage") - revokePublicPage(pageId: String!, workspaceId: String!): WorkspacePage! + revokePublicDoc(docId: String!, workspaceId: String!): DocType! + revokePublicPage(docId: String!, workspaceId: String!): DocType! @deprecated(reason: "use revokePublicDoc instead") sendChangeEmail(callbackUrl: String!, email: String): Boolean! sendChangePasswordEmail(callbackUrl: String!, email: String @deprecated(reason: "fetched from signed in user")): Boolean! sendSetPasswordEmail(callbackUrl: String!, email: String @deprecated(reason: "fetched from signed in user")): Boolean! sendVerifyChangeEmail(callbackUrl: String!, email: String!, token: String!): Boolean! sendVerifyEmail(callbackUrl: String!): Boolean! setBlob(blob: Upload!, workspaceId: String!): String! - sharePage(pageId: String!, workspaceId: String!): Boolean! @deprecated(reason: "renamed to publishPage") """Update a copilot prompt""" updateCopilotPrompt(messages: [CopilotPromptMessageInput!]!, name: String!): CopilotPromptType! """Update a chat session""" updateCopilotSession(options: UpdateChatSessionInput!): String! + updateDocDefaultRole(input: UpdateDocDefaultRoleInput!): Boolean! updateDocUserRole(input: UpdateDocUserRoleInput!): Boolean! - updatePageDefaultRole(input: UpdatePageDefaultRoleInput!): Boolean! updateProfile(input: UpdateUserInput!): UserType! """update server runtime configurable setting""" @@ -719,8 +722,8 @@ enum Permission { Owner } -"""The mode which the public page default in""" -enum PublicPageMode { +"""The mode which the public doc default in""" +enum PublicDocMode { Edgeless Page } @@ -1005,6 +1008,12 @@ input UpdateChatSessionInput { sessionId: String! } +input UpdateDocDefaultRoleInput { + docId: String! + role: DocRole! + workspaceId: String! +} + input UpdateDocUserRoleInput { docId: String! role: DocRole! @@ -1012,12 +1021,6 @@ input UpdateDocUserRoleInput { workspaceId: String! } -input UpdatePageDefaultRoleInput { - docId: String! - role: DocRole! - workspaceId: String! -} - input UpdateUserInput { """User name""" name: String @@ -1128,13 +1131,6 @@ type WorkspaceMembersExceedLimitToDowngradeDataType { limit: Int! } -type WorkspacePage { - id: String! - mode: PublicPageMode! - public: Boolean! - workspaceId: String! -} - type WorkspacePageMeta { createdAt: DateTime! createdBy: EditorType @@ -1199,6 +1195,9 @@ type WorkspaceType { """Workspace created date""" createdAt: DateTime! + """Get get with given id""" + doc(docId: String!): DocType! + """Enable AI""" enableAi: Boolean! @@ -1229,23 +1228,21 @@ type WorkspaceType { """Owner of workspace""" owner: UserType! - """Page granted users list""" - pageGrantedUsersList(pageId: String!, pagination: PaginationInput!): PaginatedGrantedDocUserType! - """Cloud page metadata of workspace""" pageMeta(pageId: String!): WorkspacePageMeta! - """Check if current user has permission to access the page""" - pagePermission(pageId: String!): DocType! - """is Public workspace""" public: Boolean! """Get public page of a workspace by page id.""" - publicPage(pageId: String!): WorkspacePage + publicDoc(docId: String!): DocType - """Public pages of a workspace""" - publicPages: [WorkspacePage!]! + """Get public docs of a workspace""" + publicDocs: [DocType!]! + + """Get public page of a workspace by page id.""" + publicPage(pageId: String!): DocType @deprecated(reason: "use [WorkspaceType.publicDoc] instead") + publicPages: [DocType!]! @deprecated(reason: "use [WorkspaceType.publicDocs] instead") """quota of workspace""" quota: WorkspaceQuotaType! @@ -1253,9 +1250,6 @@ type WorkspaceType { """Role of current signed in user in workspace""" role: Permission! - """Shared pages of workspace""" - sharedPages: [String!]! @deprecated(reason: "use WorkspaceType.publicPages") - """The team subscription of the workspace, if exists.""" subscription: SubscriptionType diff --git a/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx b/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx index 6bf7c7ba1e..9f032eb5fb 100644 --- a/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx +++ b/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx @@ -6,7 +6,7 @@ import { ServerService } from '@affine/core/modules/cloud'; import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { WorkspacePermissionService } from '@affine/core/modules/permissions'; import { ShareInfoService } from '@affine/core/modules/share-doc'; -import { PublicPageMode } from '@affine/graphql'; +import { PublicDocMode } from '@affine/graphql'; import { useI18n } from '@affine/i18n'; import { track } from '@affine/track'; import { @@ -92,7 +92,7 @@ export const AFFiNESharePage = (props: ShareMenuProps) => { } try { // TODO(@JimmFly): remove mode when we have a better way to handle it - await shareInfoService.shareInfo.enableShare(PublicPageMode.Page); + await shareInfoService.shareInfo.enableShare(PublicDocMode.Page); track.$.sharePanel.$.createShareLink(); notify.success({ title: diff --git a/packages/frontend/core/src/components/hooks/affine/use-all-page-list-config.tsx b/packages/frontend/core/src/components/hooks/affine/use-all-page-list-config.tsx index 308dde7cd7..36f23bf7d7 100644 --- a/packages/frontend/core/src/components/hooks/affine/use-all-page-list-config.tsx +++ b/packages/frontend/core/src/components/hooks/affine/use-all-page-list-config.tsx @@ -4,7 +4,7 @@ import { FavoriteTag } from '@affine/core/components/page-list/components/favori import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite'; import { ShareDocsListService } from '@affine/core/modules/share-doc'; import { WorkspaceService } from '@affine/core/modules/workspace'; -import { PublicPageMode } from '@affine/graphql'; +import { PublicDocMode } from '@affine/graphql'; import { useI18n } from '@affine/i18n'; import type { DocMeta, Workspace } from '@blocksuite/affine/store'; import { useLiveData, useService } from '@toeverything/infra'; @@ -68,9 +68,9 @@ export const useAllPageListConfig = () => { allPages: pageMetas, getPublicMode(id) { const mode = shareDocs?.find(shareDoc => shareDoc.id === id)?.mode; - if (mode === PublicPageMode.Edgeless) { + if (mode === PublicDocMode.Edgeless) { return 'edgeless'; - } else if (mode === PublicPageMode.Page) { + } else if (mode === PublicDocMode.Page) { return 'page'; } else { return undefined; diff --git a/packages/frontend/core/src/components/page-list/docs/select-page.tsx b/packages/frontend/core/src/components/page-list/docs/select-page.tsx index eac410f3e5..d30772be08 100644 --- a/packages/frontend/core/src/components/page-list/docs/select-page.tsx +++ b/packages/frontend/core/src/components/page-list/docs/select-page.tsx @@ -3,7 +3,7 @@ import { useBlockSuiteDocMeta } from '@affine/core/components/hooks/use-block-su import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite'; import { ShareDocsListService } from '@affine/core/modules/share-doc'; import { WorkspaceService } from '@affine/core/modules/workspace'; -import { PublicPageMode } from '@affine/graphql'; +import { PublicDocMode } from '@affine/graphql'; import { Trans, useI18n } from '@affine/i18n'; import type { DocMeta } from '@blocksuite/affine/store'; import { FilterIcon } from '@blocksuite/icons/rc'; @@ -76,9 +76,9 @@ export const SelectPage = ({ const getPublicMode = useCallback( (id: string) => { const mode = shareDocs?.find(shareDoc => shareDoc.id === id)?.mode; - if (mode === PublicPageMode.Edgeless) { + if (mode === PublicDocMode.Edgeless) { return 'edgeless'; - } else if (mode === PublicPageMode.Page) { + } else if (mode === PublicDocMode.Page) { return 'page'; } else { return undefined; diff --git a/packages/frontend/core/src/components/page-list/use-filtered-page-metas.tsx b/packages/frontend/core/src/components/page-list/use-filtered-page-metas.tsx index 140c9720ac..d40ff56844 100644 --- a/packages/frontend/core/src/components/page-list/use-filtered-page-metas.tsx +++ b/packages/frontend/core/src/components/page-list/use-filtered-page-metas.tsx @@ -1,7 +1,7 @@ import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite'; import { ShareDocsListService } from '@affine/core/modules/share-doc'; import type { Collection, Filter } from '@affine/env/filter'; -import { PublicPageMode } from '@affine/graphql'; +import { PublicDocMode } from '@affine/graphql'; import type { DocMeta } from '@blocksuite/affine/store'; import { useLiveData, useService } from '@toeverything/infra'; import { useCallback, useEffect, useMemo } from 'react'; @@ -23,7 +23,7 @@ export const useFilteredPageMetas = ( (id: string) => { const mode = shareDocs?.find(shareDoc => shareDoc.id === id)?.mode; return mode - ? mode === PublicPageMode.Edgeless + ? mode === PublicDocMode.Edgeless ? ('edgeless' as const) : ('page' as const) : undefined; diff --git a/packages/frontend/core/src/mobile/components/explorer/nodes/collection/index.tsx b/packages/frontend/core/src/mobile/components/explorer/nodes/collection/index.tsx index 645b9d0dc2..c89a7ca9ef 100644 --- a/packages/frontend/core/src/mobile/components/explorer/nodes/collection/index.tsx +++ b/packages/frontend/core/src/mobile/components/explorer/nodes/collection/index.tsx @@ -8,7 +8,7 @@ import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite'; import { GlobalContextService } from '@affine/core/modules/global-context'; import { ShareDocsListService } from '@affine/core/modules/share-doc'; import type { Collection } from '@affine/env/filter'; -import { PublicPageMode } from '@affine/graphql'; +import { PublicDocMode } from '@affine/graphql'; import { useI18n } from '@affine/i18n'; import track from '@affine/track'; import type { DocMeta } from '@blocksuite/affine/store'; @@ -161,9 +161,9 @@ const ExplorerCollectionNodeChildren = ({ const pageData = { meta: meta as DocMeta, publicMode: - publicMode === PublicPageMode.Edgeless + publicMode === PublicDocMode.Edgeless ? ('edgeless' as const) - : publicMode === PublicPageMode.Page + : publicMode === PublicDocMode.Page ? ('page' as const) : undefined, favorite: favourites.some(fav => fav.id === meta.id), diff --git a/packages/frontend/core/src/modules/explorer/views/nodes/collection/index.tsx b/packages/frontend/core/src/modules/explorer/views/nodes/collection/index.tsx index 746c6be8ff..89732d8231 100644 --- a/packages/frontend/core/src/modules/explorer/views/nodes/collection/index.tsx +++ b/packages/frontend/core/src/modules/explorer/views/nodes/collection/index.tsx @@ -14,7 +14,7 @@ import { GlobalContextService } from '@affine/core/modules/global-context'; import { ShareDocsListService } from '@affine/core/modules/share-doc'; import type { AffineDNDData } from '@affine/core/types/dnd'; import type { Collection } from '@affine/env/filter'; -import { PublicPageMode } from '@affine/graphql'; +import { PublicDocMode } from '@affine/graphql'; import { useI18n } from '@affine/i18n'; import { track } from '@affine/track'; import type { DocMeta } from '@blocksuite/affine/store'; @@ -283,9 +283,9 @@ const ExplorerCollectionNodeChildren = ({ const pageData = { meta: meta as DocMeta, publicMode: - publicMode === PublicPageMode.Edgeless + publicMode === PublicDocMode.Edgeless ? ('edgeless' as const) - : publicMode === PublicPageMode.Page + : publicMode === PublicDocMode.Page ? ('page' as const) : undefined, favorite: favourites.some(fav => fav.id === meta.id), diff --git a/packages/frontend/core/src/modules/share-doc/entities/share-docs-list.ts b/packages/frontend/core/src/modules/share-doc/entities/share-docs-list.ts index 17fb637cb8..e7e281a7dd 100644 --- a/packages/frontend/core/src/modules/share-doc/entities/share-docs-list.ts +++ b/packages/frontend/core/src/modules/share-doc/entities/share-docs-list.ts @@ -18,8 +18,7 @@ import type { GlobalCache } from '../../storage'; import type { WorkspaceService } from '../../workspace'; import type { ShareDocsStore } from '../stores/share-docs'; -type ShareDocListType = - GetWorkspacePublicPagesQuery['workspace']['publicPages']; +type ShareDocListType = GetWorkspacePublicPagesQuery['workspace']['publicDocs']; export const logger = new DebugLogger('affine:share-doc-list'); diff --git a/packages/frontend/core/src/modules/share-doc/entities/share-info.ts b/packages/frontend/core/src/modules/share-doc/entities/share-info.ts index 926646d0e3..af80bb8284 100644 --- a/packages/frontend/core/src/modules/share-doc/entities/share-info.ts +++ b/packages/frontend/core/src/modules/share-doc/entities/share-info.ts @@ -1,6 +1,6 @@ import type { GetWorkspacePublicPageByIdQuery, - PublicPageMode, + PublicDocMode, } from '@affine/graphql'; import { backoffRetry, @@ -20,7 +20,7 @@ import type { DocService } from '../../doc'; import type { WorkspaceService } from '../../workspace'; import type { ShareStore } from '../stores/share'; -type ShareInfoType = GetWorkspacePublicPageByIdQuery['workspace']['publicPage']; +type ShareInfoType = GetWorkspacePublicPageByIdQuery['workspace']['publicDoc']; export class ShareInfo extends Entity { info$ = new LiveData(null); @@ -70,7 +70,7 @@ export class ShareInfo extends Entity { return this.isRevalidating$.waitFor(v => v === false, signal); } - async enableShare(mode: PublicPageMode) { + async enableShare(mode: PublicDocMode) { await this.store.enableSharePage( this.workspaceService.workspace.id, this.docService.doc.id, @@ -79,7 +79,7 @@ export class ShareInfo extends Entity { await this.waitForRevalidation(); } - async changeShare(mode: PublicPageMode) { + async changeShare(mode: PublicDocMode) { await this.enableShare(mode); } diff --git a/packages/frontend/core/src/modules/share-doc/stores/share-docs.ts b/packages/frontend/core/src/modules/share-doc/stores/share-docs.ts index 79f23cedae..7c88375de0 100644 --- a/packages/frontend/core/src/modules/share-doc/stores/share-docs.ts +++ b/packages/frontend/core/src/modules/share-doc/stores/share-docs.ts @@ -20,6 +20,6 @@ export class ShareDocsStore extends Store { signal, }, }); - return data.workspace.publicPages; + return data.workspace.publicDocs; } } diff --git a/packages/frontend/core/src/modules/share-doc/stores/share.ts b/packages/frontend/core/src/modules/share-doc/stores/share.ts index 2555102ff2..d15a45935d 100644 --- a/packages/frontend/core/src/modules/share-doc/stores/share.ts +++ b/packages/frontend/core/src/modules/share-doc/stores/share.ts @@ -1,4 +1,4 @@ -import type { PublicPageMode } from '@affine/graphql'; +import type { PublicDocMode } from '@affine/graphql'; import { getWorkspacePublicPageByIdQuery, publishPageMutation, @@ -31,13 +31,13 @@ export class ShareStore extends Store { signal, }, }); - return data.workspace.publicPage ?? undefined; + return data.workspace.publicDoc ?? undefined; } async enableSharePage( workspaceId: string, pageId: string, - docMode?: PublicPageMode, + docMode?: PublicDocMode, signal?: AbortSignal ) { if (!this.workspaceServerService.server) { diff --git a/packages/frontend/graphql/src/graphql/get-workspace-public-page-by-id.gql b/packages/frontend/graphql/src/graphql/get-workspace-public-page-by-id.gql index e5ccaa7605..b3c335f430 100644 --- a/packages/frontend/graphql/src/graphql/get-workspace-public-page-by-id.gql +++ b/packages/frontend/graphql/src/graphql/get-workspace-public-page-by-id.gql @@ -1,6 +1,6 @@ query getWorkspacePublicPageById($workspaceId: String!, $pageId: String!) { workspace(id: $workspaceId) { - publicPage(pageId: $pageId) { + publicDoc(docId: $pageId) { id mode } diff --git a/packages/frontend/graphql/src/graphql/get-workspace-public-pages.gql b/packages/frontend/graphql/src/graphql/get-workspace-public-pages.gql index fcfd7fc6e7..8a1e371b2f 100644 --- a/packages/frontend/graphql/src/graphql/get-workspace-public-pages.gql +++ b/packages/frontend/graphql/src/graphql/get-workspace-public-pages.gql @@ -1,6 +1,6 @@ query getWorkspacePublicPages($workspaceId: String!) { workspace(id: $workspaceId) { - publicPages { + publicDocs { id mode } diff --git a/packages/frontend/graphql/src/graphql/index.ts b/packages/frontend/graphql/src/graphql/index.ts index f1388c9d67..265c13c75f 100644 --- a/packages/frontend/graphql/src/graphql/index.ts +++ b/packages/frontend/graphql/src/graphql/index.ts @@ -752,7 +752,7 @@ export const getWorkspacePublicPageByIdQuery = { query: ` query getWorkspacePublicPageById($workspaceId: String!, $pageId: String!) { workspace(id: $workspaceId) { - publicPage(pageId: $pageId) { + publicDoc(docId: $pageId) { id mode } @@ -768,7 +768,7 @@ export const getWorkspacePublicPagesQuery = { query: ` query getWorkspacePublicPages($workspaceId: String!) { workspace(id: $workspaceId) { - publicPages { + publicDocs { id mode } @@ -937,11 +937,11 @@ query prices { export const publishPageMutation = { id: 'publishPageMutation' as const, operationName: 'publishPage', - definitionName: 'publishPage', + definitionName: 'publishDoc', containsFile: false, query: ` -mutation publishPage($workspaceId: String!, $pageId: String!, $mode: PublicPageMode = Page) { - publishPage(workspaceId: $workspaceId, pageId: $pageId, mode: $mode) { +mutation publishPage($workspaceId: String!, $pageId: String!, $mode: PublicDocMode = Page) { + publishDoc(workspaceId: $workspaceId, docId: $pageId, mode: $mode) { id mode } @@ -1033,11 +1033,11 @@ mutation revokeMemberPermission($workspaceId: String!, $userId: String!) { export const revokePublicPageMutation = { id: 'revokePublicPageMutation' as const, operationName: 'revokePublicPage', - definitionName: 'revokePublicPage', + definitionName: 'revokePublicDoc', containsFile: false, query: ` mutation revokePublicPage($workspaceId: String!, $pageId: String!) { - revokePublicPage(workspaceId: $workspaceId, pageId: $pageId) { + revokePublicDoc(workspaceId: $workspaceId, docId: $pageId) { id mode public diff --git a/packages/frontend/graphql/src/graphql/public-page.gql b/packages/frontend/graphql/src/graphql/public-page.gql index 7074bc153a..31926f865f 100644 --- a/packages/frontend/graphql/src/graphql/public-page.gql +++ b/packages/frontend/graphql/src/graphql/public-page.gql @@ -1,9 +1,9 @@ mutation publishPage( $workspaceId: String! $pageId: String! - $mode: PublicPageMode = Page + $mode: PublicDocMode = Page ) { - publishPage(workspaceId: $workspaceId, pageId: $pageId, mode: $mode) { + publishDoc(workspaceId: $workspaceId, docId: $pageId, mode: $mode) { id mode } diff --git a/packages/frontend/graphql/src/graphql/revoke-public-page.gql b/packages/frontend/graphql/src/graphql/revoke-public-page.gql index 1515b3d501..9bbaf0c2d0 100644 --- a/packages/frontend/graphql/src/graphql/revoke-public-page.gql +++ b/packages/frontend/graphql/src/graphql/revoke-public-page.gql @@ -1,5 +1,5 @@ mutation revokePublicPage($workspaceId: String!, $pageId: String!) { - revokePublicPage(workspaceId: $workspaceId, pageId: $pageId) { + revokePublicDoc(workspaceId: $workspaceId, docId: $pageId) { id mode public diff --git a/packages/frontend/graphql/src/schema.ts b/packages/frontend/graphql/src/schema.ts index 9bd59907ea..dbbde1a9ca 100644 --- a/packages/frontend/graphql/src/schema.ts +++ b/packages/frontend/graphql/src/schema.ts @@ -253,6 +253,23 @@ export interface DocNotFoundDataType { spaceId: Scalars['String']['output']; } +export interface DocPermissions { + __typename?: 'DocPermissions'; + Doc_Copy: Scalars['Boolean']['output']; + Doc_Delete: Scalars['Boolean']['output']; + Doc_Duplicate: Scalars['Boolean']['output']; + Doc_Properties_Read: Scalars['Boolean']['output']; + Doc_Properties_Update: Scalars['Boolean']['output']; + Doc_Publish: Scalars['Boolean']['output']; + Doc_Read: Scalars['Boolean']['output']; + Doc_Restore: Scalars['Boolean']['output']; + Doc_TransferOwner: Scalars['Boolean']['output']; + Doc_Trash: Scalars['Boolean']['output']; + Doc_Update: Scalars['Boolean']['output']; + Doc_Users_Manage: Scalars['Boolean']['output']; + Doc_Users_Read: Scalars['Boolean']['output']; +} + /** User permission in doc */ export enum DocRole { Editor = 'Editor', @@ -264,10 +281,17 @@ export enum DocRole { export interface DocType { __typename?: 'DocType'; + /** paginated doc granted users list */ + grantedUsersList: PaginatedGrantedDocUserType; id: Scalars['String']['output']; - permissions: RolePermissions; + mode: PublicDocMode; + permissions: DocPermissions; public: Scalars['Boolean']['output']; - role: DocRole; + workspaceId: Scalars['String']['output']; +} + +export interface DocTypeGrantedUsersListArgs { + pagination: PaginationInput; } export interface EditorType { @@ -337,16 +361,18 @@ export enum ErrorNames { COPILOT_SESSION_NOT_FOUND = 'COPILOT_SESSION_NOT_FOUND', CUSTOMER_PORTAL_CREATE_FAILED = 'CUSTOMER_PORTAL_CREATE_FAILED', DOC_ACCESS_DENIED = 'DOC_ACCESS_DENIED', + DOC_DEFAULT_ROLE_CAN_NOT_BE_OWNER = 'DOC_DEFAULT_ROLE_CAN_NOT_BE_OWNER', DOC_HISTORY_NOT_FOUND = 'DOC_HISTORY_NOT_FOUND', + DOC_IS_NOT_PUBLIC = 'DOC_IS_NOT_PUBLIC', DOC_NOT_FOUND = 'DOC_NOT_FOUND', EARLY_ACCESS_REQUIRED = 'EARLY_ACCESS_REQUIRED', EMAIL_ALREADY_USED = 'EMAIL_ALREADY_USED', EMAIL_TOKEN_NOT_FOUND = 'EMAIL_TOKEN_NOT_FOUND', EMAIL_VERIFICATION_REQUIRED = 'EMAIL_VERIFICATION_REQUIRED', EXPECT_TO_GRANT_DOC_USER_ROLES = 'EXPECT_TO_GRANT_DOC_USER_ROLES', - EXPECT_TO_PUBLISH_PAGE = 'EXPECT_TO_PUBLISH_PAGE', + EXPECT_TO_PUBLISH_DOC = 'EXPECT_TO_PUBLISH_DOC', EXPECT_TO_REVOKE_DOC_USER_ROLES = 'EXPECT_TO_REVOKE_DOC_USER_ROLES', - EXPECT_TO_REVOKE_PUBLIC_PAGE = 'EXPECT_TO_REVOKE_PUBLIC_PAGE', + EXPECT_TO_REVOKE_PUBLIC_DOC = 'EXPECT_TO_REVOKE_PUBLIC_DOC', EXPECT_TO_UPDATE_DOC_USER_ROLE = 'EXPECT_TO_UPDATE_DOC_USER_ROLE', FAILED_TO_CHECKOUT = 'FAILED_TO_CHECKOUT', FAILED_TO_SAVE_UPDATES = 'FAILED_TO_SAVE_UPDATES', @@ -375,7 +401,6 @@ export enum ErrorNames { NO_COPILOT_PROVIDER_AVAILABLE = 'NO_COPILOT_PROVIDER_AVAILABLE', OAUTH_ACCOUNT_ALREADY_CONNECTED = 'OAUTH_ACCOUNT_ALREADY_CONNECTED', OAUTH_STATE_EXPIRED = 'OAUTH_STATE_EXPIRED', - PAGE_IS_NOT_PUBLIC = 'PAGE_IS_NOT_PUBLIC', PASSWORD_REQUIRED = 'PASSWORD_REQUIRED', QUERY_TOO_LONG = 'QUERY_TOO_LONG', RUNTIME_CONFIG_NOT_FOUND = 'RUNTIME_CONFIG_NOT_FOUND', @@ -453,23 +478,16 @@ export interface GrantDocUserRolesInput { workspaceId: Scalars['String']['input']; } -export interface GrantedDocUserEdge { - __typename?: 'GrantedDocUserEdge'; - cursor: Scalars['String']['output']; - user: GrantedDocUserType; -} - export interface GrantedDocUserType { __typename?: 'GrantedDocUserType'; role: DocRole; - user: UserType; + user: PublicUserType; } -export interface GrantedDocUsersConnection { - __typename?: 'GrantedDocUsersConnection'; - edges: Array; - pageInfo: PageInfo; - totalCount: Scalars['Int']['output']; +export interface GrantedDocUserTypeEdge { + __typename?: 'GrantedDocUserTypeEdge'; + cursor: Scalars['String']['output']; + node: GrantedDocUserType; } export interface InvalidEmailDataType { @@ -688,7 +706,9 @@ export interface Mutation { invite: Scalars['String']['output']; inviteBatch: Array; leaveWorkspace: Scalars['Boolean']['output']; - publishPage: WorkspacePage; + publishDoc: DocType; + /** @deprecated use publishDoc instead */ + publishPage: DocType; recoverDoc: Scalars['DateTime']['output']; releaseDeletedBlobs: Scalars['Boolean']['output']; /** Remove user avatar */ @@ -698,21 +718,20 @@ export interface Mutation { revoke: Scalars['Boolean']['output']; revokeDocUserRoles: Scalars['Boolean']['output']; revokeInviteLink: Scalars['Boolean']['output']; - /** @deprecated use revokePublicPage */ - revokePage: Scalars['Boolean']['output']; - revokePublicPage: WorkspacePage; + revokePublicDoc: DocType; + /** @deprecated use revokePublicDoc instead */ + revokePublicPage: DocType; sendChangeEmail: Scalars['Boolean']['output']; sendChangePasswordEmail: Scalars['Boolean']['output']; sendSetPasswordEmail: Scalars['Boolean']['output']; sendVerifyChangeEmail: Scalars['Boolean']['output']; sendVerifyEmail: Scalars['Boolean']['output']; setBlob: Scalars['String']['output']; - /** @deprecated renamed to publishPage */ - sharePage: Scalars['Boolean']['output']; /** Update a copilot prompt */ updateCopilotPrompt: CopilotPromptType; /** Update a chat session */ updateCopilotSession: Scalars['String']['output']; + updateDocDefaultRole: Scalars['Boolean']['output']; updateDocUserRole: Scalars['Boolean']['output']; updateProfile: UserType; /** update server runtime configurable setting */ @@ -867,8 +886,14 @@ export interface MutationLeaveWorkspaceArgs { workspaceName?: InputMaybe; } +export interface MutationPublishDocArgs { + docId: Scalars['String']['input']; + mode?: InputMaybe; + workspaceId: Scalars['String']['input']; +} + export interface MutationPublishPageArgs { - mode?: InputMaybe; + mode?: InputMaybe; pageId: Scalars['String']['input']; workspaceId: Scalars['String']['input']; } @@ -900,21 +925,20 @@ export interface MutationRevokeArgs { } export interface MutationRevokeDocUserRolesArgs { - docId: Scalars['String']['input']; - userIds: Array; + input: RevokeDocUserRolesInput; } export interface MutationRevokeInviteLinkArgs { workspaceId: Scalars['String']['input']; } -export interface MutationRevokePageArgs { - pageId: Scalars['String']['input']; +export interface MutationRevokePublicDocArgs { + docId: Scalars['String']['input']; workspaceId: Scalars['String']['input']; } export interface MutationRevokePublicPageArgs { - pageId: Scalars['String']['input']; + docId: Scalars['String']['input']; workspaceId: Scalars['String']['input']; } @@ -948,11 +972,6 @@ export interface MutationSetBlobArgs { workspaceId: Scalars['String']['input']; } -export interface MutationSharePageArgs { - pageId: Scalars['String']['input']; - workspaceId: Scalars['String']['input']; -} - export interface MutationUpdateCopilotPromptArgs { messages: Array; name: Scalars['String']['input']; @@ -962,10 +981,12 @@ export interface MutationUpdateCopilotSessionArgs { options: UpdateChatSessionInput; } +export interface MutationUpdateDocDefaultRoleArgs { + input: UpdateDocDefaultRoleInput; +} + export interface MutationUpdateDocUserRoleArgs { - docId: Scalars['String']['input']; - role: DocRole; - userId: Scalars['String']['input']; + input: UpdateDocUserRoleInput; } export interface MutationUpdateProfileArgs { @@ -1021,15 +1042,6 @@ export enum OAuthProviderType { OIDC = 'OIDC', } -export interface PageGrantedUsersInput { - /** Cursor */ - after?: InputMaybe; - /** Cursor */ - before?: InputMaybe; - first: Scalars['Int']['input']; - offset: Scalars['Int']['input']; -} - export interface PageInfo { __typename?: 'PageInfo'; endCursor: Maybe; @@ -1038,6 +1050,22 @@ export interface PageInfo { startCursor: Maybe; } +export interface PaginatedGrantedDocUserType { + __typename?: 'PaginatedGrantedDocUserType'; + edges: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +} + +export interface PaginationInput { + /** returns the elements in the list that come after the specified cursor. */ + after?: InputMaybe; + /** returns the first n elements from the list. */ + first?: InputMaybe; + /** ignore the first n elements from the list. */ + offset?: InputMaybe; +} + export interface PasswordLimitsType { __typename?: 'PasswordLimitsType'; maxLength: Scalars['Int']['output']; @@ -1052,12 +1080,20 @@ export enum Permission { Owner = 'Owner', } -/** The mode which the public page default in */ -export enum PublicPageMode { +/** The mode which the public doc default in */ +export enum PublicDocMode { Edgeless = 'Edgeless', Page = 'Page', } +export interface PublicUserType { + __typename?: 'PublicUserType'; + avatarUrl: Maybe; + email: Scalars['String']['output']; + id: Scalars['String']['output']; + name: Scalars['String']['output']; +} + export interface Query { __typename?: 'Query'; /** @deprecated use `user.quotaUsage` instead */ @@ -1166,34 +1202,10 @@ export interface RemoveAvatar { success: Scalars['Boolean']['output']; } -export interface RolePermissions { - __typename?: 'RolePermissions'; - Doc_Copy: Scalars['Boolean']['output']; - Doc_Delete: Scalars['Boolean']['output']; - Doc_Duplicate: Scalars['Boolean']['output']; - Doc_Properties_Read: Scalars['Boolean']['output']; - Doc_Properties_Update: Scalars['Boolean']['output']; - Doc_Publish: Scalars['Boolean']['output']; - Doc_Read: Scalars['Boolean']['output']; - Doc_Restore: Scalars['Boolean']['output']; - Doc_TransferOwner: Scalars['Boolean']['output']; - Doc_Trash: Scalars['Boolean']['output']; - Doc_Update: Scalars['Boolean']['output']; - Doc_Users_Manage: Scalars['Boolean']['output']; - Doc_Users_Read: Scalars['Boolean']['output']; - Workspace_CreateDoc: Scalars['Boolean']['output']; - Workspace_Delete: Scalars['Boolean']['output']; - Workspace_Organize_Read: Scalars['Boolean']['output']; - Workspace_Properties_Create: Scalars['Boolean']['output']; - Workspace_Properties_Delete: Scalars['Boolean']['output']; - Workspace_Properties_Read: Scalars['Boolean']['output']; - Workspace_Properties_Update: Scalars['Boolean']['output']; - Workspace_Settings_Read: Scalars['Boolean']['output']; - Workspace_Settings_Update: Scalars['Boolean']['output']; - Workspace_Sync: Scalars['Boolean']['output']; - Workspace_TransferOwner: Scalars['Boolean']['output']; - Workspace_Users_Manage: Scalars['Boolean']['output']; - Workspace_Users_Read: Scalars['Boolean']['output']; +export interface RevokeDocUserRolesInput { + docId: Scalars['String']['input']; + userIds: Array; + workspaceId: Scalars['String']['input']; } export interface RuntimeConfigNotFoundDataType { @@ -1395,6 +1407,19 @@ export interface UpdateChatSessionInput { sessionId: Scalars['String']['input']; } +export interface UpdateDocDefaultRoleInput { + docId: Scalars['String']['input']; + role: DocRole; + workspaceId: Scalars['String']['input']; +} + +export interface UpdateDocUserRoleInput { + docId: Scalars['String']['input']; + role: DocRole; + userId: Scalars['String']['input']; + workspaceId: Scalars['String']['input']; +} + export interface UpdateUserInput { /** User name */ name?: InputMaybe; @@ -1514,14 +1539,6 @@ export interface WorkspaceMembersExceedLimitToDowngradeDataType { limit: Scalars['Int']['output']; } -export interface WorkspacePage { - __typename?: 'WorkspacePage'; - id: Scalars['String']['output']; - mode: PublicPageMode; - public: Scalars['Boolean']['output']; - workspaceId: Scalars['String']['output']; -} - export interface WorkspacePageMeta { __typename?: 'WorkspacePageMeta'; createdAt: Scalars['DateTime']['output']; @@ -1591,6 +1608,8 @@ export interface WorkspaceType { blobsSize: Scalars['Int']['output']; /** Workspace created date */ createdAt: Scalars['DateTime']['output']; + /** Get get with given id */ + doc: DocType; /** Enable AI */ enableAi: Scalars['Boolean']['output']; /** Enable url previous when sharing */ @@ -1612,33 +1631,35 @@ export interface WorkspaceType { members: Array; /** Owner of workspace */ owner: UserType; - /** Page granted users list */ - pageGrantedUsersList: GrantedDocUsersConnection; /** Cloud page metadata of workspace */ pageMeta: WorkspacePageMeta; - /** Check if current user has permission to access the page */ - pagePermission: DocType; /** is Public workspace */ public: Scalars['Boolean']['output']; /** Get public page of a workspace by page id. */ - publicPage: Maybe; - /** Public pages of a workspace */ - publicPages: Array; + publicDoc: Maybe; + /** Get public docs of a workspace */ + publicDocs: Array; + /** + * Get public page of a workspace by page id. + * @deprecated use [WorkspaceType.publicDoc] instead + */ + publicPage: Maybe; + /** @deprecated use [WorkspaceType.publicDocs] instead */ + publicPages: Array; /** quota of workspace */ quota: WorkspaceQuotaType; /** Role of current signed in user in workspace */ role: Permission; - /** - * Shared pages of workspace - * @deprecated use WorkspaceType.publicPages - */ - sharedPages: Array; /** The team subscription of the workspace, if exists. */ subscription: Maybe; /** if workspace is team workspace */ team: Scalars['Boolean']['output']; } +export interface WorkspaceTypeDocArgs { + docId: Scalars['String']['input']; +} + export interface WorkspaceTypeHistoriesArgs { before?: InputMaybe; guid: Scalars['String']['input']; @@ -1656,17 +1677,12 @@ export interface WorkspaceTypeMembersArgs { take?: InputMaybe; } -export interface WorkspaceTypePageGrantedUsersListArgs { - pageGrantedUsersInput: PageGrantedUsersInput; - pageId: Scalars['String']['input']; -} - export interface WorkspaceTypePageMetaArgs { pageId: Scalars['String']['input']; } -export interface WorkspaceTypePagePermissionArgs { - pageId: Scalars['String']['input']; +export interface WorkspaceTypePublicDocArgs { + docId: Scalars['String']['input']; } export interface WorkspaceTypePublicPageArgs { @@ -2357,10 +2373,10 @@ export type GetWorkspacePublicPageByIdQuery = { __typename?: 'Query'; workspace: { __typename?: 'WorkspaceType'; - publicPage: { - __typename?: 'WorkspacePage'; + publicDoc: { + __typename?: 'DocType'; id: string; - mode: PublicPageMode; + mode: PublicDocMode; } | null; }; }; @@ -2373,10 +2389,10 @@ export type GetWorkspacePublicPagesQuery = { __typename?: 'Query'; workspace: { __typename?: 'WorkspaceType'; - publicPages: Array<{ - __typename?: 'WorkspacePage'; + publicDocs: Array<{ + __typename?: 'DocType'; id: string; - mode: PublicPageMode; + mode: PublicDocMode; }>; }; }; @@ -2527,16 +2543,12 @@ export type PricesQuery = { export type PublishPageMutationVariables = Exact<{ workspaceId: Scalars['String']['input']; pageId: Scalars['String']['input']; - mode?: InputMaybe; + mode?: InputMaybe; }>; export type PublishPageMutation = { __typename?: 'Mutation'; - publishPage: { - __typename?: 'WorkspacePage'; - id: string; - mode: PublicPageMode; - }; + publishDoc: { __typename?: 'DocType'; id: string; mode: PublicDocMode }; }; export type QuotaQueryVariables = Exact<{ [key: string]: never }>; @@ -2618,10 +2630,10 @@ export type RevokePublicPageMutationVariables = Exact<{ export type RevokePublicPageMutation = { __typename?: 'Mutation'; - revokePublicPage: { - __typename?: 'WorkspacePage'; + revokePublicDoc: { + __typename?: 'DocType'; id: string; - mode: PublicPageMode; + mode: PublicDocMode; public: boolean; }; };