From 8b89b265c15d709c0d6f19ec91f9ee749a1937ca Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Mon, 11 Sep 2023 20:43:06 +0800 Subject: [PATCH] feat: add role based send text message permission control --- client/shared/index.tsx | 2 + .../shared/redux/hooks/useGroupPermission.ts | 65 +++++++++++++++++++ .../src/components/Panel/group/TextPanel.tsx | 8 +-- 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/client/shared/index.tsx b/client/shared/index.tsx index 37fafbfa..6e344b2a 100644 --- a/client/shared/index.tsx +++ b/client/shared/index.tsx @@ -211,7 +211,9 @@ export { useGroupAck } from './redux/hooks/useGroupAck'; export { useGroupMemberMute } from './redux/hooks/useGroupMemberMute'; export { useGroupMemberAllPermissions, + useGroupPanelMemberAllPermissions, useHasGroupPermission, + useHasGroupPanelPermission, } from './redux/hooks/useGroupPermission'; export { useUserInfo, useUserId } from './redux/hooks/useUserInfo'; export { useInboxList, useInboxItem } from './redux/hooks/useInbox'; diff --git a/client/shared/redux/hooks/useGroupPermission.ts b/client/shared/redux/hooks/useGroupPermission.ts index b7b69a97..9e604841 100644 --- a/client/shared/redux/hooks/useGroupPermission.ts +++ b/client/shared/redux/hooks/useGroupPermission.ts @@ -47,6 +47,41 @@ export function useGroupMemberAllPermissions(groupId: string): string[] { return userPermissions; } +/** + * 获取面板的所有权限 + * 不包含群组本身的权限 + */ +export function useGroupPanelMemberAllPermissions( + groupId: string, + panelId: string +): string[] { + const groupInfo = useGroupInfo(groupId); + const userId = useUserId(); + + if (!groupInfo || !userId) { + return []; + } + + const panelInfo = groupInfo.panels.find((p) => p.id === panelId); + if (!panelInfo) { + return []; + } + + const fallbackPermissions = panelInfo.fallbackPermissions ?? []; + const permissionMap = panelInfo.permissionMap ?? {}; + const specPermissions = permissionMap[userId] ?? []; + + const userRoles = + groupInfo.members.find((m) => m.userId === userId)?.roles ?? []; // 当前用户角色 + const userPanelPermissions = _uniq([ + ..._flatten(userRoles.map((roleId) => permissionMap[roleId] ?? [])), + ...specPermissions, + ...fallbackPermissions, + ]); + + return userPanelPermissions; +} + /** * 判断用户是否拥有以下权限 */ @@ -70,3 +105,33 @@ export function useHasGroupPermission( return result; } + +/** + * 判断用户是否在某个面板下拥有以下权限 + * 用于面板权限控制 + */ +export function useHasGroupPanelPermission( + groupId: string, + panelId: string, + permissions: string[] +) { + const groupPermissions = useGroupMemberAllPermissions(groupId); + const panelPermissions = useGroupPanelMemberAllPermissions(groupId, panelId); + + const fullPermissions = _uniq([...groupPermissions, ...panelPermissions]); + + const result = useMemo( + () => permissions.map((p) => fullPermissions.includes(p)), + [fullPermissions.join(','), permissions.join(',')] + ); + + useDebugValue({ + groupId, + panelId, + fullPermissions, + checkedPermissions: permissions, + result, + }); + + return result; +} diff --git a/client/web/src/components/Panel/group/TextPanel.tsx b/client/web/src/components/Panel/group/TextPanel.tsx index 3b1230d8..42046caa 100644 --- a/client/web/src/components/Panel/group/TextPanel.tsx +++ b/client/web/src/components/Panel/group/TextPanel.tsx @@ -14,10 +14,10 @@ import { t, humanizeMsDuration, useInterval, - useHasGroupPermission, PERMISSION, useGroupInfo, GroupPanelType, + useHasGroupPanelPermission, } from 'tailchat-shared'; import { useFriendNicknameMap } from 'tailchat-shared/redux/hooks/useFriendNickname'; import { MembersPanel } from './MembersPanel'; @@ -26,10 +26,10 @@ import { GroupPanelContainer } from './shared/GroupPanelContainer'; /** * 聊天输入框显示状态管理 */ -function useChatInputInfo(groupId: string) { +function useChatInputInfo(groupId: string, panelId: string) { const userId = useUserId(); const muteUntil = useGroupMemberMute(groupId, userId ?? ''); - const [hasPermission] = useHasGroupPermission(groupId, [ + const [hasPermission] = useHasGroupPanelPermission(groupId, panelId, [ PERMISSION.core.message, ]); @@ -80,7 +80,7 @@ export const TextPanel: React.FC = React.memo( const group = useGroupInfo(groupId); const groupMembers = useGroupMemberInfos(groupId); const panelInfo = useGroupPanelInfo(groupId, panelId); - const { disabled, placeholder } = useChatInputInfo(groupId); + const { disabled, placeholder } = useChatInputInfo(groupId, panelId); const friendNicknameMap = useFriendNicknameMap(); if (!group) {