From 10b5ff9e0d4c3f85ae2dbe9c69fee29483375e4a Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 4 Jun 2021 16:17:44 +1000 Subject: [PATCH] fix deleteAuthToken by including it on the request --- .../conversation/SessionConversation.tsx | 4 +++ ts/data/data.ts | 1 - ts/opengroup/opengroupV2/ApiAuth.ts | 7 +++-- ts/opengroup/opengroupV2/ApiUtil.ts | 1 + ts/opengroup/opengroupV2/OpenGroupAPIV2.ts | 13 ++++++--- .../opengroupV2/OpenGroupManagerV2.ts | 12 ++++++--- .../opengroupV2/OpenGroupServerPoller.ts | 25 +++++++++++------ .../conversations/ConversationController.ts | 12 ++++----- ts/session/utils/syncUtils.ts | 27 +++++++++++-------- ts/util/accountManager.ts | 7 ++++- 10 files changed, 73 insertions(+), 36 deletions(-) diff --git a/ts/components/session/conversation/SessionConversation.tsx b/ts/components/session/conversation/SessionConversation.tsx index 9b55ef9d5..61c6efcce 100644 --- a/ts/components/session/conversation/SessionConversation.tsx +++ b/ts/components/session/conversation/SessionConversation.tsx @@ -159,6 +159,10 @@ export class SessionConversation extends React.Component { div?.removeEventListener('dragleave', this.handleDragOut); div?.removeEventListener('dragover', this.handleDrag); div?.removeEventListener('drop', this.handleDrop); + if (this.publicMembersRefreshTimeout) { + global.clearInterval(this.publicMembersRefreshTimeout); + this.publicMembersRefreshTimeout = undefined; + } } if (newConversationKey !== oldConversationKey) { void this.loadInitialMessages(); diff --git a/ts/data/data.ts b/ts/data/data.ts index 7d6b39916..275926369 100644 --- a/ts/data/data.ts +++ b/ts/data/data.ts @@ -10,7 +10,6 @@ import { MessageAttributes } from '../models/messageType'; import { HexKeyPair } from '../receiver/keypairs'; import { getSodium } from '../session/crypto'; import { PubKey } from '../session/types'; -import { sleepFor } from '../session/utils/Promise'; import { fromArrayBufferToBase64, fromBase64ToArrayBuffer } from '../session/utils/String'; import { ConversationType } from '../state/ducks/conversations'; import { channels } from './channels'; diff --git a/ts/opengroup/opengroupV2/ApiAuth.ts b/ts/opengroup/opengroupV2/ApiAuth.ts index cc3744a87..77a21c774 100644 --- a/ts/opengroup/opengroupV2/ApiAuth.ts +++ b/ts/opengroup/opengroupV2/ApiAuth.ts @@ -88,16 +88,19 @@ export async function getAuthToken({ return oneAtATimeGetAuth({ roomId, serverUrl }); } +export type DeleteAuthTokenRequest = OpenGroupRequestCommonType & { token: string }; export const deleteAuthToken = async ({ serverUrl, roomId, -}: OpenGroupRequestCommonType): Promise => { + token, +}: DeleteAuthTokenRequest): Promise => { const request: OpenGroupV2Request = { method: 'DELETE', room: roomId, server: serverUrl, - isAuthRequired: false, + isAuthRequired: true, endpoint: 'auth_token', + forcedTokenToUse: token, }; try { const result = await sendApiV2Request(request); diff --git a/ts/opengroup/opengroupV2/ApiUtil.ts b/ts/opengroup/opengroupV2/ApiUtil.ts index 1f688fe0e..301741321 100644 --- a/ts/opengroup/opengroupV2/ApiUtil.ts +++ b/ts/opengroup/opengroupV2/ApiUtil.ts @@ -19,6 +19,7 @@ export type OpenGroupV2Request = FileServerV2Request & { server: string; isAuthRequired: boolean; serverPublicKey?: string; // if not provided, a db called will be made to try to get it. + forcedTokenToUse?: string; }; export type OpenGroupV2CompactPollRequest = { diff --git a/ts/opengroup/opengroupV2/OpenGroupAPIV2.ts b/ts/opengroup/opengroupV2/OpenGroupAPIV2.ts index 0f45ad126..944e8a009 100644 --- a/ts/opengroup/opengroupV2/OpenGroupAPIV2.ts +++ b/ts/opengroup/opengroupV2/OpenGroupAPIV2.ts @@ -105,10 +105,15 @@ export async function sendApiV2Request( // or the promise currently fetching a new token for that same room // or fetch from the open group a new token for that room. - const token = await getAuthToken({ - roomId: request.room, - serverUrl: request.server, - }); + if (request.forcedTokenToUse) { + window?.log?.info('sendV2Request. Forcing token to use for room:', request.room); + } + const token = + request.forcedTokenToUse || + (await getAuthToken({ + roomId: request.room, + serverUrl: request.server, + })); if (!token) { window?.log?.error('Failed to get token for open group v2'); diff --git a/ts/opengroup/opengroupV2/OpenGroupManagerV2.ts b/ts/opengroup/opengroupV2/OpenGroupManagerV2.ts index f3f247067..451f5ab77 100644 --- a/ts/opengroup/opengroupV2/OpenGroupManagerV2.ts +++ b/ts/opengroup/opengroupV2/OpenGroupManagerV2.ts @@ -14,7 +14,7 @@ import { openGroupV2GetRoomInfo } from './OpenGroupAPIV2'; import { OpenGroupServerPoller } from './OpenGroupServerPoller'; import _ from 'lodash'; -import { deleteAuthToken } from './ApiAuth'; +import { deleteAuthToken, DeleteAuthTokenRequest } from './ApiAuth'; import autoBind from 'auto-bind'; export class OpenGroupManagerV2 { @@ -87,7 +87,8 @@ export class OpenGroupManagerV2 { const groupedRoomsServerUrl = groupedRooms[0].serverUrl; const poller = this.pollers.get(groupedRoomsServerUrl); if (!poller) { - this.pollers.set(groupedRoomsServerUrl, new OpenGroupServerPoller(groupedRooms)); + const uniqGroupedRooms = _.uniqBy(groupedRooms, r => r.roomId); + this.pollers.set(groupedRoomsServerUrl, new OpenGroupServerPoller(uniqGroupedRooms)); } else { // this won't do a thing if the room is already polled for roomInfos.forEach(poller.addRoomToPoll); @@ -130,9 +131,14 @@ export class OpenGroupManagerV2 { if (!allConvos.get(roomConvoId)) { // leave the group on the remote server // this request doesn't throw - await deleteAuthToken(_.pick(infos, 'serverUrl', 'roomId')); + if (infos.token) { + await deleteAuthToken( + _.pick(infos, 'serverUrl', 'roomId', 'token') as DeleteAuthTokenRequest + ); + } // remove the roomInfos locally for this open group room await removeV2OpenGroupRoom(roomConvoId); + OpenGroupManagerV2.getInstance().removeRoomFromPolledRooms(infos); // no need to remove it from the ConversationController, the convo is already not there } } catch (e) { diff --git a/ts/opengroup/opengroupV2/OpenGroupServerPoller.ts b/ts/opengroup/opengroupV2/OpenGroupServerPoller.ts index b999b43a6..43f558027 100644 --- a/ts/opengroup/opengroupV2/OpenGroupServerPoller.ts +++ b/ts/opengroup/opengroupV2/OpenGroupServerPoller.ts @@ -385,14 +385,24 @@ const handleNewMessages = async ( convo?: ConversationModel ) => { try { - const incomingMessageIds = _.compact(newMessages.map(n => n.serverId)); - const maxNewMessageId = Math.max(...incomingMessageIds); - // TODO filter out duplicates ? const roomInfos = await getV2OpenGroupRoom(conversationId); if (!roomInfos || !roomInfos.serverUrl || !roomInfos.roomId) { throw new Error(`No room for convo ${conversationId}`); } + if (!newMessages.length) { + // if we got no new messages, just write our last update timestamp to the db + roomInfos.lastFetchTimestamp = Date.now(); + window?.log?.info( + `No new messages for ${roomInfos.roomId}... just updating our last fetched timestamp` + ); + await saveV2OpenGroupRoom(roomInfos); + return; + } + const incomingMessageIds = _.compact(newMessages.map(n => n.serverId)); + const maxNewMessageId = Math.max(...incomingMessageIds); + // TODO filter out duplicates ? + const roomDetails: OpenGroupRequestCommonType = _.pick(roomInfos, 'serverUrl', 'roomId'); // tslint:disable-next-line: prefer-for-of @@ -405,7 +415,8 @@ const handleNewMessages = async ( } } - if (roomInfos && roomInfos.lastMessageFetchedServerID !== maxNewMessageId) { + // we need to update the timestamp even if we don't have a new MaxMessageServerId + if (roomInfos) { roomInfos.lastMessageFetchedServerID = maxNewMessageId; roomInfos.lastFetchTimestamp = Date.now(); await saveV2OpenGroupRoom(roomInfos); @@ -430,10 +441,8 @@ const handleCompactPollResults = async ( await handleDeletions(res.deletions, convoId, convo); } - if (res.messages.length) { - // new messages - await handleNewMessages(res.messages, convoId, convo); - } + // new messages. call this even if we don't have new messages + await handleNewMessages(res.messages, convoId, convo); if (!convo) { window?.log?.warn('Could not find convo for compactPoll', convoId); diff --git a/ts/session/conversations/ConversationController.ts b/ts/session/conversations/ConversationController.ts index c40b4ccaf..4b56e629b 100644 --- a/ts/session/conversations/ConversationController.ts +++ b/ts/session/conversations/ConversationController.ts @@ -17,7 +17,7 @@ import { actions as conversationActions } from '../../state/ducks/conversations' import { getV2OpenGroupRoom, removeV2OpenGroupRoom } from '../../data/opengroups'; import _ from 'lodash'; import { OpenGroupManagerV2 } from '../../opengroup/opengroupV2/OpenGroupManagerV2'; -import { deleteAuthToken } from '../../opengroup/opengroupV2/ApiAuth'; +import { deleteAuthToken, DeleteAuthTokenRequest } from '../../opengroup/opengroupV2/ApiAuth'; export class ConversationController { private static instance: ConversationController | null; @@ -200,11 +200,11 @@ export class ConversationController { window?.log?.info('leaving open group v2', conversation.id); const roomInfos = await getV2OpenGroupRoom(conversation.id); if (roomInfos) { - // leave the group on the remote server - try { - await deleteAuthToken(_.pick(roomInfos, 'serverUrl', 'roomId')); - } catch (e) { - window?.log?.info('deleteAuthToken failed:', e); + if (roomInfos.token) { + // leave the group on the remote server + await deleteAuthToken( + _.pick(roomInfos, 'serverUrl', 'roomId', 'token') as DeleteAuthTokenRequest + ); } OpenGroupManagerV2.getInstance().removeRoomFromPolledRooms(roomInfos); diff --git a/ts/session/utils/syncUtils.ts b/ts/session/utils/syncUtils.ts index 3936eb984..74c8c7d80 100644 --- a/ts/session/utils/syncUtils.ts +++ b/ts/session/utils/syncUtils.ts @@ -160,18 +160,23 @@ const getValidContacts = (convos: Array) => { ); const contacts = contactsModels.map(c => { - const profileKeyForContact = c.get('profileKey') - ? fromBase64ToArray(c.get('profileKey') as string) - : undefined; - - return new ConfigurationMessageContact({ - publicKey: c.id, - displayName: c.getLokiProfile()?.displayName, - profilePictureURL: c.get('avatarPointer'), - profileKey: profileKeyForContact, - }); + try { + const profileKeyForContact = c.get('profileKey') + ? fromBase64ToArray(c.get('profileKey') as string) + : undefined; + + return new ConfigurationMessageContact({ + publicKey: c.id, + displayName: c.getLokiProfile()?.displayName, + profilePictureURL: c.get('avatarPointer'), + profileKey: profileKeyForContact, + }); + } catch (e) { + window?.log.warn('getValidContacts', e); + return null; + } }); - return contacts; + return _.compact(contacts); }; export const getCurrentConfigurationMessage = async (convos: Array) => { diff --git a/ts/util/accountManager.ts b/ts/util/accountManager.ts index adf3fc6c9..1128cf4a8 100644 --- a/ts/util/accountManager.ts +++ b/ts/util/accountManager.ts @@ -15,6 +15,7 @@ import { forceSyncConfigurationNowIfNeeded } from '../session/utils/syncUtils'; import { actions as userActions } from '../state/ducks/user'; import { mn_decode, mn_encode } from '../session/crypto/mnemonic'; import { ConversationTypeEnum } from '../models/conversation'; +import _ from 'underscore'; /** * Might throw @@ -145,7 +146,7 @@ export async function clearSessionsAndPreKeys() { ]); } -export async function deleteAccount(reason?: string) { +async function bouncyDeleteAccount(reason?: string) { const deleteEverything = async () => { window?.log?.info('configuration message sent successfully. Deleting everything'); await window.Signal.Logs.deleteAll(); @@ -176,6 +177,10 @@ export async function deleteAccount(reason?: string) { window.restart(); } +export async function deleteAccount(reason?: string) { + return _.debounce(() => bouncyDeleteAccount(reason), 200); +} + async function createAccount(identityKeyPair: any) { const sodium = await getSodium(); let password = fromArrayBufferToBase64(sodium.randombytes_buf(16));