Management: Respect changeInfo and inviteUsers permissions (#1006)

This commit is contained in:
Alexander Zinchuk 2021-04-15 10:33:20 +03:00
parent 2d36553b8f
commit 7324bf85e5
4 changed files with 46 additions and 9 deletions

View File

@ -4,7 +4,9 @@ import { withGlobal } from '../../lib/teact/teactn';
import { ApiChat } from '../../api/types'; import { ApiChat } from '../../api/types';
import { selectChat } from '../../modules/selectors'; import { selectChat } from '../../modules/selectors';
import { getChatDescription, getChatLink } from '../../modules/helpers'; import {
getChatDescription, getChatLink, getHasAdminRight, isChatChannel, isUserRightBanned,
} from '../../modules/helpers';
import renderText from '../common/helpers/renderText'; import renderText from '../common/helpers/renderText';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
@ -16,9 +18,10 @@ type OwnProps = {
type StateProps = { type StateProps = {
chat?: ApiChat; chat?: ApiChat;
canInviteUsers?: boolean;
}; };
const ChatExtra: FC<OwnProps & StateProps> = ({ chat }) => { const ChatExtra: FC<OwnProps & StateProps> = ({ chat, canInviteUsers }) => {
const lang = useLang(); const lang = useLang();
if (!chat || chat.isRestricted) { if (!chat || chat.isRestricted) {
@ -40,7 +43,7 @@ const ChatExtra: FC<OwnProps & StateProps> = ({ chat }) => {
</div> </div>
</div> </div>
)} )}
{!!link.length && ( {canInviteUsers && !!link.length && (
<div className="item"> <div className="item">
<i className="icon-mention" /> <i className="icon-mention" />
<div> <div>
@ -57,6 +60,12 @@ export default memo(withGlobal<OwnProps>(
(global, { chatId }): StateProps => { (global, { chatId }): StateProps => {
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
return { chat };
const canInviteUsers = chat && (
(!isChatChannel(chat) && !isUserRightBanned(chat, 'inviteUsers'))
|| getHasAdminRight(chat, 'inviteUsers')
);
return { chat, canInviteUsers };
}, },
)(ChatExtra)); )(ChatExtra));

View File

@ -9,7 +9,7 @@ import { ManagementScreens, ManagementProgress } from '../../../types';
import { ApiChat, ApiMediaFormat } from '../../../api/types'; import { ApiChat, ApiMediaFormat } from '../../../api/types';
import { pick } from '../../../util/iteratees'; import { pick } from '../../../util/iteratees';
import { getChatAvatarHash } from '../../../modules/helpers'; import { getChatAvatarHash, getHasAdminRight } from '../../../modules/helpers';
import useMedia from '../../../hooks/useMedia'; import useMedia from '../../../hooks/useMedia';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import { selectChat } from '../../../modules/selectors'; import { selectChat } from '../../../modules/selectors';
@ -34,6 +34,7 @@ type StateProps = {
chat: ApiChat; chat: ApiChat;
progress?: ManagementProgress; progress?: ManagementProgress;
isSignaturesShown: boolean; isSignaturesShown: boolean;
canChangeInfo?: boolean;
}; };
type DispatchProps = Pick<GlobalActions, ( type DispatchProps = Pick<GlobalActions, (
@ -47,6 +48,7 @@ const ManageChannel: FC<OwnProps & StateProps & DispatchProps> = ({
chat, chat,
progress, progress,
isSignaturesShown, isSignaturesShown,
canChangeInfo,
onScreenSelect, onScreenSelect,
updateChat, updateChat,
toggleSignatures, toggleSignatures,
@ -156,6 +158,7 @@ const ManageChannel: FC<OwnProps & StateProps & DispatchProps> = ({
<AvatarEditable <AvatarEditable
currentAvatarBlobUrl={currentAvatarBlobUrl} currentAvatarBlobUrl={currentAvatarBlobUrl}
onChange={handleSetPhoto} onChange={handleSetPhoto}
disabled={!canChangeInfo}
/> />
<InputText <InputText
id="channel-title" id="channel-title"
@ -163,6 +166,7 @@ const ManageChannel: FC<OwnProps & StateProps & DispatchProps> = ({
onChange={handleTitleChange} onChange={handleTitleChange}
value={title} value={title}
error={error === CHANNEL_TITLE_EMPTY ? error : undefined} error={error === CHANNEL_TITLE_EMPTY ? error : undefined}
disabled={!canChangeInfo}
/> />
<InputText <InputText
id="channel-about" id="channel-about"
@ -170,6 +174,7 @@ const ManageChannel: FC<OwnProps & StateProps & DispatchProps> = ({
label={lang('DescriptionPlaceholder')} label={lang('DescriptionPlaceholder')}
onChange={handleAboutChange} onChange={handleAboutChange}
value={about} value={about}
disabled={!canChangeInfo}
/> />
{chat.isCreator && ( {chat.isCreator && (
<ListItem icon="lock" ripple onClick={handleClickEditType}> <ListItem icon="lock" ripple onClick={handleClickEditType}>
@ -179,7 +184,7 @@ const ManageChannel: FC<OwnProps & StateProps & DispatchProps> = ({
</div> </div>
</ListItem> </ListItem>
)} )}
<ListItem icon="message" ripple onClick={handleClickDiscussion}> <ListItem icon="message" ripple onClick={handleClickDiscussion} disabled={!canChangeInfo}>
<div className="multiline-item"> <div className="multiline-item">
<span className="title">{lang('Discussion')}</span> <span className="title">{lang('Discussion')}</span>
<span className="subtitle">{hasLinkedChat ? lang('DiscussionUnlink') : lang('Add')}</span> <span className="subtitle">{hasLinkedChat ? lang('DiscussionUnlink') : lang('Add')}</span>
@ -243,7 +248,12 @@ export default memo(withGlobal<OwnProps>(
const { progress } = global.management; const { progress } = global.management;
const isSignaturesShown = Boolean(chat && chat.isSignaturesShown); const isSignaturesShown = Boolean(chat && chat.isSignaturesShown);
return { chat, progress, isSignaturesShown }; return {
chat,
progress,
isSignaturesShown,
canChangeInfo: getHasAdminRight(chat, 'changeInfo'),
};
}, },
(setGlobal, actions): DispatchProps => pick(actions, [ (setGlobal, actions): DispatchProps => pick(actions, [
'toggleSignatures', 'updateChat', 'closeManagement', 'leaveChannel', 'deleteChannel', 'openChat', 'toggleSignatures', 'updateChat', 'closeManagement', 'leaveChannel', 'deleteChannel', 'openChat',

View File

@ -8,7 +8,7 @@ import { ManagementScreens, ManagementProgress } from '../../../types';
import { ApiChat, ApiChatBannedRights, ApiMediaFormat } from '../../../api/types'; import { ApiChat, ApiChatBannedRights, ApiMediaFormat } from '../../../api/types';
import { GlobalActions } from '../../../global/types'; import { GlobalActions } from '../../../global/types';
import { getChatAvatarHash, isChatBasicGroup } from '../../../modules/helpers'; import { getChatAvatarHash, getHasAdminRight, isChatBasicGroup } from '../../../modules/helpers';
import useMedia from '../../../hooks/useMedia'; import useMedia from '../../../hooks/useMedia';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import useFlag from '../../../hooks/useFlag'; import useFlag from '../../../hooks/useFlag';
@ -37,6 +37,8 @@ type StateProps = {
progress?: ManagementProgress; progress?: ManagementProgress;
isBasicGroup: boolean; isBasicGroup: boolean;
hasLinkedChannel: boolean; hasLinkedChannel: boolean;
canChangeInfo?: boolean;
canBanUsers?: boolean;
}; };
type DispatchProps = Pick<GlobalActions, ( type DispatchProps = Pick<GlobalActions, (
@ -56,6 +58,8 @@ const ManageGroup: FC<OwnProps & StateProps & DispatchProps> = ({
progress, progress,
isBasicGroup, isBasicGroup,
hasLinkedChannel, hasLinkedChannel,
canChangeInfo,
canBanUsers,
onScreenSelect, onScreenSelect,
togglePreHistoryHidden, togglePreHistoryHidden,
updateChat, updateChat,
@ -205,6 +209,7 @@ const ManageGroup: FC<OwnProps & StateProps & DispatchProps> = ({
<AvatarEditable <AvatarEditable
currentAvatarBlobUrl={currentAvatarBlobUrl} currentAvatarBlobUrl={currentAvatarBlobUrl}
onChange={handleSetPhoto} onChange={handleSetPhoto}
disabled={!canChangeInfo}
/> />
<InputText <InputText
id="group-title" id="group-title"
@ -212,6 +217,7 @@ const ManageGroup: FC<OwnProps & StateProps & DispatchProps> = ({
onChange={handleTitleChange} onChange={handleTitleChange}
value={title} value={title}
error={error === GROUP_TITLE_EMPTY ? error : undefined} error={error === GROUP_TITLE_EMPTY ? error : undefined}
disabled={!canChangeInfo}
/> />
<InputText <InputText
id="group-about" id="group-about"
@ -219,6 +225,7 @@ const ManageGroup: FC<OwnProps & StateProps & DispatchProps> = ({
label={lang('DescriptionPlaceholder')} label={lang('DescriptionPlaceholder')}
onChange={handleAboutChange} onChange={handleAboutChange}
value={about} value={about}
disabled={!canChangeInfo}
/> />
{chat.isCreator && ( {chat.isCreator && (
<ListItem icon="lock" ripple onClick={handleClickEditType}> <ListItem icon="lock" ripple onClick={handleClickEditType}>
@ -236,7 +243,7 @@ const ManageGroup: FC<OwnProps & StateProps & DispatchProps> = ({
</div> </div>
</ListItem> </ListItem>
)} )}
<ListItem icon="permissions" ripple onClick={handleClickPermissions}> <ListItem icon="permissions" ripple onClick={handleClickPermissions} disabled={!canBanUsers}>
<div className="multiline-item"> <div className="multiline-item">
<span className="title">{lang('ChannelPermissions')}</span> <span className="title">{lang('ChannelPermissions')}</span>
<span className="subtitle">{enabledPermissionsCount}/{TOTAL_PERMISSIONS_COUNT}</span> <span className="subtitle">{enabledPermissionsCount}/{TOTAL_PERMISSIONS_COUNT}</span>
@ -263,6 +270,7 @@ const ManageGroup: FC<OwnProps & StateProps & DispatchProps> = ({
checked={!chat.fullInfo.isPreHistoryHidden} checked={!chat.fullInfo.isPreHistoryHidden}
label={lang('ChatHistory')} label={lang('ChatHistory')}
onChange={handleTogglePreHistory} onChange={handleTogglePreHistory}
disabled={!canBanUsers}
/> />
</div> </div>
)} )}
@ -313,6 +321,8 @@ export default memo(withGlobal<OwnProps>(
progress, progress,
isBasicGroup: isChatBasicGroup(chat), isBasicGroup: isChatBasicGroup(chat),
hasLinkedChannel, hasLinkedChannel,
canChangeInfo: getHasAdminRight(chat, 'changeInfo'),
canBanUsers: getHasAdminRight(chat, 'banUsers'),
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [ (setGlobal, actions): DispatchProps => pick(actions, [

View File

@ -71,6 +71,14 @@
&.disabled { &.disabled {
pointer-events: none; pointer-events: none;
i {
display: none;
}
&::after {
display: none;
}
} }
} }
} }