From 52647a98b5271c8b1e813aa2bcedbd8ed1723ab1 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Mon, 7 Aug 2023 20:49:53 +0800 Subject: [PATCH] fix: fix append group member roles will occur error when operate multi users --- server/models/group/group.ts | 40 +++++++++---- server/services/core/group/group.service.ts | 66 ++++++++++++--------- 2 files changed, 66 insertions(+), 40 deletions(-) diff --git a/server/models/group/group.ts b/server/models/group/group.ts index b0101a39..6d342919 100644 --- a/server/models/group/group.ts +++ b/server/models/group/group.ts @@ -320,29 +320,24 @@ export class Group extends TimeStamps implements Base { } /** - * 修改群组成员的字段信息 - * - * 带权限验证 + * 检查群组字段操作权限,如果没有权限会直接抛出异常 */ - static async updateGroupMemberField< + static async checkGroupFieldPermission< K extends keyof Pick >( this: ReturnModelType, ctx: TcContext, groupId: string, - memberId: string, - fieldName: K, - fieldValue: GroupMember[K] | ((member: GroupMember) => void), - operatorUserId: string - ): Promise { - const group = await this.findById(groupId); + fieldName: K + ) { + const userId = ctx.meta.userId; const t = ctx.meta.t; if (fieldName === 'roles') { // 检查操作用户是否有管理角色的权限 const [hasRolePermission] = await call(ctx).checkUserPermissions( groupId, - operatorUserId, + userId, [PERMISSION.core.manageRoles] ); if (!hasRolePermission) { @@ -352,13 +347,34 @@ export class Group extends TimeStamps implements Base { // 检查操作用户是否有管理用户权限 const [hasUserPermission] = await call(ctx).checkUserPermissions( groupId, - operatorUserId, + userId, [PERMISSION.core.manageUser] ); if (!hasUserPermission) { throw new NoPermissionError(t('没有操作用户权限')); } } + } + + /** + * 修改群组成员的字段信息 + * + * 带权限验证 + */ + static async updateGroupMemberField< + K extends keyof Pick + >( + this: ReturnModelType, + ctx: TcContext, + groupId: string, + memberId: string, + fieldName: K, + fieldValue: GroupMember[K] | ((member: GroupMember) => void) + ): Promise { + const group = await this.findById(groupId); + const t = ctx.meta.t; + + await this.checkGroupFieldPermission(ctx, groupId, fieldName); const member = group.members.find((m) => String(m.userId) === memberId); if (!member) { diff --git a/server/services/core/group/group.service.ts b/server/services/core/group/group.service.ts index 40799178..0b2b5a59 100644 --- a/server/services/core/group/group.service.ts +++ b/server/services/core/group/group.service.ts @@ -22,6 +22,7 @@ import { PanelFeature, config, SYSTEM_USERID, + db, } from 'tailchat-server-sdk'; import moment from 'moment'; @@ -655,20 +656,25 @@ class GroupService extends TcService { }> ) { const { groupId, memberIds, roles } = ctx.params; - const { userId } = ctx.meta; - await Promise.all( - memberIds.map((memberId) => - this.adapter.model.updateGroupMemberField( - ctx, - groupId, - memberId, - 'roles', - (member) => - (member['roles'] = _.uniq([...member['roles'], ...roles])), - userId - ) - ) + await this.adapter.model.checkGroupFieldPermission(ctx, groupId, 'roles'); + + // 更新内容 + await this.adapter.model.updateMany( + { + _id: new db.Types.ObjectId(groupId), + 'members.userId': { + $in: [...memberIds], + }, + }, + { + $addToSet: { + 'members.$[elem].roles': { + $each: roles, + }, + }, + }, + { arrayFilters: [{ 'elem.userId': { $in: [...memberIds] } }] } ); const group = await this.adapter.model.findById(groupId); @@ -692,19 +698,25 @@ class GroupService extends TcService { }> ) { const { groupId, memberIds, roles } = ctx.params; - const { userId } = ctx.meta; - await Promise.all( - memberIds.map((memberId) => - this.adapter.model.updateGroupMemberField( - ctx, - groupId, - memberId, - 'roles', - (member) => (member['roles'] = _.without(member['roles'], ...roles)), - userId - ) - ) + await this.adapter.model.checkGroupFieldPermission(ctx, groupId, 'roles'); + + // 更新内容 + await this.adapter.model.updateMany( + { + _id: new db.Types.ObjectId(groupId), + 'members.userId': { + $in: [...memberIds], + }, + }, + { + $pull: { + 'members.$[elem].roles': { + $in: roles, + }, + }, + }, + { arrayFilters: [{ 'elem.userId': { $in: [...memberIds] } }] } ); const group = await this.adapter.model.findById(groupId); @@ -1112,7 +1124,6 @@ class GroupService extends TcService { }> ) { const { groupId, memberId, muteMs } = ctx.params; - const userId = ctx.meta.userId; const language = ctx.meta.language; const isUnmute = muteMs < 0; @@ -1121,8 +1132,7 @@ class GroupService extends TcService { groupId, memberId, 'muteUntil', - isUnmute ? undefined : new Date(new Date().valueOf() + muteMs), - userId + isUnmute ? undefined : new Date(new Date().valueOf() + muteMs) ); this.notifyGroupInfoUpdate(ctx, group);