test(server): grant doc user roles (#10016)
This commit is contained in:
@@ -14,7 +14,7 @@ import { AppModule } from '../app.module';
|
|||||||
import { EventBus } from '../base';
|
import { EventBus } from '../base';
|
||||||
import { AuthService } from '../core/auth';
|
import { AuthService } from '../core/auth';
|
||||||
import { DocContentService } from '../core/doc-renderer';
|
import { DocContentService } from '../core/doc-renderer';
|
||||||
import { PermissionService, WorkspaceRole } from '../core/permission';
|
import { DocRole, PermissionService, WorkspaceRole } from '../core/permission';
|
||||||
import { WorkspaceType } from '../core/workspaces';
|
import { WorkspaceType } from '../core/workspaces';
|
||||||
import { Models } from '../models';
|
import { Models } from '../models';
|
||||||
import {
|
import {
|
||||||
@@ -26,16 +26,20 @@ import {
|
|||||||
getInviteInfo,
|
getInviteInfo,
|
||||||
getInviteLink,
|
getInviteLink,
|
||||||
getWorkspace,
|
getWorkspace,
|
||||||
|
grantDocUserRoles,
|
||||||
grantMember,
|
grantMember,
|
||||||
inviteUser,
|
inviteUser,
|
||||||
inviteUsers,
|
inviteUsers,
|
||||||
leaveWorkspace,
|
leaveWorkspace,
|
||||||
|
pageGrantedUsersList,
|
||||||
|
revokeDocUserRoles,
|
||||||
revokeInviteLink,
|
revokeInviteLink,
|
||||||
revokeMember,
|
revokeMember,
|
||||||
revokeUser,
|
revokeUser,
|
||||||
signUp,
|
signUp,
|
||||||
sleep,
|
sleep,
|
||||||
TestingApp,
|
TestingApp,
|
||||||
|
updatePageDefaultRole,
|
||||||
UserAuthedType,
|
UserAuthedType,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
||||||
@@ -804,26 +808,83 @@ test('should be able to emit events', async t => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should be able to grant and revoke users role in page', async t => {
|
||||||
|
const { app } = t.context;
|
||||||
|
const {
|
||||||
|
teamWorkspace: ws,
|
||||||
|
admin,
|
||||||
|
write,
|
||||||
|
read,
|
||||||
|
external,
|
||||||
|
} = await init(app, 5);
|
||||||
|
const pageId = nanoid();
|
||||||
|
|
||||||
|
const res = await grantDocUserRoles(
|
||||||
|
app,
|
||||||
|
admin.token.token,
|
||||||
|
ws.id,
|
||||||
|
pageId,
|
||||||
|
[read.id, write.id],
|
||||||
|
DocRole.Manager
|
||||||
|
);
|
||||||
|
|
||||||
|
t.deepEqual(res.body, {
|
||||||
|
data: {
|
||||||
|
grantDocUserRoles: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// should not downgrade the role if role exists
|
||||||
|
{
|
||||||
|
await grantDocUserRoles(
|
||||||
|
app,
|
||||||
|
admin.token.token,
|
||||||
|
ws.id,
|
||||||
|
pageId,
|
||||||
|
[read.id],
|
||||||
|
DocRole.Reader
|
||||||
|
);
|
||||||
|
// read still be the Manager of this doc
|
||||||
|
const res = await grantDocUserRoles(
|
||||||
|
app,
|
||||||
|
read.token.token,
|
||||||
|
ws.id,
|
||||||
|
pageId,
|
||||||
|
[external.id],
|
||||||
|
DocRole.Editor
|
||||||
|
);
|
||||||
|
t.deepEqual(res.body, {
|
||||||
|
data: {
|
||||||
|
grantDocUserRoles: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const pageUsersList = await pageGrantedUsersList(
|
||||||
|
app,
|
||||||
|
admin.token.token,
|
||||||
|
ws.id,
|
||||||
|
pageId
|
||||||
|
);
|
||||||
|
t.is(pageUsersList.data.workspace.pageGrantedUsersList.totalCount, 3);
|
||||||
|
const externalRole =
|
||||||
|
pageUsersList.data.workspace.pageGrantedUsersList.edges.find(
|
||||||
|
(edge: any) => edge.node.user.id === external.id
|
||||||
|
)?.node.role;
|
||||||
|
t.is(externalRole, DocRole[DocRole.Editor]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('should be able to change the default role in page', async t => {
|
test('should be able to change the default role in page', async t => {
|
||||||
const { app } = t.context;
|
const { app } = t.context;
|
||||||
const { teamWorkspace: ws, admin } = await init(app, 5);
|
const { teamWorkspace: ws, admin } = await init(app, 5);
|
||||||
const pageId = nanoid();
|
const pageId = nanoid();
|
||||||
const res = await request(app.getHttpServer())
|
const res = await updatePageDefaultRole(
|
||||||
.post('/graphql')
|
app,
|
||||||
.auth(admin.token.token, { type: 'bearer' })
|
admin.token.token,
|
||||||
.set({ 'x-request-id': 'test', 'x-operation-name': 'test' })
|
ws.id,
|
||||||
.send({
|
pageId,
|
||||||
query: `
|
DocRole.Reader
|
||||||
mutation {
|
);
|
||||||
updatePageDefaultRole(input: {
|
|
||||||
workspaceId: "${ws.id}",
|
|
||||||
docId: "${pageId}",
|
|
||||||
role: Reader,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
t.deepEqual(res.body, {
|
t.deepEqual(res.body, {
|
||||||
data: {
|
data: {
|
||||||
@@ -832,7 +893,7 @@ test('should be able to change the default role in page', async t => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Default page role should be able to override the workspace role', async t => {
|
test('default page role should be able to override the workspace role', async t => {
|
||||||
const { app } = t.context;
|
const { app } = t.context;
|
||||||
const {
|
const {
|
||||||
teamWorkspace: workspace,
|
teamWorkspace: workspace,
|
||||||
@@ -843,22 +904,13 @@ test('Default page role should be able to override the workspace role', async t
|
|||||||
|
|
||||||
const pageId = nanoid();
|
const pageId = nanoid();
|
||||||
|
|
||||||
const res = await request(app.getHttpServer())
|
const res = await updatePageDefaultRole(
|
||||||
.post('/graphql')
|
app,
|
||||||
.auth(admin.token.token, { type: 'bearer' })
|
admin.token.token,
|
||||||
.set({ 'x-request-id': 'test', 'x-operation-name': 'test' })
|
workspace.id,
|
||||||
.send({
|
pageId,
|
||||||
query: `
|
DocRole.Manager
|
||||||
mutation {
|
);
|
||||||
updatePageDefaultRole(input: {
|
|
||||||
workspaceId: "${workspace.id}",
|
|
||||||
docId: "${pageId}",
|
|
||||||
role: Manager,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
t.deepEqual(res.body, {
|
t.deepEqual(res.body, {
|
||||||
data: {
|
data: {
|
||||||
@@ -868,22 +920,13 @@ test('Default page role should be able to override the workspace role', async t
|
|||||||
|
|
||||||
// reader can manage the page if the page default role is Manager
|
// reader can manage the page if the page default role is Manager
|
||||||
{
|
{
|
||||||
const readerRes = await request(app.getHttpServer())
|
const readerRes = await updatePageDefaultRole(
|
||||||
.post('/graphql')
|
app,
|
||||||
.auth(read.token.token, { type: 'bearer' })
|
read.token.token,
|
||||||
.set({ 'x-request-id': 'test', 'x-operation-name': 'test' })
|
workspace.id,
|
||||||
.send({
|
pageId,
|
||||||
query: `
|
DocRole.Manager
|
||||||
mutation {
|
);
|
||||||
updatePageDefaultRole(input: {
|
|
||||||
workspaceId: "${workspace.id}",
|
|
||||||
docId: "${pageId}",
|
|
||||||
role: Manager,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
t.deepEqual(readerRes.body, {
|
t.deepEqual(readerRes.body, {
|
||||||
data: {
|
data: {
|
||||||
@@ -894,22 +937,13 @@ test('Default page role should be able to override the workspace role', async t
|
|||||||
|
|
||||||
// external can't manage the page even if the page default role is Manager
|
// external can't manage the page even if the page default role is Manager
|
||||||
{
|
{
|
||||||
const externalRes = await request(app.getHttpServer())
|
const externalRes = await updatePageDefaultRole(
|
||||||
.post('/graphql')
|
app,
|
||||||
.auth(external.token.token, { type: 'bearer' })
|
external.token.token,
|
||||||
.set({ 'x-request-id': 'test', 'x-operation-name': 'test' })
|
workspace.id,
|
||||||
.send({
|
pageId,
|
||||||
query: `
|
DocRole.Manager
|
||||||
mutation {
|
);
|
||||||
updatePageDefaultRole(input: {
|
|
||||||
workspaceId: "${workspace.id}",
|
|
||||||
docId: "${pageId}",
|
|
||||||
role: Manager,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
t.like(externalRes.body, {
|
t.like(externalRes.body, {
|
||||||
errors: [
|
errors: [
|
||||||
@@ -925,23 +959,15 @@ test('should be able to grant and revoke doc user role', async t => {
|
|||||||
const { app } = t.context;
|
const { app } = t.context;
|
||||||
const { teamWorkspace: ws, admin, read, external } = await init(app, 5);
|
const { teamWorkspace: ws, admin, read, external } = await init(app, 5);
|
||||||
const pageId = nanoid();
|
const pageId = nanoid();
|
||||||
const res = await request(app.getHttpServer())
|
|
||||||
.post('/graphql')
|
const res = await grantDocUserRoles(
|
||||||
.auth(admin.token.token, { type: 'bearer' })
|
app,
|
||||||
.set({ 'x-request-id': 'test', 'x-operation-name': 'test' })
|
admin.token.token,
|
||||||
.send({
|
ws.id,
|
||||||
query: `
|
pageId,
|
||||||
mutation {
|
[external.id],
|
||||||
grantDocUserRoles(input: {
|
DocRole.Manager
|
||||||
workspaceId: "${ws.id}",
|
);
|
||||||
docId: "${pageId}",
|
|
||||||
role: Manager,
|
|
||||||
userIds: ["${external.id}"]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
t.deepEqual(res.body, {
|
t.deepEqual(res.body, {
|
||||||
data: {
|
data: {
|
||||||
@@ -951,23 +977,15 @@ test('should be able to grant and revoke doc user role', async t => {
|
|||||||
|
|
||||||
// external user now can manage the page
|
// external user now can manage the page
|
||||||
{
|
{
|
||||||
const externalRes = await request(app.getHttpServer())
|
const externalRes = await grantDocUserRoles(
|
||||||
.post('/graphql')
|
app,
|
||||||
.auth(external.token.token, { type: 'bearer' })
|
external.token.token,
|
||||||
.set({ 'x-request-id': 'test', 'x-operation-name': 'test' })
|
ws.id,
|
||||||
.send({
|
pageId,
|
||||||
query: `
|
[read.id],
|
||||||
mutation {
|
DocRole.Manager
|
||||||
grantDocUserRoles(input: {
|
);
|
||||||
workspaceId: "${ws.id}",
|
|
||||||
docId: "${pageId}",
|
|
||||||
role: Manager,
|
|
||||||
userIds: ["${read.id}"]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
t.deepEqual(externalRes.body, {
|
t.deepEqual(externalRes.body, {
|
||||||
data: {
|
data: {
|
||||||
grantDocUserRoles: true,
|
grantDocUserRoles: true,
|
||||||
@@ -977,22 +995,14 @@ test('should be able to grant and revoke doc user role', async t => {
|
|||||||
|
|
||||||
// revoke the role of the external user
|
// revoke the role of the external user
|
||||||
{
|
{
|
||||||
const revokeRes = await request(app.getHttpServer())
|
const revokeRes = await revokeDocUserRoles(
|
||||||
.post('/graphql')
|
app,
|
||||||
.auth(admin.token.token, { type: 'bearer' })
|
admin.token.token,
|
||||||
.set({ 'x-request-id': 'test', 'x-operation-name': 'test' })
|
ws.id,
|
||||||
.send({
|
pageId,
|
||||||
query: `
|
external.id
|
||||||
mutation {
|
);
|
||||||
revokeDocUserRoles(input: {
|
|
||||||
workspaceId: "${ws.id}",
|
|
||||||
docId: "${pageId}",
|
|
||||||
userId: "${external.id}"
|
|
||||||
})
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
t.deepEqual(revokeRes.body, {
|
t.deepEqual(revokeRes.body, {
|
||||||
data: {
|
data: {
|
||||||
revokeDocUserRoles: true,
|
revokeDocUserRoles: true,
|
||||||
@@ -1000,22 +1010,14 @@ test('should be able to grant and revoke doc user role', async t => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// external user can't manage the page
|
// external user can't manage the page
|
||||||
const externalRes = await request(app.getHttpServer())
|
const externalRes = await revokeDocUserRoles(
|
||||||
.post('/graphql')
|
app,
|
||||||
.auth(external.token.token, { type: 'bearer' })
|
external.token.token,
|
||||||
.set({ 'x-request-id': 'test', 'x-operation-name': 'test' })
|
ws.id,
|
||||||
.send({
|
pageId,
|
||||||
query: `
|
read.id
|
||||||
mutation {
|
);
|
||||||
revokeDocUserRoles(input: {
|
|
||||||
workspaceId: "${ws.id}",
|
|
||||||
docId: "${pageId}",
|
|
||||||
userId: "${read.id}"
|
|
||||||
})
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
t.like(externalRes.body, {
|
t.like(externalRes.body, {
|
||||||
errors: [
|
errors: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
export * from './blobs';
|
export * from './blobs';
|
||||||
export * from './invite';
|
export * from './invite';
|
||||||
|
export * from './permission';
|
||||||
export * from './user';
|
export * from './user';
|
||||||
export * from './utils';
|
export * from './utils';
|
||||||
export * from './workspace';
|
export * from './workspace';
|
||||||
|
|||||||
114
packages/backend/server/src/__tests__/utils/permission.ts
Normal file
114
packages/backend/server/src/__tests__/utils/permission.ts
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import type { INestApplication } from '@nestjs/common';
|
||||||
|
import request from 'supertest';
|
||||||
|
|
||||||
|
import { DocRole } from '../../core/permission/types';
|
||||||
|
import { gql } from './common';
|
||||||
|
|
||||||
|
export function grantDocUserRoles(
|
||||||
|
app: INestApplication,
|
||||||
|
token: string,
|
||||||
|
workspaceId: string,
|
||||||
|
docId: string,
|
||||||
|
userIds: string[],
|
||||||
|
role: DocRole
|
||||||
|
) {
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.post(gql)
|
||||||
|
.auth(token, { type: 'bearer' })
|
||||||
|
.set({ 'x-request-id': 'test', 'x-operation-name': 'test' })
|
||||||
|
.send({
|
||||||
|
query: `
|
||||||
|
mutation {
|
||||||
|
grantDocUserRoles(input: {
|
||||||
|
workspaceId: "${workspaceId}",
|
||||||
|
docId: "${docId}",
|
||||||
|
userIds: ["${userIds.join('","')}"],
|
||||||
|
role: ${DocRole[role]}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function revokeDocUserRoles(
|
||||||
|
app: INestApplication,
|
||||||
|
token: string,
|
||||||
|
workspaceId: string,
|
||||||
|
docId: string,
|
||||||
|
userId: string
|
||||||
|
) {
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.post(gql)
|
||||||
|
.auth(token, { type: 'bearer' })
|
||||||
|
.set({ 'x-request-id': 'test', 'x-operation-name': 'test' })
|
||||||
|
.send({
|
||||||
|
query: `
|
||||||
|
mutation {
|
||||||
|
revokeDocUserRoles(input: {
|
||||||
|
workspaceId: "${workspaceId}",
|
||||||
|
docId: "${docId}",
|
||||||
|
userId: "${userId}"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updatePageDefaultRole(
|
||||||
|
app: INestApplication,
|
||||||
|
token: string,
|
||||||
|
workspaceId: string,
|
||||||
|
docId: string,
|
||||||
|
role: DocRole
|
||||||
|
) {
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.post(gql)
|
||||||
|
.auth(token, { type: 'bearer' })
|
||||||
|
.set({ 'x-request-id': 'test', 'x-operation-name': 'test' })
|
||||||
|
.send({
|
||||||
|
query: `
|
||||||
|
mutation {
|
||||||
|
updatePageDefaultRole(input: {
|
||||||
|
workspaceId: "${workspaceId}",
|
||||||
|
docId: "${docId}",
|
||||||
|
role: ${DocRole[role]}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function pageGrantedUsersList(
|
||||||
|
app: INestApplication,
|
||||||
|
token: string,
|
||||||
|
workspaceId: string,
|
||||||
|
docId: string,
|
||||||
|
first = 10,
|
||||||
|
offset = 0
|
||||||
|
) {
|
||||||
|
const res = await request(app.getHttpServer())
|
||||||
|
.post(gql)
|
||||||
|
.auth(token, { type: 'bearer' })
|
||||||
|
.set({ 'x-request-id': 'test', 'x-operation-name': 'test' })
|
||||||
|
.send({
|
||||||
|
query: `
|
||||||
|
query {
|
||||||
|
workspace(id: "${workspaceId}") {
|
||||||
|
pageGrantedUsersList(pageId: "${docId}", pagination: { first: ${first}, offset: ${offset} }) {
|
||||||
|
totalCount
|
||||||
|
edges {
|
||||||
|
cursor
|
||||||
|
node {
|
||||||
|
role
|
||||||
|
user {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
return res.body;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user