mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 12:55:00 +00:00
feat(server): allow to set default role in page (#9963)
This commit is contained in:
@@ -571,30 +571,69 @@ export class PermissionService {
|
||||
}
|
||||
|
||||
if (user) {
|
||||
const count = await this.prisma.workspacePageUserPermission.count({
|
||||
where: {
|
||||
workspaceId: ws,
|
||||
pageId: page,
|
||||
userId: user,
|
||||
type: {
|
||||
gte: role,
|
||||
const [roleEntity, pageEntity, workspaceRoleEntity] = await Promise.all([
|
||||
this.prisma.workspacePageUserPermission.findFirst({
|
||||
where: {
|
||||
workspaceId: ws,
|
||||
pageId: page,
|
||||
userId: user,
|
||||
},
|
||||
},
|
||||
});
|
||||
select: {
|
||||
type: true,
|
||||
},
|
||||
}),
|
||||
this.prisma.workspacePage.findFirst({
|
||||
where: {
|
||||
workspaceId: ws,
|
||||
pageId: page,
|
||||
},
|
||||
select: {
|
||||
defaultRole: true,
|
||||
},
|
||||
}),
|
||||
this.prisma.workspaceUserPermission.findFirst({
|
||||
where: {
|
||||
workspaceId: ws,
|
||||
userId: user,
|
||||
OR: this.acceptedCondition,
|
||||
},
|
||||
select: {
|
||||
type: true,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// page shared to user
|
||||
// accessible
|
||||
if (count > 0) {
|
||||
if (
|
||||
// Page role exists, check it first
|
||||
(roleEntity && roleEntity.type >= role) ||
|
||||
// if
|
||||
// - page has a default role
|
||||
// - the user is in this workspace
|
||||
// - the user is not an external user in this workspace
|
||||
// then use the max of the two
|
||||
(workspaceRoleEntity &&
|
||||
workspaceRoleEntity.type !== WorkspaceRole.External &&
|
||||
Math.max(
|
||||
roleEntity?.type ?? Number.MIN_SAFE_INTEGER,
|
||||
pageEntity?.defaultRole ?? Number.MIN_SAFE_INTEGER
|
||||
) >= role)
|
||||
) {
|
||||
return true;
|
||||
} else {
|
||||
this.logger.log("User's PageRole is lower than required", {
|
||||
workspaceId: ws,
|
||||
pageId: page,
|
||||
userId: user,
|
||||
requiredRole: DocRole[role],
|
||||
action,
|
||||
});
|
||||
}
|
||||
this.logger.log("User's role is lower than required", {
|
||||
workspaceId: ws,
|
||||
docId: page,
|
||||
userId: user,
|
||||
workspaceRole: workspaceRoleEntity
|
||||
? WorkspaceRole[workspaceRoleEntity.type]
|
||||
: undefined,
|
||||
pageRole: roleEntity ? DocRole[roleEntity.type] : undefined,
|
||||
pageDefaultRole: pageEntity
|
||||
? DocRole[pageEntity.defaultRole]
|
||||
: undefined,
|
||||
requiredRole: DocRole[role],
|
||||
action,
|
||||
});
|
||||
}
|
||||
|
||||
// check whether user has workspace related permission
|
||||
|
||||
@@ -240,7 +240,7 @@ export function mapDocRoleToPermissions(docRole: DocRole) {
|
||||
export function fixupDocRole(
|
||||
workspaceRole: WorkspaceRole = WorkspaceRole.External,
|
||||
docRole: DocRole = DocRole.External
|
||||
) {
|
||||
): DocRole {
|
||||
switch (workspaceRole) {
|
||||
case WorkspaceRole.External:
|
||||
// Workspace External user won't be able to have any high permission doc role
|
||||
|
||||
@@ -14,11 +14,13 @@ import type { WorkspacePage as PrismaWorkspacePage } from '@prisma/client';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
import {
|
||||
DocAccessDenied,
|
||||
ExpectToGrantDocUserRoles,
|
||||
ExpectToPublishPage,
|
||||
ExpectToRevokeDocUserRoles,
|
||||
ExpectToRevokePublicPage,
|
||||
ExpectToUpdateDocUserRole,
|
||||
PageDefaultRoleCanNotBeOwner,
|
||||
PageIsNotPublic,
|
||||
paginate,
|
||||
Paginated,
|
||||
@@ -74,6 +76,45 @@ class GrantDocUserRolesInput {
|
||||
userIds!: string[];
|
||||
}
|
||||
|
||||
@InputType()
|
||||
class UpdateDocUserRoleInput {
|
||||
@Field(() => String)
|
||||
docId!: string;
|
||||
|
||||
@Field(() => String)
|
||||
workspaceId!: string;
|
||||
|
||||
@Field(() => String)
|
||||
userId!: string;
|
||||
|
||||
@Field(() => DocRole)
|
||||
role!: DocRole;
|
||||
}
|
||||
|
||||
@InputType()
|
||||
class RevokeDocUserRolesInput {
|
||||
@Field(() => String)
|
||||
docId!: string;
|
||||
|
||||
@Field(() => String)
|
||||
workspaceId!: string;
|
||||
|
||||
@Field(() => [String])
|
||||
userIds!: string[];
|
||||
}
|
||||
|
||||
@InputType()
|
||||
class UpdatePageDefaultRoleInput {
|
||||
@Field(() => String)
|
||||
docId!: string;
|
||||
|
||||
@Field(() => String)
|
||||
workspaceId!: string;
|
||||
|
||||
@Field(() => DocRole)
|
||||
role!: DocRole;
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
class GrantedDocUserType {
|
||||
@Field(() => String)
|
||||
@@ -413,12 +454,11 @@ export class PagePermissionResolver {
|
||||
@Mutation(() => Boolean)
|
||||
async revokeDocUserRoles(
|
||||
@CurrentUser() user: CurrentUser,
|
||||
@Args('docId') docId: string,
|
||||
@Args('userIds', { type: () => [String] }) userIds: string[]
|
||||
@Args('input') input: RevokeDocUserRolesInput
|
||||
): Promise<boolean> {
|
||||
const doc = new DocID(docId);
|
||||
const doc = new DocID(input.docId, input.workspaceId);
|
||||
const pairs = {
|
||||
spaceId: doc.workspace,
|
||||
spaceId: input.workspaceId,
|
||||
docId: doc.guid,
|
||||
};
|
||||
if (doc.isWorkspace) {
|
||||
@@ -436,10 +476,10 @@ export class PagePermissionResolver {
|
||||
user.id,
|
||||
WorkspaceRole.Collaborator
|
||||
);
|
||||
await this.permission.revokePage(doc.workspace, doc.guid, userIds);
|
||||
await this.permission.revokePage(doc.workspace, doc.guid, input.userIds);
|
||||
this.logger.log('Revoke doc user roles', {
|
||||
...pairs,
|
||||
userIds: userIds,
|
||||
userIds: input.userIds,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
@@ -447,11 +487,9 @@ export class PagePermissionResolver {
|
||||
@Mutation(() => Boolean)
|
||||
async updateDocUserRole(
|
||||
@CurrentUser() user: CurrentUser,
|
||||
@Args('docId') docId: string,
|
||||
@Args('userId') userId: string,
|
||||
@Args('role', { type: () => DocRole }) role: DocRole
|
||||
@Args('input') input: UpdateDocUserRoleInput
|
||||
): Promise<boolean> {
|
||||
const doc = new DocID(docId);
|
||||
const doc = new DocID(input.docId, input.workspaceId);
|
||||
const pairs = {
|
||||
spaceId: doc.workspace,
|
||||
docId: doc.guid,
|
||||
@@ -471,32 +509,94 @@ export class PagePermissionResolver {
|
||||
user.id,
|
||||
WorkspaceRole.Collaborator
|
||||
);
|
||||
if (role === DocRole.Owner) {
|
||||
if (input.role === DocRole.Owner) {
|
||||
const ret = await this.permission.grantPagePermission(
|
||||
doc.workspace,
|
||||
doc.guid,
|
||||
[userId],
|
||||
role
|
||||
[input.userId],
|
||||
input.role
|
||||
);
|
||||
this.logger.log('Transfer doc owner', {
|
||||
...pairs,
|
||||
userId: userId,
|
||||
role: role,
|
||||
userId: input.userId,
|
||||
role: input.role,
|
||||
});
|
||||
return ret.length > 0;
|
||||
} else {
|
||||
await this.permission.updatePagePermission(
|
||||
doc.workspace,
|
||||
doc.guid,
|
||||
userId,
|
||||
role
|
||||
input.userId,
|
||||
input.role
|
||||
);
|
||||
this.logger.log('Update doc user role', {
|
||||
...pairs,
|
||||
userId: userId,
|
||||
role: role,
|
||||
userId: input.userId,
|
||||
role: input.role,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Mutation(() => Boolean)
|
||||
async updatePageDefaultRole(
|
||||
@CurrentUser() user: CurrentUser,
|
||||
@Args('input') input: UpdatePageDefaultRoleInput
|
||||
) {
|
||||
if (input.role === DocRole.Owner) {
|
||||
this.logger.log('Page default role can not be owner', input);
|
||||
throw new PageDefaultRoleCanNotBeOwner();
|
||||
}
|
||||
const doc = new DocID(input.docId, input.workspaceId);
|
||||
const pairs = {
|
||||
spaceId: doc.workspace,
|
||||
docId: doc.guid,
|
||||
};
|
||||
if (doc.isWorkspace) {
|
||||
this.logger.error(
|
||||
'Expect to update page default role, but it is a workspace',
|
||||
pairs
|
||||
);
|
||||
throw new ExpectToUpdateDocUserRole(
|
||||
pairs,
|
||||
'Expect doc not to be workspace'
|
||||
);
|
||||
}
|
||||
try {
|
||||
await this.permission.checkCloudPagePermission(
|
||||
doc.workspace,
|
||||
doc.guid,
|
||||
'Doc.Users.Manage',
|
||||
user.id
|
||||
);
|
||||
} catch (error) {
|
||||
if (error instanceof DocAccessDenied) {
|
||||
this.logger.log(
|
||||
'User does not have permission to update page default role',
|
||||
{
|
||||
...pairs,
|
||||
userId: user.id,
|
||||
}
|
||||
);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
await this.prisma.workspacePage.upsert({
|
||||
where: {
|
||||
workspaceId_pageId: {
|
||||
workspaceId: doc.workspace,
|
||||
pageId: doc.guid,
|
||||
},
|
||||
},
|
||||
update: {
|
||||
defaultRole: input.role,
|
||||
},
|
||||
create: {
|
||||
workspaceId: doc.workspace,
|
||||
pageId: doc.guid,
|
||||
defaultRole: input.role,
|
||||
},
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user