mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-19 19:16:29 +08:00
refactor: rename all page query to doc (#10019)
This commit is contained in:
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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}.`,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 },
|
||||
});
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -16,7 +16,7 @@ export {
|
||||
fixupDocRole,
|
||||
mapDocRoleToPermissions,
|
||||
mapWorkspaceRoleToPermissions,
|
||||
PublicPageMode,
|
||||
PublicDocMode,
|
||||
WORKSPACE_ACTIONS,
|
||||
type WorkspaceActionPermissions,
|
||||
WorkspaceRole,
|
||||
|
||||
@@ -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<any>[]
|
||||
);
|
||||
|
||||
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,
|
||||
})),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { LeafPaths, LeafVisitor } from '../../base';
|
||||
|
||||
export enum PublicPageMode {
|
||||
export enum PublicDocMode {
|
||||
Page,
|
||||
Edgeless,
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
+245
-234
@@ -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<PrismaWorkspacePage> {
|
||||
class DocType implements Partial<PrismaWorkspaceDoc> {
|
||||
@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<DocActionPermissions>(
|
||||
);
|
||||
|
||||
@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<DocType> {
|
||||
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<DocType> {
|
||||
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<DocRolePermissions> {
|
||||
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<PaginatedGrantedDocUserType> {
|
||||
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,
|
||||
},
|
||||
});
|
||||
@@ -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';
|
||||
|
||||
@@ -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<PageUserPermission> {
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+2
-2
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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');
|
||||
|
||||
|
||||
@@ -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<ShareInfoType | undefined | null>(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);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,6 @@ export class ShareDocsStore extends Store {
|
||||
signal,
|
||||
},
|
||||
});
|
||||
return data.workspace.publicPages;
|
||||
return data.workspace.publicDocs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
query getWorkspacePublicPageById($workspaceId: String!, $pageId: String!) {
|
||||
workspace(id: $workspaceId) {
|
||||
publicPage(pageId: $pageId) {
|
||||
publicDoc(docId: $pageId) {
|
||||
id
|
||||
mode
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
query getWorkspacePublicPages($workspaceId: String!) {
|
||||
workspace(id: $workspaceId) {
|
||||
publicPages {
|
||||
publicDocs {
|
||||
id
|
||||
mode
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
mutation revokePublicPage($workspaceId: String!, $pageId: String!) {
|
||||
revokePublicPage(workspaceId: $workspaceId, pageId: $pageId) {
|
||||
revokePublicDoc(workspaceId: $workspaceId, docId: $pageId) {
|
||||
id
|
||||
mode
|
||||
public
|
||||
|
||||
@@ -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<GrantedDocUserEdge>;
|
||||
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<InviteResult>;
|
||||
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<Scalars['String']['input']>;
|
||||
}
|
||||
|
||||
export interface MutationPublishDocArgs {
|
||||
docId: Scalars['String']['input'];
|
||||
mode?: InputMaybe<PublicDocMode>;
|
||||
workspaceId: Scalars['String']['input'];
|
||||
}
|
||||
|
||||
export interface MutationPublishPageArgs {
|
||||
mode?: InputMaybe<PublicPageMode>;
|
||||
mode?: InputMaybe<PublicDocMode>;
|
||||
pageId: Scalars['String']['input'];
|
||||
workspaceId: Scalars['String']['input'];
|
||||
}
|
||||
@@ -900,21 +925,20 @@ export interface MutationRevokeArgs {
|
||||
}
|
||||
|
||||
export interface MutationRevokeDocUserRolesArgs {
|
||||
docId: Scalars['String']['input'];
|
||||
userIds: Array<Scalars['String']['input']>;
|
||||
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<CopilotPromptMessageInput>;
|
||||
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<Scalars['String']['input']>;
|
||||
/** Cursor */
|
||||
before?: InputMaybe<Scalars['String']['input']>;
|
||||
first: Scalars['Int']['input'];
|
||||
offset: Scalars['Int']['input'];
|
||||
}
|
||||
|
||||
export interface PageInfo {
|
||||
__typename?: 'PageInfo';
|
||||
endCursor: Maybe<Scalars['String']['output']>;
|
||||
@@ -1038,6 +1050,22 @@ export interface PageInfo {
|
||||
startCursor: Maybe<Scalars['String']['output']>;
|
||||
}
|
||||
|
||||
export interface PaginatedGrantedDocUserType {
|
||||
__typename?: 'PaginatedGrantedDocUserType';
|
||||
edges: Array<GrantedDocUserTypeEdge>;
|
||||
pageInfo: PageInfo;
|
||||
totalCount: Scalars['Int']['output'];
|
||||
}
|
||||
|
||||
export interface PaginationInput {
|
||||
/** returns the elements in the list that come after the specified cursor. */
|
||||
after?: InputMaybe<Scalars['String']['input']>;
|
||||
/** returns the first n elements from the list. */
|
||||
first?: InputMaybe<Scalars['Int']['input']>;
|
||||
/** ignore the first n elements from the list. */
|
||||
offset?: InputMaybe<Scalars['Int']['input']>;
|
||||
}
|
||||
|
||||
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<Scalars['String']['output']>;
|
||||
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<Scalars['String']['input']>;
|
||||
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<Scalars['String']['input']>;
|
||||
@@ -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<InviteUserType>;
|
||||
/** 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<WorkspacePage>;
|
||||
/** Public pages of a workspace */
|
||||
publicPages: Array<WorkspacePage>;
|
||||
publicDoc: Maybe<DocType>;
|
||||
/** Get public docs of a workspace */
|
||||
publicDocs: Array<DocType>;
|
||||
/**
|
||||
* Get public page of a workspace by page id.
|
||||
* @deprecated use [WorkspaceType.publicDoc] instead
|
||||
*/
|
||||
publicPage: Maybe<DocType>;
|
||||
/** @deprecated use [WorkspaceType.publicDocs] instead */
|
||||
publicPages: Array<DocType>;
|
||||
/** 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<Scalars['String']['output']>;
|
||||
/** The team subscription of the workspace, if exists. */
|
||||
subscription: Maybe<SubscriptionType>;
|
||||
/** if workspace is team workspace */
|
||||
team: Scalars['Boolean']['output'];
|
||||
}
|
||||
|
||||
export interface WorkspaceTypeDocArgs {
|
||||
docId: Scalars['String']['input'];
|
||||
}
|
||||
|
||||
export interface WorkspaceTypeHistoriesArgs {
|
||||
before?: InputMaybe<Scalars['DateTime']['input']>;
|
||||
guid: Scalars['String']['input'];
|
||||
@@ -1656,17 +1677,12 @@ export interface WorkspaceTypeMembersArgs {
|
||||
take?: InputMaybe<Scalars['Int']['input']>;
|
||||
}
|
||||
|
||||
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<PublicPageMode>;
|
||||
mode?: InputMaybe<PublicDocMode>;
|
||||
}>;
|
||||
|
||||
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;
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user