Monoforum: Fix admin rights check (#6538)
This commit is contained in:
parent
9b17732097
commit
ade72a0727
@ -197,6 +197,7 @@ export interface ApiChatAdminRights {
|
||||
postStories?: true;
|
||||
editStories?: true;
|
||||
deleteStories?: true;
|
||||
manageDirectMessages?: true;
|
||||
}
|
||||
|
||||
export interface ApiChatBannedRights {
|
||||
|
||||
@ -955,6 +955,14 @@
|
||||
"EditAdminBanUsers" = "Ban Users";
|
||||
"EditAdminPinMessages" = "Pin Messages";
|
||||
"EditAdminAddAdmins" = "Add New Admins";
|
||||
"EditAdminManageDirect" = "Manage Direct Messages";
|
||||
"EditAdminPostStories" = "Post Stories";
|
||||
"EditAdminEditStories" = "Edit Stories of Others";
|
||||
"EditAdminDeleteStories" = "Delete Stories of Others";
|
||||
"EditAdminManageTopics" = "Manage Topics";
|
||||
"EditAdminUnavailable" = "You can't edit the rights of this admin.";
|
||||
"EditAdminConfirmDismissText" = "Are you sure you want to dismiss this admin?";
|
||||
"EditAdminConfirmDismiss" = "Dismiss Admin";
|
||||
"StartVoipChatPermission" = "Manage Video Chats";
|
||||
"EditAdminSendAnonymously" = "Remain Anonymous";
|
||||
"ChannelEditAdminCannotEdit" = "You can't edit the rights of this admin.";
|
||||
|
||||
@ -24,7 +24,8 @@ import {
|
||||
selectBot,
|
||||
selectCanDeleteSelectedMessages,
|
||||
selectChat,
|
||||
selectChatFullInfo, selectIsChatWithBot,
|
||||
selectChatFullInfo,
|
||||
selectIsChatWithBot,
|
||||
selectSenderFromMessage,
|
||||
selectTabState,
|
||||
selectUser,
|
||||
@ -164,7 +165,7 @@ const DeleteMessageModal: FC<OwnProps & StateProps> = ({
|
||||
|
||||
const peerListToBan = useMemo(() => {
|
||||
const isCurrentUserInList = peerList.some((peer) => peer.id === currentUserId);
|
||||
const shouldReturnEmpty = !canBanUsers || isCurrentUserInList || chat?.isMonoforum;
|
||||
const shouldReturnEmpty = !canBanUsers || isCurrentUserInList;
|
||||
|
||||
if (shouldReturnEmpty) {
|
||||
return MEMO_EMPTY_ARRAY;
|
||||
@ -174,7 +175,7 @@ const DeleteMessageModal: FC<OwnProps & StateProps> = ({
|
||||
const isAdmin = adminMembersById?.[peer.id];
|
||||
return isCreator || !isAdmin;
|
||||
});
|
||||
}, [peerList, isCreator, currentUserId, canBanUsers, adminMembersById, chat?.isMonoforum]);
|
||||
}, [peerList, isCreator, currentUserId, canBanUsers, adminMembersById]);
|
||||
|
||||
const shouldShowAdditionalOptions = useMemo(() => {
|
||||
return Boolean(peerListToDeleteAll.length || peerListToReportSpam.length || peerListToBan.length);
|
||||
@ -510,7 +511,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
: undefined;
|
||||
const chatBot = Boolean(chat && !isSystemBot(chat.id) && selectBot(global, chat.id));
|
||||
const adminMembersById = chatFullInfo?.adminMembersById;
|
||||
const canBanUsers = chat && getHasAdminRight(chat, 'banUsers');
|
||||
const canBanUsers = chat && getHasAdminRight(chat, 'banUsers') && !chat.isMonoforum; // TODO: Ban in channel in case of monoforum
|
||||
const isCreator = chat?.isCreator;
|
||||
const isChatWithBot = chat ? selectIsChatWithBot(global, chat) : undefined;
|
||||
const willDeleteForCurrentUserOnly = (chat && isChatBasicGroup(chat) && !canDeleteForAll) || isChatWithBot;
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import type React from '../../lib/teact/teact';
|
||||
import {
|
||||
memo, useMemo,
|
||||
} from '../../lib/teact/teact';
|
||||
@ -19,15 +17,15 @@ import Checkbox from '../ui/Checkbox';
|
||||
|
||||
export type OwnProps = {
|
||||
chatId?: string;
|
||||
handlePermissionChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
permissions: ApiChatBannedRights;
|
||||
isMediaDropdownOpen: boolean;
|
||||
setIsMediaDropdownOpen: (open: boolean) => void;
|
||||
className?: string;
|
||||
shiftedClassName?: string;
|
||||
dropdownClassName?: string;
|
||||
withCheckbox?: boolean;
|
||||
permissionGroup?: boolean;
|
||||
handlePermissionChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
setIsMediaDropdownOpen: (open: boolean) => void;
|
||||
getControlIsDisabled?: (key: Exclude<keyof ApiChatBannedRights, 'untilDate'>) => boolean | undefined;
|
||||
};
|
||||
|
||||
@ -41,20 +39,20 @@ const permissionKeyList: (keyof ApiChatBannedRights)[] = [
|
||||
'sendAudios', 'sendDocs', 'sendVoices', 'sendRoundvideos', 'embedLinks', 'sendPolls',
|
||||
];
|
||||
|
||||
const PermissionCheckboxList: FC<OwnProps & StateProps> = ({
|
||||
const PermissionCheckboxList = ({
|
||||
chat,
|
||||
isMediaDropdownOpen,
|
||||
setIsMediaDropdownOpen,
|
||||
hasLinkedChat,
|
||||
permissions,
|
||||
handlePermissionChange,
|
||||
className,
|
||||
shiftedClassName,
|
||||
dropdownClassName,
|
||||
withCheckbox,
|
||||
getControlIsDisabled,
|
||||
permissionGroup,
|
||||
}) => {
|
||||
setIsMediaDropdownOpen,
|
||||
handlePermissionChange,
|
||||
getControlIsDisabled,
|
||||
}: OwnProps & StateProps) => {
|
||||
const {
|
||||
showNotification,
|
||||
} = getActions();
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import type React from '../../../lib/teact/teact';
|
||||
import {
|
||||
memo, useCallback, useEffect, useMemo, useState,
|
||||
} from '../../../lib/teact/teact';
|
||||
@ -15,7 +13,7 @@ import { selectChat, selectChatFullInfo } from '../../../global/selectors';
|
||||
|
||||
import useFlag from '../../../hooks/useFlag';
|
||||
import useHistoryBack from '../../../hooks/useHistoryBack';
|
||||
import useOldLang from '../../../hooks/useOldLang';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
|
||||
import PrivateChatInfo from '../../common/PrivateChatInfo';
|
||||
import Checkbox from '../../ui/Checkbox';
|
||||
@ -40,15 +38,13 @@ type StateProps = {
|
||||
adminMembersById?: Record<string, ApiChatMember>;
|
||||
hasFullInfo: boolean;
|
||||
currentUserId?: string;
|
||||
isChannel: boolean;
|
||||
isFormFullyDisabled: boolean;
|
||||
isForum?: boolean;
|
||||
defaultRights?: ApiChatAdminRights;
|
||||
};
|
||||
|
||||
const CUSTOM_TITLE_MAX_LENGTH = 16;
|
||||
|
||||
const ManageGroupAdminRights: FC<OwnProps & StateProps> = ({
|
||||
const ManageGroupAdminRights = ({
|
||||
isActive,
|
||||
isNewAdmin,
|
||||
selectedUserId,
|
||||
@ -58,12 +54,10 @@ const ManageGroupAdminRights: FC<OwnProps & StateProps> = ({
|
||||
currentUserId,
|
||||
adminMembersById,
|
||||
hasFullInfo,
|
||||
isChannel,
|
||||
isForum,
|
||||
isFormFullyDisabled,
|
||||
onClose,
|
||||
onScreenSelect,
|
||||
}) => {
|
||||
}: OwnProps & StateProps) => {
|
||||
const { updateChatAdmin } = getActions();
|
||||
|
||||
const [permissions, setPermissions] = useState<ApiChatAdminRights>({});
|
||||
@ -71,7 +65,11 @@ const ManageGroupAdminRights: FC<OwnProps & StateProps> = ({
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isDismissConfirmationDialogOpen, openDismissConfirmationDialog, closeDismissConfirmationDialog] = useFlag();
|
||||
const [customTitle, setCustomTitle] = useState('');
|
||||
const lang = useOldLang();
|
||||
const lang = useLang();
|
||||
|
||||
const isChannel = isChatChannel(chat);
|
||||
const isForum = chat.isForum;
|
||||
const hasDirectMessages = Boolean(chat.linkedMonoforumId);
|
||||
|
||||
useHistoryBack({
|
||||
isActive,
|
||||
@ -186,7 +184,7 @@ const ManageGroupAdminRights: FC<OwnProps & StateProps> = ({
|
||||
: undefined;
|
||||
|
||||
if (promotedByUser) {
|
||||
return lang('EditAdminPromotedBy', getUserFullName(promotedByUser));
|
||||
return lang('EditAdminPromotedBy', { user: getUserFullName(promotedByUser) });
|
||||
}
|
||||
|
||||
return lang('ChannelAdmin');
|
||||
@ -290,18 +288,28 @@ const ManageGroupAdminRights: FC<OwnProps & StateProps> = ({
|
||||
onChange={handlePermissionChange}
|
||||
/>
|
||||
</div>
|
||||
{!isChannel && (
|
||||
{hasDirectMessages && (
|
||||
<div className="ListItem">
|
||||
<Checkbox
|
||||
name="banUsers"
|
||||
checked={Boolean(permissions.banUsers)}
|
||||
label={lang('EditAdminBanUsers')}
|
||||
name="manageDirectMessages"
|
||||
checked={Boolean(permissions.manageDirectMessages)}
|
||||
label={lang('EditAdminManageDirect')}
|
||||
blocking
|
||||
disabled={getControlIsDisabled('banUsers')}
|
||||
disabled={getControlIsDisabled('manageDirectMessages')}
|
||||
onChange={handlePermissionChange}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="ListItem">
|
||||
<Checkbox
|
||||
name="banUsers"
|
||||
checked={Boolean(permissions.banUsers)}
|
||||
label={lang('EditAdminBanUsers')}
|
||||
blocking
|
||||
disabled={getControlIsDisabled('banUsers')}
|
||||
onChange={handlePermissionChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="ListItem">
|
||||
<Checkbox
|
||||
name="inviteUsers"
|
||||
@ -349,7 +357,7 @@ const ManageGroupAdminRights: FC<OwnProps & StateProps> = ({
|
||||
<Checkbox
|
||||
name="manageTopics"
|
||||
checked={Boolean(permissions.manageTopics)}
|
||||
label={lang('ManageTopicsPermission')}
|
||||
label={lang('EditAdminManageTopics')}
|
||||
blocking
|
||||
disabled={getControlIsDisabled('manageTopics')}
|
||||
onChange={handlePermissionChange}
|
||||
@ -371,7 +379,7 @@ const ManageGroupAdminRights: FC<OwnProps & StateProps> = ({
|
||||
|
||||
{isFormFullyDisabled && (
|
||||
<p className="section-info mb-4" dir="auto">
|
||||
{lang('Channel.EditAdmin.CannotEdit')}
|
||||
{lang('EditAdminUnavailable')}
|
||||
</p>
|
||||
)}
|
||||
|
||||
@ -407,8 +415,8 @@ const ManageGroupAdminRights: FC<OwnProps & StateProps> = ({
|
||||
<ConfirmDialog
|
||||
isOpen={isDismissConfirmationDialogOpen}
|
||||
onClose={closeDismissConfirmationDialog}
|
||||
text="Are you sure you want to dismiss this admin?"
|
||||
confirmLabel={lang('Channel.Admin.Dismiss')}
|
||||
text={lang('EditAdminConfirmDismissText')}
|
||||
confirmLabel={lang('EditAdminConfirmDismiss')}
|
||||
confirmHandler={handleDismissAdmin}
|
||||
confirmIsDestructive
|
||||
/>
|
||||
@ -423,16 +431,12 @@ export default memo(withGlobal<OwnProps>(
|
||||
const fullInfo = selectChatFullInfo(global, chatId);
|
||||
const { byId: usersById } = global.users;
|
||||
const { currentUserId } = global;
|
||||
const isChannel = isChatChannel(chat);
|
||||
const isFormFullyDisabled = !(chat.isCreator || isPromotedByCurrentUser);
|
||||
const isForum = chat.isForum;
|
||||
|
||||
return {
|
||||
chat,
|
||||
usersById,
|
||||
currentUserId,
|
||||
isChannel,
|
||||
isForum,
|
||||
isFormFullyDisabled,
|
||||
defaultRights: chat.adminRights,
|
||||
hasFullInfo: Boolean(fullInfo),
|
||||
|
||||
@ -17,6 +17,7 @@ import {
|
||||
deletePeerPhoto,
|
||||
leaveChat,
|
||||
removeUnreadMentions,
|
||||
replaceChatMessages,
|
||||
replacePeerPhotos,
|
||||
replacePinnedTopicIds,
|
||||
replaceThreadParam,
|
||||
@ -69,6 +70,15 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
|
||||
global = updatePeerStoriesHidden(global, update.id, update.chat.areStoriesHidden || false);
|
||||
}
|
||||
|
||||
const localAdminRights = localChat?.adminRights;
|
||||
const newAdminRights = update.chat.adminRights;
|
||||
|
||||
if (localAdminRights && localAdminRights.manageDirectMessages && !update.chat.isMin
|
||||
&& newAdminRights?.manageDirectMessages !== localAdminRights.manageDirectMessages
|
||||
&& localChat.linkedMonoforumId) {
|
||||
global = replaceChatMessages(global, localChat.linkedMonoforumId, {});
|
||||
}
|
||||
|
||||
setGlobal(global);
|
||||
|
||||
const updatedChat = selectChat(global, update.id);
|
||||
|
||||
@ -96,7 +96,9 @@ export function updateCurrentMessageList<T extends GlobalState>(
|
||||
}, tabId);
|
||||
}
|
||||
|
||||
function replaceChatMessages<T extends GlobalState>(global: T, chatId: string, newById: Record<number, ApiMessage>): T {
|
||||
export function replaceChatMessages<T extends GlobalState>(
|
||||
global: T, chatId: string, newById: Record<number, ApiMessage>,
|
||||
): T {
|
||||
return updateMessageStore(global, chatId, {
|
||||
byId: newById,
|
||||
});
|
||||
|
||||
@ -360,7 +360,7 @@ export function selectIsMonoforumAdmin<T extends GlobalState>(
|
||||
const channel = selectMonoforumChannel(global, chatId);
|
||||
if (!channel) return;
|
||||
|
||||
return Boolean(chat.isCreator || chat.adminRights || channel.isCreator || channel.adminRights);
|
||||
return Boolean(chat.isCreator || getHasAdminRight(channel, 'manageDirectMessages'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -5,7 +5,7 @@ import { SERVICE_NOTIFICATIONS_USER_ID } from '../../config';
|
||||
import { isUserId } from '../../util/entities/ids';
|
||||
import { getCurrentTabId } from '../../util/establishMultitabRole';
|
||||
import { getHasAdminRight, isChatAdmin, isChatChannel, isDeletedUser } from '../helpers';
|
||||
import { selectChat, selectChatFullInfo } from './chats';
|
||||
import { selectChat, selectChatFullInfo, selectIsMonoforumAdmin } from './chats';
|
||||
import { type ProfileCollectionKey } from './payments';
|
||||
import { selectTabState } from './tabs';
|
||||
import { selectBot, selectUser, selectUserFullInfo } from './users';
|
||||
@ -66,7 +66,7 @@ export function selectPeerPaidMessagesStars<T extends GlobalState>(
|
||||
|
||||
const chat = selectChat(global, peerId);
|
||||
if (!chat) return undefined;
|
||||
if (isChatAdmin(chat)) return undefined;
|
||||
if (isChatAdmin(chat) || selectIsMonoforumAdmin(global, chat.id)) return undefined;
|
||||
return chat.paidMessagesStars;
|
||||
}
|
||||
|
||||
|
||||
8
src/types/language.d.ts
vendored
8
src/types/language.d.ts
vendored
@ -831,6 +831,14 @@ export interface LangPair {
|
||||
'EditAdminBanUsers': undefined;
|
||||
'EditAdminPinMessages': undefined;
|
||||
'EditAdminAddAdmins': undefined;
|
||||
'EditAdminManageDirect': undefined;
|
||||
'EditAdminPostStories': undefined;
|
||||
'EditAdminEditStories': undefined;
|
||||
'EditAdminDeleteStories': undefined;
|
||||
'EditAdminManageTopics': undefined;
|
||||
'EditAdminUnavailable': undefined;
|
||||
'EditAdminConfirmDismissText': undefined;
|
||||
'EditAdminConfirmDismiss': undefined;
|
||||
'StartVoipChatPermission': undefined;
|
||||
'EditAdminSendAnonymously': undefined;
|
||||
'ChannelEditAdminCannotEdit': undefined;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user