fix: reset lasthash on promotion

pull/3281/head
Audric Ackermann 9 months ago
parent 2b26c65f5f
commit 6ae0e3aac9
No known key found for this signature in database

@ -1010,6 +1010,7 @@ export async function promoteUsersInGroup({
sentAt,
convo,
markAlreadySent: false, // the store below will mark the message as sent with dbMsgIdentifier
messageHash: null,
});
const groupMemberChange = await GroupUpdateMessageFactory.getPromotedControlMessage({
adminSecretKey: groupInWrapper.secretKey,

@ -1769,13 +1769,24 @@ function getLastHashBySnode(convoId: string, snode: string, namespace: number) {
}
function getSeenMessagesByHashList(hashes: Array<string>) {
const rows = assertGlobalInstance()
const fromSeenTableRows = assertGlobalInstance()
.prepare(
`SELECT * FROM ${SEEN_MESSAGE_TABLE} WHERE hash IN ( ${hashes.map(() => '?').join(', ')} );`
)
.all(hashes);
return map(rows, row => row.hash);
const fromMessagesTableRows = compact(
assertGlobalInstance()
.prepare(
`SELECT messageHash FROM ${MESSAGES_TABLE} WHERE messageHash IN ( ${hashes.map(() => '?').join(', ')} )`
)
.all(hashes)
);
const hashesFromSeen: Array<string> = map(fromSeenTableRows, row => row.hash);
const hashesFromMessages: Array<string> = map(fromMessagesTableRows, row => row.messageHash);
return uniq(hashesFromSeen.concat(hashesFromMessages));
}
function getExpiredMessages() {

@ -635,6 +635,7 @@ async function handleClosedGroupNameChanged(
sentAt: toNumber(envelope.timestamp),
expireUpdate,
markAlreadySent: false, // legacy groups support will be removed eventually
messageHash: null, // legacy groups
});
if (!shouldOnlyAddUpdateMessage) {
convo.set({ displayNameInProfile: newName });
@ -699,6 +700,7 @@ async function handleClosedGroupMembersAdded(
sentAt: toNumber(envelope.timestamp),
expireUpdate,
markAlreadySent: false, // legacy groups support will be removed eventually
messageHash: null, // legacy groups
});
if (!shouldOnlyAddUpdateMessage) {
@ -793,6 +795,7 @@ async function handleClosedGroupMembersRemoved(
sentAt: toNumber(envelope.timestamp),
expireUpdate,
markAlreadySent: false, // legacy groups support will be removed eventually
messageHash: null, // legacy groups
});
convo.updateLastMessage();
}
@ -932,6 +935,7 @@ async function handleClosedGroupMemberLeft(
sentAt: toNumber(envelope.timestamp),
expireUpdate,
markAlreadySent: false, // legacy groups support will be removed eventually
messageHash: null, // legacy groups
});
convo.updateLastMessage();
// if a user just left and we are the admin, we remove him right away for everyone by sending a MEMBERS_REMOVED message so no need to add him as a zombie

@ -12,7 +12,7 @@ import { getSodiumRenderer } from '../../session/crypto';
import { WithDisappearingMessageUpdate } from '../../session/disappearing_messages/types';
import { ClosedGroup } from '../../session/group/closed-group';
import { PubKey } from '../../session/types';
import { WithMessageHash } from '../../session/types/with';
import { WithMessageHash, type WithMessageHashOrNull } from '../../session/types/with';
import { UserUtils } from '../../session/utils';
import { sleepFor } from '../../session/utils/Promise';
import { ed25519Str, stringToUint8Array } from '../../session/utils/String';
@ -44,7 +44,8 @@ type GroupUpdateGeneric<T> = {
} & WithSignatureTimestamp &
WithGroupPubkey &
WithAuthor &
WithDisappearingMessageUpdate;
WithDisappearingMessageUpdate &
WithMessageHashOrNull;
type GroupUpdateDetails = {
updateMessage: SignalService.GroupUpdateMessage;
@ -226,6 +227,7 @@ async function handleGroupInfoChangeMessage({
signatureTimestamp,
author,
expireUpdate,
messageHash,
}: GroupUpdateGeneric<SignalService.GroupUpdateInfoChangeMessage>) {
const sigValid = await verifySig({
pubKey: HexString.fromHexStringNoPrefix(groupPk),
@ -252,6 +254,7 @@ async function handleGroupInfoChangeMessage({
sentAt: signatureTimestamp,
expireUpdate,
markAlreadySent: true,
messageHash,
});
break;
@ -264,6 +267,7 @@ async function handleGroupInfoChangeMessage({
sentAt: signatureTimestamp,
expireUpdate,
markAlreadySent: true,
messageHash,
});
break;
}
@ -298,6 +302,7 @@ async function handleGroupMemberChangeMessage({
signatureTimestamp,
author,
expireUpdate,
messageHash,
}: GroupUpdateGeneric<SignalService.GroupUpdateMemberChangeMessage>) {
const convo = ConvoHub.use().get(groupPk);
if (!convo) {
@ -327,6 +332,7 @@ async function handleGroupMemberChangeMessage({
sentAt: signatureTimestamp,
expireUpdate,
markAlreadySent: true,
messageHash,
};
switch (change.type) {
@ -386,6 +392,7 @@ async function handleGroupUpdateMemberLeftNotificationMessage({
signatureTimestamp,
author,
expireUpdate,
messageHash,
}: GroupUpdateGeneric<SignalService.GroupUpdateMemberLeftNotificationMessage>) {
// No need to verify sig, the author is already verified with the libsession.decrypt()
const convo = ConvoHub.use().get(groupPk);
@ -401,6 +408,7 @@ async function handleGroupUpdateMemberLeftNotificationMessage({
sentAt: signatureTimestamp,
expireUpdate,
markAlreadySent: true,
messageHash,
});
convo.set({
@ -619,6 +627,9 @@ async function handleGroupUpdatePromoteMessage({
await LibSessionUtil.saveDumpsToDb(UserUtils.getOurPubKeyStrFromCache());
if (!found.invitePending) {
// yes, we really want to refetch the whole history of messages from that group...
await ConvoHub.use().resetLastHashesForConversation(groupPk);
// This group should already be polling based on if that author is pre-approved or we've already approved that group from another device.
// Start polling from it, we will mark ourselves as admin once we get the first merge result, if needed.
getSwarmPollingInstance().addGroupId(groupPk);

@ -285,6 +285,7 @@ async function handleMessageFromPendingMember(
groupPk: convoId,
author: source,
change: { isApproved: true },
messageHash: null,
});
}

@ -619,6 +619,10 @@ export class SwarmPolling {
return { namespace, lastHash };
})
);
window.log.debug(
`namespacesAndLastHashes for ${ed25519Str(pubkey)}:`,
JSON.stringify(namespacesAndLastHashes)
);
const allow401s = type === ConversationTypeEnum.GROUPV2;
const results = await SnodeAPIRetrieve.retrieveNextMessagesNoRetries(
@ -630,6 +634,23 @@ export class SwarmPolling {
allow401s
);
const namespacesAndLastHashesAfterFetch = await Promise.all(
namespaces.map(async namespace => {
const lastHash = await this.getLastHash(snodeEdkey, pubkey, namespace);
return { namespace, lastHash };
})
);
if (
namespacesAndLastHashes.some(m => m) &&
namespacesAndLastHashesAfterFetch.every(m => !m)
) {
window.log.info(
`SwarmPolling: hashes for ${ed25519Str(pubkey)} have been reset while we were fetching new messages. discarding them....`
);
return [];
}
if (!results.length) {
return [];
}

@ -416,6 +416,7 @@ class ConvoController {
}
async resetLastHashesForConversation(groupPk: GroupPubkeyType) {
window.log.info(`resetLastHashesForConversation for ${ed25519Str(groupPk)}`);
await getSwarmPollingInstance().resetLastHashesForConversation(groupPk);
await Data.emptySeenMessageHashesForConversation(groupPk);
}

@ -34,6 +34,7 @@ import { PreConditionFailed } from '../utils/errors';
import { ConversationTypeEnum } from '../../models/types';
import { NetworkTime } from '../../util/NetworkTime';
import { MessageQueue } from '../sending';
import type { WithMessageHashOrNull } from '../types/with';
export type GroupInfo = {
id: string;
@ -128,6 +129,7 @@ async function initiateClosedGroupUpdate(
const dbMessageName = await addUpdateMessage({
diff: nameOnlyDiff,
...sharedDetails,
messageHash: null, // this is legacy groups
});
await sendNewName(convo, diff.newName, dbMessageName.id as string);
}
@ -138,6 +140,7 @@ async function initiateClosedGroupUpdate(
const dbMessageAdded = await addUpdateMessage({
diff: joiningOnlyDiff,
...sharedDetails,
messageHash: null, // this is legacy groups
});
await sendAddedMembers(convo, diff.added, dbMessageAdded.id as string, updateObj);
}
@ -148,6 +151,7 @@ async function initiateClosedGroupUpdate(
const dbMessageLeaving = await addUpdateMessage({
diff: leavingOnlyDiff,
...sharedDetails,
messageHash: null, // this is legacy groups
});
await sendRemovedMembers(convo, diff.kicked, updatedMembers, dbMessageLeaving.id as string);
}
@ -161,7 +165,8 @@ export async function addUpdateMessage({
sentAt,
expireUpdate,
markAlreadySent,
}: {
messageHash,
}: WithMessageHashOrNull & {
convo: ConversationModel;
diff: GroupDiff;
sender: string;
@ -197,6 +202,7 @@ export async function addUpdateMessage({
source: sender,
conversationId: convo.id,
type: isUs ? 'outgoing' : 'incoming',
messageHash: messageHash || undefined,
};
/**

@ -2,6 +2,7 @@ import { PubkeyType } from 'libsession_util_nodejs';
import { Snode } from '../../data/types';
export type WithMessageHash = { messageHash: string };
export type WithMessageHashOrNull = { messageHash: string | null };
export type WithTimestamp = { timestamp: number };
export type WithSignature = { signature: string };
export type WithSecretKey = { secretKey: Uint8Array };

@ -205,6 +205,7 @@ const initNewGroupInWrapper = createAsyncThunk(
sentAt,
convo,
markAlreadySent: false, // the store below will mark the message as sent with dbMsgIdentifier
messageHash: null,
});
groupMemberChange = await GroupUpdateMessageFactory.getWithoutHistoryControlMessage({
adminSecretKey: groupSecretKey,
@ -624,6 +625,7 @@ async function handleMemberAddedFromUI({
sentAt: createAtNetworkTimestamp,
expireUpdate: expireDetails,
markAlreadySent: false, // the store below will mark the message as sent with dbMsgIdentifier
messageHash: null,
};
const updateMessagesToPush: Array<GroupUpdateMemberChangeMessage> = [];
if (withHistory.length) {
@ -779,6 +781,7 @@ async function handleMemberRemovedFromUI({
: null,
},
markAlreadySent: false, // the store below will mark the message as sent using dbMsgIdentifier
messageHash: null,
});
removedControlMessage = await GroupUpdateMessageFactory.getRemovedControlMessage({
adminSecretKey: group.secretKey,
@ -864,6 +867,7 @@ async function handleNameChangeFromUI({
createAtNetworkTimestamp
),
markAlreadySent: false, // the store below will mark the message as sent with dbMsgIdentifier
messageHash: null,
});
// we want to send an update only if the change was made locally.
@ -992,6 +996,7 @@ const triggerFakeAvatarUpdate = createAsyncThunk(
sentAt: createAtNetworkTimestamp,
convo,
markAlreadySent: false, // the store below will mark the message as sent with dbMsgIdentifier
messageHash: null,
});
await msgModel.commit();
@ -1169,6 +1174,7 @@ const inviteResponseReceived = createAsyncThunk(
);
}
await GroupSync.queueNewJobIfNeeded(groupPk);
await LibSessionUtil.saveDumpsToDb(groupPk);
} catch (e) {
window.log.info('inviteResponseReceived failed with', e.message);
// only admins can do the steps above, but we don't want to throw if we are not an admin

Loading…
Cancel
Save