disallow remove of an admin from a closed group

This commit is contained in:
Audric Ackermann 2021-01-13 12:36:31 +11:00
parent 19f59ca41e
commit 6cf838ade8
No known key found for this signature in database
GPG key ID: 999F434D76324AD4
9 changed files with 45 additions and 44 deletions

View file

@ -1748,6 +1748,14 @@
"message": "As you are the admin of this group, if you leave it it will be removed for every current members. Are you sure you want to leave this group?",
"description": "Confirmation dialog text that tells the user what will happen if they leave the group as admin."
},
"cannotRemoveCreatorFromGroup": {
"message": "Cannot remove this user",
"description": "Toast title when the user tries to remove the creator from a closed group v2 member list."
},
"cannotRemoveCreatorFromGroupDesc": {
"message": "You cannot remove this user as he is the creator of the group.",
"description": "Toast description when the user tries to remove the creator from a closed group v2 member list."
},
"noContactsForGroup": {
"message": "You don't have any contacts yet",
"androidKey": "activity_create_closed_group_empty_state_message"

View file

@ -34,8 +34,6 @@
upgradeMessageSchema,
loadAttachmentData,
getAbsoluteAttachmentPath,
// eslint-disable-next-line no-unused-vars
writeNewAttachmentData,
deleteAttachmentData,
} = window.Signal.Migrations;

View file

@ -105,6 +105,7 @@
this.isAdmin = groupConvo.isMediumGroup()
? true
: groupConvo.get('groupAdmins').includes(ourPK);
this.admins = groupConvo.get('groupAdmins');
const convos = window
.getConversationController()
.getConversations()
@ -142,6 +143,7 @@
existingMembers: this.existingMembers,
contactList: this.contactsAndMembers,
isAdmin: this.isAdmin,
admins: this.admins,
onClose: this.close,
onSubmit: this.onSubmit,
groupId: this.groupId,

View file

@ -113,13 +113,16 @@ class InviteContactsDialogInner extends React.Component<Props, State> {
private renderMemberList() {
const members = this.state.contactList;
const selectedContacts = this.state.contactList
.filter(d => d.checkmarked)
.map(d => d.id);
return members.map((member: ContactType, index: number) => (
<SessionMemberListItem
member={member}
key={index}
index={index}
isSelected={false}
isSelected={selectedContacts.some(m => m === member.id)}
onSelect={(selectedMember: ContactType) => {
this.onMemberClicked(selectedMember);
}}

View file

@ -9,6 +9,7 @@ import {
SessionMemberListItem,
} from '../session/SessionMemberListItem';
import { DefaultTheme } from 'styled-components';
import { ToastUtils } from '../../session/utils';
interface Props {
titleText: string;
@ -19,6 +20,8 @@ interface Props {
contactList: Array<any>;
isAdmin: boolean;
existingMembers: Array<String>;
admins: Array<String>; // used for closed group v2
i18n: any;
onSubmit: any;
onClose: any;
@ -165,23 +168,6 @@ export class UpdateGroupMembersDialog extends React.Component<Props, State> {
));
}
private onShowError(msg: string) {
if (this.state.errorDisplayed) {
return;
}
this.setState({
errorDisplayed: true,
errorMessage: msg,
});
setTimeout(() => {
this.setState({
errorDisplayed: false,
});
}, 3000);
}
private onKeyUp(event: any) {
switch (event.key) {
case 'Enter':
@ -218,12 +204,23 @@ export class UpdateGroupMembersDialog extends React.Component<Props, State> {
}
private onMemberClicked(selected: any) {
if (selected.existingMember && !this.props.isAdmin) {
const { isAdmin, admins } = this.props;
const { contactList } = this.state;
if (selected.existingMember && !isAdmin) {
window.log.warn('Only group admin can remove members!');
return;
}
const updatedContacts = this.state.contactList.map(member => {
if (selected.existingMember && admins.includes(selected.id)) {
window.log.warn(
`User ${selected.id} cannot be removed as he is the creator of this closed group v2.`
);
ToastUtils.pushCannotRemoveCreatorFromGroup();
return;
}
const updatedContacts = contactList.map(member => {
if (member.id === selected.id) {
return { ...member, checkmarked: !member.checkmarked };
} else {

View file

@ -13,7 +13,6 @@ import {
} from './SessionButton';
import { SessionSpinner } from './SessionSpinner';
import { PillDivider } from './PillDivider';
import classNames from 'classnames';
import { DefaultTheme } from 'styled-components';
export enum SessionClosableOverlayType {
@ -274,10 +273,11 @@ export class SessionClosableOverlay extends React.Component<Props, State> {
private renderMemberList(members: any) {
return members.map((member: ContactType, index: number) => (
// tslint:disable-next-line: use-simple-attributes
<SessionMemberListItem
member={member}
index={index}
isSelected={false}
isSelected={this.state.selectedMembers.some(m => m.id === member.id)}
key={member.id}
onSelect={(selectedMember: ContactType) => {
this.handleSelectMember(selectedMember);

View file

@ -26,11 +26,7 @@ interface Props {
theme: DefaultTheme;
}
interface State {
isSelected: boolean;
}
class SessionMemberListItemInner extends React.Component<Props, State> {
class SessionMemberListItemInner extends React.Component<Props> {
public static defaultProps = {
isSelected: false,
};
@ -38,10 +34,6 @@ class SessionMemberListItemInner extends React.Component<Props, State> {
constructor(props: any) {
super(props);
this.state = {
isSelected: this.props.isSelected,
};
this.handleSelectionAction = this.handleSelectionAction.bind(this);
this.selectMember = this.selectMember.bind(this);
this.unselectMember = this.unselectMember.bind(this);
@ -49,7 +41,7 @@ class SessionMemberListItemInner extends React.Component<Props, State> {
}
public render() {
const { isSelected } = this.state;
const { isSelected } = this.props;
const name = this.props.member.authorProfileName;
@ -105,7 +97,7 @@ class SessionMemberListItemInner extends React.Component<Props, State> {
}
private handleSelectionAction() {
if (this.state.isSelected) {
if (this.props.isSelected) {
this.unselectMember();
return;
@ -115,20 +107,12 @@ class SessionMemberListItemInner extends React.Component<Props, State> {
}
private selectMember() {
this.setState({
isSelected: true,
});
if (this.props.onSelect) {
this.props.onSelect(this.props.member);
}
}
private unselectMember() {
this.setState({
isSelected: false,
});
if (this.props.onUnselect) {
this.props.onUnselect(this.props.member);
}

View file

@ -251,3 +251,11 @@ export function pushDeleted() {
SessionIconType.Check
);
}
export function pushCannotRemoveCreatorFromGroup() {
pushToastWarning(
'cannotRemoveCreatorFromGroup',
window.i18n('cannotRemoveCreatorFromGroup'),
window.i18n('cannotRemoveCreatorFromGroupDesc')
);
}

View file

@ -24,7 +24,8 @@ class StubMessageAPI {
const data64 = StringUtils.decode(data, 'base64');
await fetch(
`${this.baseUrl
`${
this.baseUrl
}/messages?pubkey=${pubKey}&timestamp=${messageTimeStamp}&data=${encodeURIComponent(
data64
)}`,