mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-27 19:02:23 +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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user