服务器身份组
更新时间: 2024/11/21 16:31:48
服务器身份组指负责在服务器维度对用户进行权限控制的身份组,包括服务器下的@everyone 身份组和自定义身份组。创建服务器时,@everyone 身份组默认自动创建。而服务器自定义身份组则需要用户手动创建。首个自定义身份组创建后,其权限配置默认继承自 @everyone 身份组,如需调整,需要拥有相应权限的用户手动更新。此外,用户还可调整服务器身份组的优先级(需拥有相应权限)。
本文介绍通过服务器身份组进行权限控制的流程,以及其他与服务器身份组相关的 SDK API。
@everyone 身份组的权限配置,只有服务器创建者可修改。@everyone 身份组的其他信息(身份组的名称、图标、自定义扩展和优先级)不支持修改。
服务器身份组定义
SDK 中定义服务器身份组的结构体为QChatServerRoleInfo
。该结构体的参数说明如下:
单击展开查看QChatServerRoleInfo的成员参数
参数 | 类型 | 说明 |
---|---|---|
member_count |
uint32_t | 身份组的成员数量,@ everyone 身份组的成员数量数量默认为-1 |
priority |
uint64_t | 身份组优先级(具体见下文的批量更新服务器身份组优先级),用于判定身份组成员是否能修改其他身份组的权限配置。自定义身份组优先级取值范围为 1 至 9007199254740991,数字越小优先级越高。高优先级身份组中拥有管理角色权限的用户,可修改低优先级身份组的权限,但无法修改更高优先级身份组的权限。 @everyone 身份组优先级取值为 0 且不能更改,默认低于自定义身份组优先级 |
server_id |
uint64_t | 身份组所属服务器的 ID |
role_id |
uint64_t | 身份组 ID |
role_name |
std::string | 身份组名称 |
role_icon |
std::string | 身份组图标的 URL |
extension |
std::string | 身份组的扩展字段 |
permissions |
QChatPermission |
身份组权限 map。 |
role_type |
NIMQChatRoleType |
身份组的类型,1 表示 @everyone 身份组,2 表示自定义身份组 |
create_time |
uint64_t | 身份组的创建时间 |
update_time |
uint64_t | 身份组配置的更新时间 |
实现流程
以下时序图以典型场景为例,介绍通过服务器身份组进行权限控制的流程。该典型场景为:服务器创建者将频道管理权限(NIMQChatPermissionTypeManageChannel
)授予服务器成员,从而使该成员能够创建频道。
sequenceDiagram
note over QChat 实例: 初始化与登录
用户A ->> QChat 实例: 初始化
用户B ->> QChat 实例: 初始化
用户A ->> QChat 实例: 登录圈组
用户B ->> QChat 实例: 登录圈组
note over QChat 实例: 用户A 将权限授予用户 B
用户A ->> QChat 实例: 创建服务器
用户A ->> QChat 实例: 创建服务器身份组
用户A ->> QChat 实例: 修改服务器身份组
note over 用户A: 修改时将频道管理权限开启,<br>使该身份组的成员拥有该权限
用户A ->> QChat 实例: 邀请用户B 加入服务器
用户B ->> QChat 实例: 接受邀请加入服务器
note over 用户B: 用户B 需要先加入服务器,<br>才能被添加为身份组成员
用户A ->> QChat 实例: 添加身份组成员
note over 用户A: 将用户B 加入该服务器身份组,<br>使用户B 获得频道管理权限
note over QChat 实例: 用户B 创建频道
note over 用户B: 用户B 拥有了频道管理权限,<br>可进行频道创建操作
用户B ->> QChat 实例: 在服务器内创建频道
本节仅对上图中标为部分的方法调用做详细说明,其他方法调用请参考相应的文档。
步骤1:创建服务器身份组
调用CreateServerRole
方法创建自定义身份组。
新创建的自定义身份组的权限为用户所有已有身份组的权限之和。假设用户在创建之前,只属于 @everyone 身份组的成员,则新创建的自定义身份组的权限将继承 @everyone 身份组的权限,两者权限一致。如需修改,还需要调用UpdateServerRole
方法,具体请参见下文的修改服务器身份组。
- 调用该方法需要拥有管理频道的权限(
kPermissionManageRole
),且必须是相应服务器的成员。如果没有该权限,调用该方法将返回403
错误码。 - 新创建的服务器自定义身份组的优先级,必须小于用户已有身份组的最高优先级。
- 单个服务器内可创建的服务器身份组数量上限,默认为 20 个。
可在云信控制台配置单个服务器内的身份组数量上限
在云信控制台选择应用,进入IM 即时通讯 > 功能配置 > 圈组 > 子功能配置 > 单server可创建的身份组即可配置。
- 示例代码
CreateServerRoleParam param; param.info.server_id = 123456; param.info.role_name = "role name"; param.info.role_icon = "role icon url"; param.info.extension = "extension"; param.info.role_type = kRoleTypeCustom; param.info.priority = 1; param.anti_spam_info.text_bid = "anti spam text business id"; param.anti_spam_info.pic_bid = "anti spam pic business id"; param.cb = [this](const CreateServerRoleResp& resp) { if (resp.res_code != NIMResCode::kNIMResSuccess) { // error handling return; } // process response // ... }; Role::CreateServerRole(param);
步骤2:修改服务器身份组
调用UpdateServerRole
方法可修改服务器身份组的名称、图标、自定义扩展字段、权限列表配置和优先级(优先级的具体介绍请参见下文的批量更新服务器身份组优先级)。
- 调用该方法需要管理角色权限(
kPermissionManageRole
),且必须是相应服务器的成员。如没有该权限,调用将返回403
错误码。 - 创建服务器时默认创建的 @everyone 身份组仅支持修改其权限配置(且只有服务器创建者可修改),其他属性(身份组的名称、图标、自定义扩展和优先级)不支持修改。 如调用该方法修改 @everyone 身份组的名称、图标、自定义扩展和优先级, 将报错(错误码
403
)。 - 调用该方法修改身份组的优先级必须小于用户已有身份组的最高优先级。
- 用户无法配置自己没有的权限。例如用户没有权限A,则无法修改权限A 的配置。
- 用户无法将自己拥有的某个权限在全部所属身份组中都设置为关闭(
kPermissionSwitchDeny
),如果都关闭,那么将返回403
错误码。例如用户属于 10 个身份组且这 10 个身份组都开启了权限A,那么用户最多可以将其中 9 个身份组的权限A 设置为关闭。
- 示例代码
UpdateServerRoleParam param; param.info.server_id = 123456; param.info.role_id = 123456; param.info.role_name = "role name"; param.info.role_icon = "role icon url"; param.info.extension = "extension"; param.info.permissions[kPermissionManageServer] = kPermissionSwitchAllow; param.info.permissions[kPermissionManageChannel] = kPermissionSwitchDeny; param.info.permissions[kPermissionManageRole] = kPermissionSwitchExtend; param.info.permissions[kPermissionBanServerMember] = kPermissionSwitchAllow param.anti_spam_info.text_bid = "anti spam text business id"; param.anti_spam_info.pic_bid = "anti spam pic business id"; // ... param.info.priority = params["priority"].asUInt64(); param.cb = [this](const UpdateServerRoleResp& resp) { if (resp.res_code != NIMResCode::kNIMResSuccess) { // error handling return; } // process response // ... }; Role::UpdateServerRole(param);
步骤3:添加身份组成员
服务器的 @everyone 身份组的成员,默认为服务器的全部成员。服务器自定义身份组的成员,需要用户手动添加。
调用AddMembersToServerRole
方法可将用户批量添加至指定的服务器自定义身份组。
添加后,继承自该服务器身份组的频道身份组成员也会作相应变化。频道身份组与服务器身份组在成员的具体关联为:公开频道的身份组成员等于被继承的服务器身份组成员去掉频道黑名单成员和频道黑名单身份组成员;私密频道的身份组成员是同时存在于频道白名单和被继承的服务器身份组的公共成员。
- 调用该方法必须先拥有
kPermissionManageRole
权限。如果没有该权限,调用该方法将返回403
错误码。 - 待加入用户必须为身份组所属服务器成员,才能被成功加入该身份组。
- 将用户加入某服务器身份组会触发系统通知。具体的触发条件和接收条件请参考圈组系统通知。
- 示例代码
AddMembersToServerRoleParam param; param.server_id = 123456; param.role_id = 123456; param.members_accids = {"accid1", "accid2"}; param.cb = [this](const AddMembersToServerRoleResp& resp) { if (resp.res_code != NIMResCode::kNIMResSuccess) { // error handling return; } // process response // ... }; Role::AddMembersToServerRole(param);
其他相关 SDK API
移除身份组成员
可调用RemoveMembersFromServerRole
方法将服务器自定义身份组的成员批量移除。
移除服务器身份组成员后,继承自该服务器身份组的频道身份组成员也会作相应变化。频道身份组与服务器身份组在成员的具体关联为:公开频道的身份组成员等于被继承的服务器身份组成员去掉频道黑名单成员和频道黑名单身份组成员;私密频道的身份组成员是同时存在于频道白名单和被继承的服务器身份组的公共成员。
- 调用该方法必须先拥有
kPermissionManageRole
权限。如果没有该权限,调用该方法将返回403
错误码。 - 将用户移出某服务器身份组会触发系统通知。具体的触发条件和接收条件请参考圈组系统通知。
- 示例代码
RemoveMembersFromServerRoleParam param; param.server_id = 123456; param.role_id = 123456; param.members_accids = {"accid1", "accid2"}; param.cb = [this](const RemoveMembersFromServerRoleResp& resp) { if (resp.res_code != NIMResCode::kNIMResSuccess) { // error handling return; } // process response // ... }; Role::RemoveMembersFromServerRole(param);
删除服务器身份组
拥有kPermissionManageRole
权限的用户可调用DeleteServerRole
方法删除包含此权限的自定义身份组。
- 调用该方法必须先拥有
kPermissionManageRole
权限,且必须是相应服务器的成员。如果没有该权限,调用该方法将返回403
错误码。 - @everyone 身份组默认不可删除。
- 用户无法删除优先级高于自己已有身份组的最高优先级的身份组。
-
示例代码
DeleteServerRoleParam param; param.server_id = 123456; param.role_id = 123456; param.cb = [this](const DeleteServerRoleResp& resp) { if (resp.res_code != NIMResCode::kNIMResSuccess) { // error handling return; } // process response // ... }; Role::DeleteServerRole(param);
批量更新服务器身份组优先级
身份组有优先级高低之分,拥有kPermissionkManageRole
权限的高优先级身份组成员,才可修改低优先级身份组的权限配置。
当用户拥有kPermissionkManageRole
权限后,可对优先级低于自身最高优先级身份组的其他身份组进行操作(如修改权限配置),也可创建一个新的自定义身份组,并对其进行优先级排序。比如在 UI 展示中,允许用户拖拽身份组对身份组优先级进行排序,则在排序完成后将最终的排序列表传递到参数中即可。
调用UpdateServerRolePriorities
方法可同时修改多个服务器身份组的优先级。
最佳实践:建议把 priority
为 1 的身份组空出来,不要用在业务上。可以把这个 priority 为 1 的身份组专门留给最高管理员使用,方便后面调整其他身份组的优先级。
- 调用该方法需要拥有
kPermissionManageRole
权限。如果没有该权限,调用该方法将返回403
错误码。当拥有kPermissionManageRole
权限的用户想去变更某个低优先级身份组的某项权限时,首先其自身必须有该权限,即该用户所在的所有身份组中,至少有一个身份组为其赋予过该权限。 - 自定义身份组等级永远高于@everyone身份组。新的自定义身份组被创建后,其优先级默认为用户所属自定义身份组中最低。
- 修改后的优先级必须在修改前的最高优先级和最低优先级之间。比如,修改前 server_role1 优先级 p1,server_role2 优先级 p2,server_role3 优先级 p3,想把他们的优先级分别改为 P1、P2 和 P3,必须满足 min(P1,P2,P3) >= min(p1,p2,p3),max(P1,P2,P3) <= max(p1,p2,p3)。
-
API 调用时序示例
以下时序图以用户A(服务器创建者) 和 用户B(服务器成员)的交互场景为例,展示在调用
UpdateServerRolePriorities
方法前需要实现的业务逻辑。
单击展开查看 API 调用时序示例
sequenceDiagram note over QChat 实例: 初始化与登录 用户A ->> QChat 实例: 初始化 用户B ->> QChat 实例: 初始化 用户A ->> QChat 实例: 登录圈组 用户B ->> QChat 实例: 登录圈组 note over QChat 实例: 用户A 创建服务器 用户A ->> QChat 实例: 创建服务器 note over QChat 实例: 用户A 创建多个身份组并授予用户B 权限 用户A ->> QChat 实例: 创建身份组1 note over 用户A: 身份组1 的优先级默认高于<br>之后新创建的身份组 用户A ->> QChat 实例: 修改身份组1 note over 用户A: 调用修改身份组接口<br>开启身份组1的管理角色权限,<br>使该身份组的成员拥有该权限 用户A ->> QChat 实例: 创建身份组2 用户A ->> QChat 实例: 创建身份组3 用户A ->> QChat 实例: 邀请用户B 加入服务器 用户B ->> QChat 实例: 接受邀请加入服务器 note right of 用户B: 需先加入服务器<br>才能被添加为身份组成员 用户A ->> QChat 实例: 将用户B 加入身份组1 note over 用户A: 用户B 加入身份组1 后,<br>获得管理角色权限 note over QChat 实例: 用户B 批量更新身份组优先级 note over 用户B: 用户B 获得管理角色权限后,<br>可进行身份组管理操作 用户B ->> QChat 实例: 创建身份组4 note over 用户B: 由于用户B 所属的身份组1<br>优先级高于身份组2、3、4,<br>所以用户B 可批量更新2、3、4 的优先级 用户B ->> QChat 实例: 批量更新身份组2,3,4的优先级
-
示例代码
UpdateServerRolePrioritiesParam param; param.server_id = 123456; param.priority_map = {{123456, 1}, {234567, 2}}; param.cb = [this](const UpdateServerRolePrioritiesResp& resp) { if (resp.res_code != NIMResCode::kNIMResSuccess) { // error handling return; } // process response // ... }; Role::UpdateServerRolePriorities(param);