fix: send msg to group unapproved accepts and then sends message

pull/2963/head
Audric Ackermann 1 year ago
parent 5867c5af7f
commit b9da60af3b

@ -2,14 +2,9 @@ import React from 'react';
import styled from 'styled-components';
import { useIsIncomingRequest } from '../../hooks/useParamSelector';
import {
approveConvoAndSendResponse,
declineConversationWithConfirm,
handleAcceptConversationRequest,
} from '../../interactions/conversationInteractions';
import { GroupV2Receiver } from '../../receiver/groupv2/handleGroupV2Message';
import { getSwarmPollingInstance } from '../../session/apis/snode_api/swarmPolling';
import { ConvoHub } from '../../session/conversations';
import { PubKey } from '../../session/types';
import { sleepFor } from '../../session/utils/Promise';
import {
useSelectedConversationIdOrigin,
useSelectedConversationKey,
@ -17,7 +12,6 @@ import {
useSelectedIsPrivateFriend,
} from '../../state/selectors/selectedConversation';
import { useLibGroupInvitePending } from '../../state/selectors/userGroups';
import { UserGroupsWrapperActions } from '../../webworker/workers/browser/libsession_worker_interface';
import { SessionButton, SessionButtonColor } from '../basic/SessionButton';
import { InvitedToGroupControlMessage, MessageRequestExplanation } from './SubtleNotification';
@ -77,34 +71,6 @@ const handleDeclineAndBlockConversationRequest = (
});
};
const handleAcceptConversationRequest = async (convoId: string) => {
const convo = ConvoHub.use().get(convoId);
if (!convo) {
return;
}
await convo.setDidApproveMe(true, false);
await convo.setIsApproved(true, false);
await convo.commit();
if (convo.isPrivate()) {
await convo.addOutgoingApprovalMessage(Date.now());
await approveConvoAndSendResponse(convoId);
} else if (PubKey.is03Pubkey(convoId)) {
const found = await UserGroupsWrapperActions.getGroup(convoId);
if (!found) {
window.log.warn('cannot approve a non existing group in usergroup');
return;
}
// this updates the wrapper and refresh the redux slice
await UserGroupsWrapperActions.setGroup({ ...found, invitePending: false });
getSwarmPollingInstance().addGroupId(convoId, async () => {
// we need to do a first poll to fetch the keys etc before we can send our invite response
// this is pretty hacky, but also an admin seeing a message from that user in the group will mark it as not pending anymore
await sleepFor(2000);
await GroupV2Receiver.sendInviteResponseToGroup({ groupPk: convoId });
});
}
};
export const ConversationMessageRequestButtons = () => {
const selectedConvoId = useSelectedConversationKey();
const isIncomingRequest = useIsIncomingRequest(selectedConvoId);
@ -131,7 +97,7 @@ export const ConversationMessageRequestButtons = () => {
<ConversationBannerRow>
<SessionButton
onClick={async () => {
await handleAcceptConversationRequest(selectedConvoId);
await handleAcceptConversationRequest({ convoId: selectedConvoId, sendResponse: true });
}}
text={window.i18n('accept')}
dataTestId="accept-message-request"

@ -4,9 +4,10 @@ import { Item, Menu } from 'react-contexify';
import { useSelector } from 'react-redux';
import { useIsPinned, useIsPrivate, useIsPrivateAndFriend } from '../../hooks/useParamSelector';
import { ConvoHub } from '../../session/conversations';
import { isSearching } from '../../state/selectors/search';
import { getIsMessageSection } from '../../state/selectors/section';
import { useConvoIdFromContext } from '../leftpane/conversation-list-item/ConvoIdContext';
import { SessionContextMenuContainer } from '../SessionContextMenuContainer';
import { useConvoIdFromContext } from '../leftpane/conversation-list-item/ConvoIdContext';
import {
AcceptMsgRequestMenuItem,
BanMenuItem,
@ -17,16 +18,15 @@ import {
DeclineAndBlockMsgRequestMenuItem,
DeclineMsgRequestMenuItem,
DeleteMessagesMenuItem,
DeletePrivateConversationMenuItem,
InviteContactMenuItem,
LeaveGroupOrCommunityMenuItem,
MarkAllReadMenuItem,
MarkConversationUnreadMenuItem,
NotificationForConvoMenuItem,
ShowUserDetailsMenuItem,
UnbanMenuItem,
DeletePrivateConversationMenuItem,
NotificationForConvoMenuItem,
} from './Menu';
import { isSearching } from '../../state/selectors/search';
export type PropsContextConversationItem = {
triggerId: string;

@ -23,12 +23,12 @@ import {
import {
ConversationInteractionStatus,
ConversationInteractionType,
approveConvoAndSendResponse,
blockConvoById,
clearNickNameByConvoId,
copyPublicKeyByConvoId,
declineConversationWithConfirm,
deleteAllMessagesByConvoIdWithConfirmation,
handleAcceptConversationRequest,
markAllReadByConvoId,
setNotificationForConvoId,
showAddModeratorsByConvoId,
@ -441,17 +441,17 @@ export const DeletePrivateConversationMenuItem = () => {
export const AcceptMsgRequestMenuItem = () => {
const convoId = useConvoIdFromContext();
const isRequest = useIsIncomingRequest(convoId);
const convo = ConvoHub.use().get(convoId);
const isPrivate = useIsPrivate(convoId);
if (isRequest && isPrivate) {
if (isRequest && (isPrivate || PubKey.is03Pubkey(convoId))) {
return (
<Item
// eslint-disable-next-line @typescript-eslint/no-misused-promises
onClick={async () => {
await convo.setDidApproveMe(true);
await convo.addOutgoingApprovalMessage(Date.now());
await approveConvoAndSendResponse(convoId);
await handleAcceptConversationRequest({
convoId,
sendResponse: true,
});
}}
>
{window.i18n('accept')}

@ -10,15 +10,19 @@ import { SessionButtonColor } from '../components/basic/SessionButton';
import { getCallMediaPermissionsSettings } from '../components/settings/SessionSettings';
import { Data } from '../data/data';
import { SettingsKey } from '../data/settings-key';
import { GroupV2Receiver } from '../receiver/groupv2/handleGroupV2Message';
import { uploadFileToFsWithOnionV4 } from '../session/apis/file_server_api/FileServerApi';
import { OpenGroupUtils } from '../session/apis/open_group_api/utils';
import { getSwarmPollingInstance } from '../session/apis/snode_api';
import { GetNetworkTime } from '../session/apis/snode_api/getNetworkTime';
import { ConvoHub } from '../session/conversations';
import { getSodiumRenderer } from '../session/crypto';
import { getDecryptedMediaUrl } from '../session/crypto/DecryptedAttachmentsManager';
import { DisappearingMessageConversationModeType } from '../session/disappearing_messages/types';
import { ed25519Str } from '../session/onions/onionPath';
import { PubKey } from '../session/types';
import { perfEnd, perfStart } from '../session/utils/Performance';
import { sleepFor } from '../session/utils/Promise';
import { fromHexToArray, toHex } from '../session/utils/String';
import { UserSync } from '../session/utils/job_runners/jobs/UserSyncJob';
import { SessionUtilContact } from '../session/utils/libsession/libsession_utils_contacts';
@ -109,21 +113,53 @@ export async function unblockConvoById(conversationId: string) {
await conversation.commit();
}
/**
* marks the conversation's approval fields, sends messageRequestResponse
*/
export const approveConvoAndSendResponse = async (conversationId: string) => {
const convoToApprove = ConvoHub.use().get(conversationId);
if (!convoToApprove) {
window?.log?.info('Conversation is already approved.');
return;
export const handleAcceptConversationRequest = async ({
convoId,
sendResponse,
}: {
convoId: string;
sendResponse: boolean;
}) => {
const convo = ConvoHub.use().get(convoId);
if (!convo) {
return null;
}
await convo.setDidApproveMe(true, false);
await convo.setIsApproved(true, false);
await convo.commit();
await convoToApprove.setIsApproved(true, false);
await convoToApprove.commit();
await convoToApprove.sendMessageRequestResponse();
if (convo.isPrivate()) {
await convo.addOutgoingApprovalMessage(Date.now());
if (sendResponse) {
await convo.sendMessageRequestResponse();
}
return null;
}
if (PubKey.is03Pubkey(convoId)) {
const found = await UserGroupsWrapperActions.getGroup(convoId);
if (!found) {
window.log.warn('cannot approve a non existing group in usergroup');
return null;
}
// this updates the wrapper and refresh the redux slice
await UserGroupsWrapperActions.setGroup({ ...found, invitePending: false });
const acceptedPromise = new Promise(resolve => {
getSwarmPollingInstance().addGroupId(convoId, async () => {
// we need to do a first poll to fetch the keys etc before we can send our invite response
// this is pretty hacky, but also an admin seeing a message from that user in the group will mark it as not pending anymore
await sleepFor(2000);
if (sendResponse) {
await GroupV2Receiver.sendInviteResponseToGroup({ groupPk: convoId });
}
window.log.info(
`handleAcceptConversationRequest: first poll for group ${ed25519Str(convoId)} happened, we should have encryption keys now`
);
return resolve(true);
});
});
await acceptedPromise;
}
return null;
};
export async function declineConversationWithoutConfirm({

@ -127,6 +127,7 @@ import {
getSubscriberCountOutsideRedux,
} from '../state/selectors/sogsRoomInfo'; // decide it it makes sense to move this to a redux slice?
import { handleAcceptConversationRequest } from '../interactions/conversationInteractions';
import { DisappearingMessages } from '../session/disappearing_messages';
import { DisappearingMessageConversationModeType } from '../session/disappearing_messages/types';
import { GroupUpdateInfoChangeMessage } from '../session/messages/outgoing/controlMessage/group_v2/to_group/GroupUpdateInfoChangeMessage';
@ -2034,7 +2035,8 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
lokiProfile: UserUtils.getOurProfile(),
};
const shouldApprove = !this.isApproved() && this.isPrivate();
const shouldApprove = !this.isApproved() && (this.isPrivate() || this.isClosedGroupV2());
const incomingMessageCount = await Data.getMessageCountByType(
this.id,
MessageDirection.incoming
@ -2048,6 +2050,10 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
}
if (shouldApprove) {
await handleAcceptConversationRequest({
convoId: this.id,
sendResponse: !message,
});
await this.setIsApproved(true);
if (hasIncomingMessages) {
// have to manually add approval for local client here as DB conditional approval check in config msg handling will prevent this from running

@ -24,7 +24,7 @@ import { PubKey } from '../../types';
import { getMessageQueue } from '../..';
import { getCallMediaPermissionsSettings } from '../../../components/settings/SessionSettings';
import { Data } from '../../../data/data';
import { approveConvoAndSendResponse } from '../../../interactions/conversationInteractions';
import { handleAcceptConversationRequest } from '../../../interactions/conversationInteractions';
import { READ_MESSAGE_STATE } from '../../../models/conversationAttributes';
import { PnServer } from '../../apis/push_notification_api';
import { GetNetworkTime } from '../../apis/snode_api/getNetworkTime';
@ -533,7 +533,7 @@ export async function USER_callRecipient(recipient: string) {
weAreCallerOnCurrentCall = true;
// initiating a call is analogous to sending a message request
await approveConvoAndSendResponse(recipient);
await handleAcceptConversationRequest({ convoId: recipient, sendResponse: false });
// Note: we do the sending of the preoffer manually as the sendTo1o1NonDurably rely on having a message saved to the db for MessageSentSuccess
// which is not the case for a pre offer message (the message only exists in memory)
@ -932,8 +932,10 @@ export async function USER_acceptIncomingCallRequest(fromSender: string) {
await buildAnswerAndSendIt(fromSender, msgIdentifier);
// consider the conversation completely approved
await callerConvo.setDidApproveMe(true);
await approveConvoAndSendResponse(fromSender);
await handleAcceptConversationRequest({
convoId: fromSender,
sendResponse: true,
});
}
export async function rejectCallAlreadyAnotherCall(fromSender: string, forcedUUID: string) {

Loading…
Cancel
Save