feat: add poller changes and closed group keypair gen

pull/2873/head
Audric Ackermann 2 years ago
parent 53fca2a4e9
commit 5b2580c48d

@ -103,6 +103,7 @@ export const OverlayChooseAction = () => {
<IconOnActionRow iconType="group" />
<StyledChooseActionTitle>{window.i18n('createGroup')}</StyledChooseActionTitle>
</StyledActionRow>
<StyledActionRow
onClick={openJoinCommunity}
data-testid="chooser-new-community"

@ -39,14 +39,14 @@ async function unsendMessagesForEveryone(
await Promise.all(
unsendMsgObjects.map(unsendObject =>
getMessageQueue()
.sendToPubKey(new PubKey(destinationId), unsendObject, SnodeNamespaces.UserMessages)
.sendToPubKey(new PubKey(destinationId), unsendObject, SnodeNamespaces.Default)
.catch(window?.log?.error)
)
);
await Promise.all(
unsendMsgObjects.map(unsendObject =>
getMessageQueue()
.sendSyncMessage({ namespace: SnodeNamespaces.UserMessages, message: unsendObject })
.sendSyncMessage({ namespace: SnodeNamespaces.Default, message: unsendObject })
.catch(window?.log?.error)
)
);
@ -57,7 +57,7 @@ async function unsendMessagesForEveryone(
return getMessageQueue()
.sendToGroup({
message: unsendObject,
namespace: SnodeNamespaces.ClosedGroupMessage,
namespace: SnodeNamespaces.LegacyClosedGroup,
groupPubKey: new PubKey(destinationId),
})
.catch(window?.log?.error);
@ -227,7 +227,7 @@ async function unsendMessageJustForThisUser(
await Promise.all(
unsendMsgObjects.map(unsendObject =>
getMessageQueue()
.sendSyncMessage({ namespace: SnodeNamespaces.UserMessages, message: unsendObject })
.sendSyncMessage({ namespace: SnodeNamespaces.Default, message: unsendObject })
.catch(window?.log?.error)
)
);

@ -172,16 +172,23 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
window.inboxStore?.dispatch(conversationsChanged([this.getConversationModelProps()]));
}
public idForLogging() {
if (this.isPrivate()) {
return this.id;
}
if (this.isPublic()) {
return this.id;
public idForLogging(): string {
const type = this.get('type');
switch (type) {
case ConversationTypeEnum.PRIVATE:
return this.id;
case ConversationTypeEnum.GROUPV3:
return `group(${ed25519Str(this.id)})`;
case ConversationTypeEnum.GROUP: {
if (this.isPublic()) {
return this.id;
}
return `group(${ed25519Str(this.id)})`;
}
default:
assertUnreachable(type, `idForLogging case not handled for type:"${type}"`);
}
return `group(${ed25519Str(this.id)})`;
return this.id;
}
public isMe() {
@ -205,13 +212,18 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
public isOpenGroupV2(): boolean {
return OpenGroupUtils.isOpenGroupV2(this.id);
}
public isClosedGroup(): boolean {
return Boolean(
(this.get('type') === ConversationTypeEnum.GROUP && this.id.startsWith('05')) ||
(this.get('type') === ConversationTypeEnum.GROUPV3 && this.id.startsWith('03'))
this.isClosedGroupV3()
);
}
public isClosedGroupV3(): boolean {
return Boolean(this.get('type') === ConversationTypeEnum.GROUPV3 && this.id.startsWith('03'));
}
public isPrivate() {
return isDirectConversation(this.get('type'));
}
@ -589,7 +601,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
syncTarget: this.id,
});
await getMessageQueue().sendSyncMessage({
namespace: SnodeNamespaces.UserMessages,
namespace: SnodeNamespaces.Default,
message: chatMessageMe,
});
@ -597,7 +609,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
await getMessageQueue().sendToPubKey(
destinationPubkey,
chatMessagePrivate,
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
await Reactions.handleMessageReaction({
reaction,
@ -616,7 +628,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
// we need the return await so that errors are caught in the catch {}
await getMessageQueue().sendToGroup({
message: closedGroupVisibleMessage,
namespace: SnodeNamespaces.ClosedGroupMessage,
namespace: SnodeNamespaces.LegacyClosedGroup,
});
await Reactions.handleMessageReaction({
reaction,
@ -713,7 +725,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
const messageRequestResponse = new MessageRequestResponse(messageRequestResponseParams);
const pubkeyForSending = new PubKey(this.id);
await getMessageQueue()
.sendToPubKey(pubkeyForSending, messageRequestResponse, SnodeNamespaces.UserMessages)
.sendToPubKey(pubkeyForSending, messageRequestResponse, SnodeNamespaces.Default)
.catch(window?.log?.error);
}
@ -870,11 +882,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
if (this.isPrivate()) {
const expirationTimerMessage = new ExpirationTimerUpdateMessage(expireUpdate);
const pubkey = new PubKey(this.get('id'));
await getMessageQueue().sendToPubKey(
pubkey,
expirationTimerMessage,
SnodeNamespaces.UserMessages
);
await getMessageQueue().sendToPubKey(pubkey, expirationTimerMessage, SnodeNamespaces.Default);
} else {
window?.log?.warn('TODO: Expiration update for closed groups are to be updated');
const expireUpdateForGroup = {
@ -886,7 +894,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
await getMessageQueue().sendToGroup({
message: expirationTimerMessage,
namespace: SnodeNamespaces.ClosedGroupMessage,
namespace: SnodeNamespaces.LegacyClosedGroup,
});
}
}
@ -1032,7 +1040,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
});
const device = new PubKey(this.id);
await getMessageQueue().sendToPubKey(device, receiptMessage, SnodeNamespaces.UserMessages);
await getMessageQueue().sendToPubKey(device, receiptMessage, SnodeNamespaces.Default);
}
}
@ -1757,7 +1765,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
const chatMessageMe = new VisibleMessage(chatMessageParams);
await getMessageQueue().sendSyncMessage({
namespace: SnodeNamespaces.UserMessages,
namespace: SnodeNamespaces.Default,
message: chatMessageMe,
});
return;
@ -1776,7 +1784,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
await getMessageQueue().sendToPubKey(
destinationPubkey,
groupInvitMessage,
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
return;
}
@ -1785,7 +1793,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
await getMessageQueue().sendToPubKey(
destinationPubkey,
chatMessagePrivate,
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
return;
}
@ -1800,7 +1808,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
// we need the return await so that errors are caught in the catch {}
await getMessageQueue().sendToGroup({
message: closedGroupVisibleMessage,
namespace: SnodeNamespaces.ClosedGroupMessage,
namespace: SnodeNamespaces.LegacyClosedGroup,
});
return;
}
@ -2108,7 +2116,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
const device = new PubKey(recipientId);
void getMessageQueue()
.sendToPubKey(device, typingMessage, SnodeNamespaces.UserMessages)
.sendToPubKey(device, typingMessage, SnodeNamespaces.Default)
.catch(window?.log?.error);
}

@ -839,7 +839,7 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
return getMessageQueue().sendToPubKey(
PubKey.cast(conversation.id),
chatMessage,
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
}
@ -860,7 +860,7 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
return getMessageQueue().sendToGroup({
message: closedGroupVisibleMessage,
namespace: SnodeNamespaces.ClosedGroupMessage,
namespace: SnodeNamespaces.LegacyClosedGroup,
});
} catch (e) {
await this.saveErrors(e);
@ -955,7 +955,7 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
}
const syncMessage = buildSyncMessage(this.id, dataMessage, conversation.id, sentTimestamp);
await getMessageQueue().sendSyncMessage({
namespace: SnodeNamespaces.UserMessages,
namespace: SnodeNamespaces.Default,
message: syncMessage,
});
}

@ -923,7 +923,7 @@ async function sendLatestKeyPairToUsers(
await getMessageQueue().sendToPubKey(
PubKey.cast(member),
keypairsMessage,
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
})
);

@ -32,7 +32,7 @@ export type RetrievePubkeySubRequestType = {
export type RetrieveLegacyClosedGroupSubRequestType = {
method: 'retrieve';
params: {
namespace: SnodeNamespaces.ClosedGroupMessage; // legacy closed groups retrieve are not authenticated because the clients do not have a shared key
namespace: SnodeNamespaces.LegacyClosedGroup; // legacy closed groups retrieve are not authenticated because the clients do not have a shared key
} & RetrieveAlwaysNeeded &
RetrieveMaxCountSize;
};

@ -3,10 +3,15 @@ import { assertUnreachable } from '../../../types/sqlSharedTypes';
import { PickEnum } from '../../../types/Enums';
export enum SnodeNamespaces {
/**
* The messages sent to a closed group are sent and polled from this namespace
*/
LegacyClosedGroup = -10,
/**
* This is the namespace anyone can deposit a message for us
*/
UserMessages = 0,
Default = 0,
/**
* This is the namespace used to sync our profile
@ -27,24 +32,33 @@ export enum SnodeNamespaces {
UserGroups = 5,
/**
* The messages sent to a closed group are sent and polled from this namespace
* This is the namespace used to sync the closed group details for each closed group
*/
ClosedGroupInfo = 11,
/**
* This is the namespace used to sync the members for each closed group
*/
ClosedGroupMessage = -10,
ClosedGroupMembers = 12,
/**
* This is the namespace used to sync the closed group details for each of the closed groups we are polling
* This is the namespace used to sync the keys for each closed group
*/
// ClosedGroupInfo = 1,
ClosedGroupKeys = 13,
}
export type SnodeNamespacesGroup = PickEnum<
SnodeNamespaces,
SnodeNamespaces.ClosedGroupMessage // | SnodeNamespaces.ClosedGroupInfo
| SnodeNamespaces.LegacyClosedGroup
| SnodeNamespaces.ClosedGroupInfo
| SnodeNamespaces.ClosedGroupMembers
| SnodeNamespaces.ClosedGroupKeys
| SnodeNamespaces.Default
>;
export type SnodeNamespacesUser = PickEnum<
SnodeNamespaces,
SnodeNamespaces.UserContacts | SnodeNamespaces.UserProfile | SnodeNamespaces.UserMessages
SnodeNamespaces.UserContacts | SnodeNamespaces.UserProfile | SnodeNamespaces.Default
>;
/**
@ -53,7 +67,7 @@ export type SnodeNamespacesUser = PickEnum<
// eslint-disable-next-line consistent-return
function isUserConfigNamespace(namespace: SnodeNamespaces) {
switch (namespace) {
case SnodeNamespaces.UserMessages:
case SnodeNamespaces.Default:
// user messages is not hosting config based messages
return false;
case SnodeNamespaces.UserContacts:
@ -61,8 +75,10 @@ function isUserConfigNamespace(namespace: SnodeNamespaces) {
case SnodeNamespaces.UserGroups:
case SnodeNamespaces.ConvoInfoVolatile:
return true;
// case SnodeNamespaces.ClosedGroupInfo:
case SnodeNamespaces.ClosedGroupMessage:
case SnodeNamespaces.ClosedGroupInfo:
case SnodeNamespaces.ClosedGroupKeys:
case SnodeNamespaces.ClosedGroupMembers:
case SnodeNamespaces.LegacyClosedGroup:
return false;
default:
@ -75,10 +91,34 @@ function isUserConfigNamespace(namespace: SnodeNamespaces) {
}
}
function isGroupConfigNamespace(namespace: SnodeNamespaces) {
switch (namespace) {
case SnodeNamespaces.Default:
case SnodeNamespaces.UserContacts:
case SnodeNamespaces.UserProfile:
case SnodeNamespaces.UserGroups:
case SnodeNamespaces.ConvoInfoVolatile:
case SnodeNamespaces.LegacyClosedGroup:
return false;
case SnodeNamespaces.ClosedGroupInfo:
case SnodeNamespaces.ClosedGroupKeys:
case SnodeNamespaces.ClosedGroupMembers:
return true;
default:
try {
assertUnreachable(namespace, `isGroupConfigNamespace case not handled: ${namespace}`);
} catch (e) {
window.log.warn(`isGroupConfigNamespace case not handled: ${namespace}: ${e.message}`);
return false;
}
}
}
// eslint-disable-next-line consistent-return
function namespacePriority(namespace: SnodeNamespaces): number {
switch (namespace) {
case SnodeNamespaces.UserMessages:
case SnodeNamespaces.Default:
return 10;
case SnodeNamespaces.UserContacts:
return 1;
@ -88,7 +128,10 @@ function namespacePriority(namespace: SnodeNamespaces): number {
return 1;
case SnodeNamespaces.ConvoInfoVolatile:
return 1;
case SnodeNamespaces.ClosedGroupMessage:
case SnodeNamespaces.LegacyClosedGroup:
case SnodeNamespaces.ClosedGroupInfo:
case SnodeNamespaces.ClosedGroupMembers:
case SnodeNamespaces.ClosedGroupKeys:
return 10;
default:
@ -127,5 +170,6 @@ function maxSizeMap(namespaces: Array<SnodeNamespaces>) {
export const SnodeNamespace = {
isUserConfigNamespace,
isGroupConfigNamespace,
maxSizeMap,
};

@ -34,7 +34,7 @@ async function buildRetrieveRequest(
max_size: foundMaxSize,
};
if (namespace === SnodeNamespaces.ClosedGroupMessage) {
if (namespace === SnodeNamespaces.LegacyClosedGroup) {
if (pubkey === ourPubkey || !pubkey.startsWith('05')) {
throw new Error(
'namespace -10 can only be used to retrieve messages from a legacy closed group (prefix 05)'
@ -56,7 +56,7 @@ async function buildRetrieveRequest(
// if we get here, this can only be a retrieve for our own swarm, which must be authenticated
if (
!SnodeNamespace.isUserConfigNamespace(namespace) &&
namespace !== SnodeNamespaces.UserMessages
namespace !== SnodeNamespaces.Default
) {
throw new Error(`not a legacy closed group. namespace can only be 0 and was ${namespace}`);
}

@ -10,11 +10,11 @@ import { ERROR_CODE_NO_CONNECT } from './SNodeAPI';
import * as snodePool from './snodePool';
import { ConversationModel } from '../../../models/conversation';
import { ConversationTypeEnum } from '../../../models/conversationAttributes';
import { ConfigMessageHandler } from '../../../receiver/configMessage';
import { decryptEnvelopeWithOurKey } from '../../../receiver/contentMessage';
import { EnvelopePlus } from '../../../receiver/types';
import { updateIsOnline } from '../../../state/ducks/onion';
import { ReleasedFeatures } from '../../../util/releaseFeature';
import {
GenericWrapperActions,
UserGroupsWrapperActions,
@ -167,28 +167,38 @@ export class SwarmPolling {
return;
}
// we always poll as often as possible for our pubkey
const ourPubkey = UserUtils.getOurPubKeyFromCache();
const ourPubkey = UserUtils.getOurPubKeyStrFromCache();
const userNamespaces = await this.getUserNamespacesPolled();
const directPromise = Promise.all([this.pollOnceForKey(ourPubkey, false, userNamespaces)]).then(
() => undefined
);
const directPromise = Promise.all([
this.pollOnceForKey(ourPubkey, ConversationTypeEnum.PRIVATE, userNamespaces),
]).then(() => undefined);
const now = Date.now();
const groupPromises = this.groupPolling.map(async group => {
const convoPollingTimeout = this.getPollingTimeout(group.pubkey);
const diff = now - group.lastPolledTimestamp;
const { key } = group.pubkey;
const isV3 = PubKey.isClosedGroupV3(key);
const loggingId =
getConversationController()
.get(group.pubkey.key)
?.idForLogging() || group.pubkey.key;
.get(key)
?.idForLogging() || key;
if (diff >= convoPollingTimeout) {
window?.log?.debug(
`Polling for ${loggingId}; timeout: ${convoPollingTimeout}; diff: ${diff} `
);
return this.pollOnceForKey(group.pubkey, true, [SnodeNamespaces.ClosedGroupMessage]);
if (isV3) {
return this.pollOnceForKey(key, ConversationTypeEnum.GROUPV3, [
SnodeNamespaces.Default,
SnodeNamespaces.ClosedGroupKeys,
SnodeNamespaces.ClosedGroupInfo,
SnodeNamespaces.ClosedGroupMembers,
]);
}
return this.pollOnceForKey(key, ConversationTypeEnum.GROUP, [
SnodeNamespaces.LegacyClosedGroup,
]);
}
window?.log?.debug(
`Not polling for ${loggingId}; timeout: ${convoPollingTimeout} ; diff: ${diff}`
@ -196,6 +206,7 @@ export class SwarmPolling {
return Promise.resolve();
});
try {
await Promise.all(concat([directPromise], groupPromises));
} catch (e) {
@ -210,13 +221,11 @@ export class SwarmPolling {
* Only exposed as public for testing
*/
public async pollOnceForKey(
pubkey: PubKey,
isGroup: boolean,
pubkey: string,
type: ConversationTypeEnum,
namespaces: Array<SnodeNamespaces>
) {
const polledPubkey = pubkey.key;
const swarmSnodes = await snodePool.getSwarmFor(polledPubkey);
const swarmSnodes = await snodePool.getSwarmFor(pubkey);
// Select nodes for which we already have lastHashes
const alreadyPolled = swarmSnodes.filter((n: Snode) => this.lastHashes[n.pubkey_ed25519]);
@ -230,12 +239,7 @@ export class SwarmPolling {
let resultsFromAllNamespaces: RetrieveMessagesResultsBatched | null;
try {
resultsFromAllNamespaces = await this.pollNodeForKey(
toPollFrom,
pubkey,
namespaces,
!isGroup
);
resultsFromAllNamespaces = await this.pollNodeForKey(toPollFrom, pubkey, namespaces, type);
} catch (e) {
window.log.warn(
`pollNodeForKey of ${pubkey} namespaces: ${namespaces} failed with: ${e.message}`
@ -243,58 +247,60 @@ export class SwarmPolling {
resultsFromAllNamespaces = null;
}
let allNamespacesWithoutUserConfigIfNeeded: Array<RetrieveMessageItem> = [];
const userConfigLibsession = await ReleasedFeatures.checkIsUserConfigFeatureReleased();
if (!resultsFromAllNamespaces?.length) {
// not a single message from any of the polled namespace was retrieve. nothing else to do
return;
}
const { confMessages, otherMessages } = filterMessagesPerTypeOfConvo(
type,
resultsFromAllNamespaces
);
// check if we just fetched the details from the config namespaces.
// If yes, merge them together and exclude them from the rest of the messages.
if (userConfigLibsession && resultsFromAllNamespaces) {
const userConfigMessages = resultsFromAllNamespaces
.filter(m => SnodeNamespace.isUserConfigNamespace(m.namespace))
.map(r => r.messages.messages);
// first make sure to handle the shared user config message first
allNamespacesWithoutUserConfigIfNeeded = flatten(
compact(
resultsFromAllNamespaces
.filter(m => !SnodeNamespace.isUserConfigNamespace(m.namespace))
.map(r => r.messages.messages)
)
);
const userConfigMessagesMerged = flatten(compact(userConfigMessages));
if (!isGroup && userConfigMessagesMerged.length) {
if (type === ConversationTypeEnum.PRIVATE) {
if (confMessages?.length) {
window.log.info(
`received userConfigMessages count: ${userConfigMessagesMerged.length} for key ${pubkey.key}`
`received userConfigMessagesMerged count: ${confMessages.length} for key ${pubkey}`
);
try {
await this.handleSharedConfigMessages(userConfigMessagesMerged);
await this.handleUserSharedConfigMessages(confMessages);
} catch (e) {
window.log.warn(
`handleSharedConfigMessages of ${userConfigMessagesMerged.length} failed with ${e.message}`
`handleSharedConfigMessages of ${confMessages.length} failed with ${e.message}`
);
// not rethrowing
}
}
// first make sure to handle the shared user config message first
} else {
allNamespacesWithoutUserConfigIfNeeded = flatten(
compact(resultsFromAllNamespaces?.map(m => m.messages.messages))
);
} else if (type === ConversationTypeEnum.GROUPV3) {
if (confMessages?.length) {
window.log.info(
`received GROUPV3MessagesMerged count: ${confMessages.length} for key ${pubkey}`
);
throw new Error('received GROUPV3MessagesMerged TODO');
// try {
// await this.handleUserSharedConfigMessages(confMessages);
// } catch (e) {
// window.log.warn(
// `handleSharedConfigMessages of ${confMessages.length} failed with ${e.message}`
// );
// // not rethrowing
// }
}
}
if (allNamespacesWithoutUserConfigIfNeeded.length) {
window.log.debug(
`received allNamespacesWithoutUserConfigIfNeeded: ${allNamespacesWithoutUserConfigIfNeeded.length}`
);
if (otherMessages.length) {
window.log.debug(`received otherMessages: ${otherMessages.length} for type: ${type}`);
}
// Merge results into one list of unique messages
const messages = uniqBy(allNamespacesWithoutUserConfigIfNeeded, x => x.hash);
const messages = uniqBy(otherMessages, x => x.hash);
// if all snodes returned an error (null), no need to update the lastPolledTimestamp
if (isGroup) {
if (type === ConversationTypeEnum.GROUP || type === ConversationTypeEnum.GROUPV3) {
window?.log?.debug(
`Polled for group(${ed25519Str(pubkey.key)}):, got ${messages.length} messages back.`
`Polled for group(${ed25519Str(pubkey)}):, got ${messages.length} messages back.`
);
let lastPolledTimestamp = Date.now();
if (messages.length >= 95) {
@ -315,21 +321,19 @@ export class SwarmPolling {
});
}
perfStart(`handleSeenMessages-${polledPubkey}`);
perfStart(`handleSeenMessages-${pubkey}`);
const newMessages = await this.handleSeenMessages(messages);
perfEnd(`handleSeenMessages-${polledPubkey}`, 'handleSeenMessages');
perfEnd(`handleSeenMessages-${pubkey}`, 'handleSeenMessages');
// don't handle incoming messages from group swarms when using the userconfig and the group is not one of the tracked group
const isUserConfigReleaseLive = await ReleasedFeatures.checkIsUserConfigFeatureReleased();
// don't handle incoming messages from group swarms when the group is not one of the tracked group
if (
isUserConfigReleaseLive &&
isGroup &&
polledPubkey.startsWith('05') &&
!(await UserGroupsWrapperActions.getLegacyGroup(polledPubkey)) // just check if a legacy group with that name exists
type === ConversationTypeEnum.GROUP &&
pubkey.startsWith('05') &&
!(await UserGroupsWrapperActions.getLegacyGroup(pubkey)) // just check if a legacy group with that name exists
) {
// that pubkey is not tracked in the wrapper anymore. Just discard those messages and make sure we are not polling
// TODOLATER we might need to do something like this for the new closed groups once released
getSwarmPollingInstance().removePubkey(polledPubkey);
getSwarmPollingInstance().removePubkey(pubkey);
} else {
// trigger the handling of all the other messages, not shared config related
newMessages.forEach(m => {
@ -338,12 +342,20 @@ export class SwarmPolling {
return;
}
Receiver.handleRequest(content.body, isGroup ? polledPubkey : null, content.messageHash);
Receiver.handleRequest(
content.body,
type === ConversationTypeEnum.GROUP || type === ConversationTypeEnum.GROUPV3
? pubkey
: null,
content.messageHash
);
});
}
}
private async handleSharedConfigMessages(userConfigMessagesMerged: Array<RetrieveMessageItem>) {
private async handleUserSharedConfigMessages(
userConfigMessagesMerged: Array<RetrieveMessageItem>
) {
const extractedUserConfigMessage = compact(
userConfigMessagesMerged.map((m: RetrieveMessageItem) => {
return extractWebSocketContent(m.data, m.hash);
@ -403,46 +415,45 @@ export class SwarmPolling {
// the lash hash record
private async pollNodeForKey(
node: Snode,
pubkey: PubKey,
pubkey: string,
namespaces: Array<SnodeNamespaces>,
isUs: boolean
type: ConversationTypeEnum
): Promise<RetrieveMessagesResultsBatched | null> {
const namespaceLength = namespaces.length;
if (namespaceLength <= 0) {
throw new Error(`invalid number of retrieve namespace provided: ${namespaceLength}`);
}
const snodeEdkey = node.pubkey_ed25519;
const pkStr = pubkey.key;
try {
const prevHashes = await Promise.all(
namespaces.map(namespace => this.getLastHash(snodeEdkey, pkStr, namespace))
namespaces.map(namespace => this.getLastHash(snodeEdkey, pubkey, namespace))
);
const configHashesToBump: Array<string> = [];
if (await ReleasedFeatures.checkIsUserConfigFeatureReleased()) {
// TODOLATER add the logic to take care of the closed groups too once we have a way to do it with the wrappers
if (isUs) {
for (let index = 0; index < LibSessionUtil.requiredUserVariants.length; index++) {
const variant = LibSessionUtil.requiredUserVariants[index];
try {
const toBump = await GenericWrapperActions.currentHashes(variant);
if (toBump?.length) {
configHashesToBump.push(...toBump);
}
} catch (e) {
window.log.warn(`failed to get currentHashes for user variant ${variant}`);
// TODOLATER add the logic to take care of the closed groups too once we have a way to do it with the wrappers
if (type === ConversationTypeEnum.PRIVATE) {
for (let index = 0; index < LibSessionUtil.requiredUserVariants.length; index++) {
const variant = LibSessionUtil.requiredUserVariants[index];
try {
const toBump = await GenericWrapperActions.currentHashes(variant);
if (toBump?.length) {
configHashesToBump.push(...toBump);
}
} catch (e) {
window.log.warn(`failed to get currentHashes for user variant ${variant}`);
}
window.log.debug(`configHashesToBump: ${configHashesToBump}`);
}
window.log.debug(`configHashesToBump: ${configHashesToBump}`);
} else if (type === ConversationTypeEnum.GROUPV3) {
console.error('pollNodeForKey case bump of hashes closedgroup v3 to do ');
}
let results = await SnodeAPIRetrieve.retrieveNextMessages(
node,
prevHashes,
pkStr,
pubkey,
namespaces,
UserUtils.getOurPubKeyStrFromCache(),
configHashesToBump
@ -538,16 +549,13 @@ export class SwarmPolling {
}
private async getUserNamespacesPolled() {
const isUserConfigRelease = await ReleasedFeatures.checkIsUserConfigFeatureReleased();
return isUserConfigRelease
? [
SnodeNamespaces.UserMessages,
SnodeNamespaces.UserProfile,
SnodeNamespaces.UserContacts,
SnodeNamespaces.UserGroups,
SnodeNamespaces.ConvoInfoVolatile,
]
: [SnodeNamespaces.UserMessages];
return [
SnodeNamespaces.Default,
SnodeNamespaces.UserProfile,
SnodeNamespaces.UserContacts,
SnodeNamespaces.UserGroups,
SnodeNamespaces.ConvoInfoVolatile,
];
}
private async updateLastHash({
@ -558,17 +566,16 @@ export class SwarmPolling {
pubkey,
}: {
edkey: string;
pubkey: PubKey;
pubkey: string;
namespace: number;
hash: string;
expiration: number;
}): Promise<void> {
const pkStr = pubkey.key;
const cached = await this.getLastHash(edkey, pubkey.key, namespace);
const cached = await this.getLastHash(edkey, pubkey, namespace);
if (!cached || cached !== hash) {
await Data.updateLastHash({
convoId: pkStr,
convoId: pubkey,
snode: edkey,
hash,
expiresAt: expiration,
@ -579,10 +586,10 @@ export class SwarmPolling {
if (!this.lastHashes[edkey]) {
this.lastHashes[edkey] = {};
}
if (!this.lastHashes[edkey][pkStr]) {
this.lastHashes[edkey][pkStr] = {};
if (!this.lastHashes[edkey][pubkey]) {
this.lastHashes[edkey][pubkey] = {};
}
this.lastHashes[edkey][pkStr][namespace] = hash;
this.lastHashes[edkey][pubkey][namespace] = hash;
}
private async getLastHash(nodeEdKey: string, pubkey: string, namespace: number): Promise<string> {
@ -603,3 +610,59 @@ export class SwarmPolling {
return this.lastHashes[nodeEdKey][pubkey][namespace];
}
}
function filterMessagesPerTypeOfConvo<T extends ConversationTypeEnum>(
type: T,
retrieveResults: RetrieveMessagesResultsBatched
): { confMessages: Array<RetrieveMessageItem> | null; otherMessages: Array<RetrieveMessageItem> } {
switch (type) {
case ConversationTypeEnum.PRIVATE: {
const confMessages = flatten(
compact(
retrieveResults
.filter(m => SnodeNamespace.isUserConfigNamespace(m.namespace))
.map(r => r.messages.messages)
)
);
const otherMessages = flatten(
compact(
retrieveResults
.filter(m => !SnodeNamespace.isUserConfigNamespace(m.namespace))
.map(r => r.messages.messages)
)
);
return { confMessages, otherMessages: uniqBy(otherMessages, x => x.hash) };
}
case ConversationTypeEnum.GROUP:
return {
confMessages: null,
otherMessages: flatten(compact(retrieveResults.map(m => m.messages.messages))),
};
case ConversationTypeEnum.GROUPV3: {
const confMessages = flatten(
compact(
retrieveResults
.filter(m => SnodeNamespace.isGroupConfigNamespace(m.namespace))
.map(r => r.messages.messages)
)
);
const otherMessages = flatten(
compact(
retrieveResults
.filter(m => !SnodeNamespace.isGroupConfigNamespace(m.namespace))
.map(r => r.messages.messages)
)
);
return { confMessages, otherMessages: uniqBy(otherMessages, x => x.hash) };
}
default:
return { confMessages: null, otherMessages: [] };
}
}

@ -179,6 +179,15 @@ export class ConversationController {
});
}
public async createGroupV3(id: string, privateIdentityKey: string): Promise<ConversationModel> {
if (!PubKey.isClosedGroupV3(id)) {
throw new Error('createGroupV3 invalid id given');
}
// FIXME we should save the key to the wrapper right away? or even to the DB idk
return getConversationController().getOrCreateAndWait(id, ConversationTypeEnum.GROUPV3);
}
/**
* Usually, we want to mark private contact deleted as inactive (active_at = undefined).
* That way we can still have the username and avatar for them, but they won't appear in search results etc.
@ -503,7 +512,7 @@ async function leaveClosedGroup(groupId: string, fromSyncMessage: boolean) {
// if we do not have a keypair for that group, we can't send our leave message, so just skip the message sending part
const wasSent = await getMessageQueue().sendToPubKeyNonDurably({
message: ourLeavingMessage,
namespace: SnodeNamespaces.ClosedGroupMessage,
namespace: SnodeNamespaces.LegacyClosedGroup,
pubkey: PubKey.cast(groupId),
});
// TODO our leaving message might fail to be sent for some specific reason we want to still delete the group.

@ -7,7 +7,11 @@ import { openConversationWithMessages } from '../../state/ducks/conversations';
import { updateConfirmModal } from '../../state/ducks/modalDialog';
import { getSwarmPollingInstance } from '../apis/snode_api';
import { SnodeNamespaces } from '../apis/snode_api/namespaces';
import { generateClosedGroupPublicKey, generateCurve25519KeyPairWithoutPrefix } from '../crypto';
import {
generateClosedGroupPublicKey,
generateCurve25519KeyPairWithoutPrefix,
generateGroupV3Keypair,
} from '../crypto';
import {
ClosedGroupNewMessage,
ClosedGroupNewMessageParams,
@ -17,23 +21,24 @@ import { UserUtils } from '../utils';
import { forceSyncConfigurationNowIfNeeded } from '../utils/sync/syncUtils';
import { getConversationController } from './ConversationController';
/**
* Creates a brand new closed group from user supplied details. This function generates a new identityKeyPair so cannot be used to restore a closed group.
* @param groupName the name of this closed group
* @param members the initial members of this closed group
* @param isV3 if this closed group is a v3 closed group or not (has a 03 prefix in the identity keypair)
*/
export async function createClosedGroup(groupName: string, members: Array<string>, isV3: boolean) {
const setOfMembers = new Set(members);
if (isV3) {
throw new Error('groupv3 is not supported yet');
}
const us = UserUtils.getOurPubKeyStrFromCache();
// const identityKeyPair = await generateGroupV3Keypair();
// if (!identityKeyPair) {
// throw new Error('Could not create identity keypair for new closed group v3');
// }
const identityKeyPair = await generateGroupV3Keypair();
if (!identityKeyPair) {
throw new Error('Could not create identity keypair for new closed group v3');
}
// a v3 pubkey starts with 03 and an old one starts with 05
const groupPublicKey = await generateClosedGroupPublicKey();
// const groupPublicKey = isV3 ? identityKeyPair.pubkey : await generateClosedGroupPublicKey();
const groupPublicKey = isV3 ? identityKeyPair.pubkey : await generateClosedGroupPublicKey();
// the first encryption keypair is generated the same for all versions of closed group
const encryptionKeyPair = await generateCurve25519KeyPairWithoutPrefix();
@ -42,12 +47,17 @@ export async function createClosedGroup(groupName: string, members: Array<string
}
// Create the group
const convo = await getConversationController().getOrCreateAndWait(
groupPublicKey,
isV3 ? ConversationTypeEnum.GROUPV3 : ConversationTypeEnum.GROUP
);
const convo = isV3
? await getConversationController().createGroupV3(groupPublicKey, identityKeyPair.privateKey)
: await getConversationController().getOrCreateAndWait(
groupPublicKey,
ConversationTypeEnum.GROUP
);
await convo.setIsApproved(true, false);
console.warn('store the v3 identityPriatekeypair as part of the wrapper only?');
// Ensure the current user is a member
setOfMembers.add(us);
const listOfMembers = [...setOfMembers];
@ -73,7 +83,8 @@ export async function createClosedGroup(groupName: string, members: Array<string
if (isV3) {
// we need to send a group info and encryption keys message to the batch endpoint with both seqno being 0
throw new Error('fixme');
console.error('isV3 send invite to group TODO'); // FIXME
return;
}
// Send a closed group update message to all members individually
@ -208,7 +219,7 @@ function createInvitePromises(
return getMessageQueue().sendToPubKeyNonDurably({
pubkey: PubKey.cast(m),
message,
namespace: SnodeNamespaces.UserMessages,
namespace: SnodeNamespaces.Default,
});
});
}

@ -67,7 +67,7 @@ export async function generateGroupV3Keypair() {
preprendedPubkey.set(publicKey, 1);
preprendedPubkey[0] = 3;
// console.warn(`generateGroupV3Keypair: pubkey${toHex(preprendedPubkey)}`);
console.warn(`generateGroupV3Keypair: pubkey${toHex(preprendedPubkey)}`);
return { pubkey: toHex(preprendedPubkey), privateKey: toHex(ed25519KeyPair.privateKey) };
}

@ -206,9 +206,11 @@ function buildGroupDiff(convo: ConversationModel, update: GroupInfo): GroupDiff
export async function updateOrCreateClosedGroup(details: GroupInfo) {
const { id, expireTimer } = details;
const isV3 = PubKey.isClosedGroupV3(id);
const conversation = await getConversationController().getOrCreateAndWait(
id,
ConversationTypeEnum.GROUP
isV3 ? ConversationTypeEnum.GROUPV3 : ConversationTypeEnum.GROUP
);
const updates: Pick<
@ -217,8 +219,7 @@ export async function updateOrCreateClosedGroup(details: GroupInfo) {
> = {
displayNameInProfile: details.name,
members: details.members,
// Note: legacy group to not support change of admins.
type: ConversationTypeEnum.GROUP,
type: isV3 ? ConversationTypeEnum.GROUPV3 : ConversationTypeEnum.GROUP,
active_at: details.activeAt ? details.activeAt : 0,
left: !details.activeAt,
};
@ -262,7 +263,7 @@ async function sendNewName(convo: ConversationModel, name: string, messageId: st
});
await getMessageQueue().sendToGroup({
message: nameChangeMessage,
namespace: SnodeNamespaces.ClosedGroupMessage,
namespace: SnodeNamespaces.LegacyClosedGroup,
});
}
@ -297,7 +298,7 @@ async function sendAddedMembers(
});
await getMessageQueue().sendToGroup({
message: closedGroupControlMessage,
namespace: SnodeNamespaces.ClosedGroupMessage,
namespace: SnodeNamespaces.LegacyClosedGroup,
});
// Send closed group update messages to any new members individually
@ -318,7 +319,7 @@ async function sendAddedMembers(
await getMessageQueue().sendToPubKey(
memberPubKey,
newClosedGroupUpdate,
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
});
await Promise.all(promises);
@ -356,7 +357,7 @@ export async function sendRemovedMembers(
// Send the group update, and only once sent, generate and distribute a new encryption key pair if needed
await getMessageQueue().sendToGroup({
message: mainClosedGroupControlMessage,
namespace: SnodeNamespaces.ClosedGroupMessage,
namespace: SnodeNamespaces.LegacyClosedGroup,
sentCb: async () => {
if (isCurrentUserAdmin) {
// we send the new encryption key only to members already here before the update
@ -430,7 +431,7 @@ async function generateAndSendNewEncryptionKeyPair(
// this is to be sent to the group pubkey address
await getMessageQueue().sendToGroup({
message: keypairsMessage,
namespace: SnodeNamespaces.ClosedGroupMessage,
namespace: SnodeNamespaces.LegacyClosedGroup,
sentCb: messageSentCallback,
});
}

@ -79,7 +79,7 @@ export const sendDataExtractionNotification = async (
await getMessageQueue().sendToPubKey(
pubkey,
dataExtractionNotificationMessage,
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
} catch (e) {
window.log.warn('failed to send data extraction notification', e);

@ -321,8 +321,8 @@ async function encryptMessageAndWrap(
: getConversationController()
.get(recipient.key)
?.isClosedGroup()
? SnodeNamespaces.ClosedGroupMessage
: SnodeNamespaces.UserMessages;
? SnodeNamespaces.LegacyClosedGroup
: SnodeNamespaces.Default;
return {
data64,

@ -422,7 +422,7 @@ async function createOfferAndSendIt(recipient: string) {
const negotiationOfferSendResult = await getMessageQueue().sendToPubKeyNonDurably({
pubkey: PubKey.cast(recipient),
message: offerMessage,
namespace: SnodeNamespaces.UserMessages,
namespace: SnodeNamespaces.Default,
});
if (typeof negotiationOfferSendResult === 'number') {
// window.log?.warn('setting last sent timestamp');
@ -524,7 +524,7 @@ export async function USER_callRecipient(recipient: string) {
const rawMessage = await MessageUtils.toRawMessage(
PubKey.cast(recipient),
preOfferMsg,
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
const { wrappedEnvelope } = await MessageSender.send(rawMessage);
void PnServer.notifyPnServer(wrappedEnvelope, recipient);
@ -587,7 +587,7 @@ const iceSenderDebouncer = _.debounce(async (recipient: string) => {
await getMessageQueue().sendToPubKeyNonDurably({
pubkey: PubKey.cast(recipient),
message: callIceCandicates,
namespace: SnodeNamespaces.UserMessages,
namespace: SnodeNamespaces.Default,
});
}, 2000);
@ -926,12 +926,12 @@ async function sendCallMessageAndSync(callmessage: CallMessage, user: string) {
getMessageQueue().sendToPubKeyNonDurably({
pubkey: PubKey.cast(user),
message: callmessage,
namespace: SnodeNamespaces.UserMessages,
namespace: SnodeNamespaces.Default,
}),
getMessageQueue().sendToPubKeyNonDurably({
pubkey: UserUtils.getOurPubKeyFromCache(),
message: callmessage,
namespace: SnodeNamespaces.UserMessages,
namespace: SnodeNamespaces.Default,
}),
]);
}
@ -952,7 +952,7 @@ export async function USER_hangup(fromSender: string) {
void getMessageQueue().sendToPubKeyNonDurably({
pubkey: PubKey.cast(fromSender),
message: endCallMessage,
namespace: SnodeNamespaces.UserMessages,
namespace: SnodeNamespaces.Default,
});
window.inboxStore?.dispatch(endCall());

@ -64,7 +64,7 @@ export const syncConfigurationIfNeeded = async () => {
// window?.log?.info('syncConfigurationIfNeeded with', configMessage);
await getMessageQueue().sendSyncMessage({
namespace: SnodeNamespaces.UserMessages,
namespace: SnodeNamespaces.Default,
message: configMessage,
});
} catch (e) {
@ -116,7 +116,7 @@ export const forceSyncConfigurationNowIfNeeded = async (waitForMessageSent = fal
}
: undefined;
void getMessageQueue().sendSyncMessage({
namespace: SnodeNamespaces.UserMessages,
namespace: SnodeNamespaces.Default,
message: configMessage,
sentCb: callback as any,
});

@ -112,7 +112,7 @@ describe('MessageQueue', () => {
await pendingMessageCache.add(
device,
TestUtils.generateVisibleMessage(),
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
const initialMessages = await pendingMessageCache.getForDevice(device);
@ -150,7 +150,7 @@ describe('MessageQueue', () => {
});
void pendingMessageCache
.add(device, message, SnodeNamespaces.UserMessages, waitForMessageSentEvent)
.add(device, message, SnodeNamespaces.Default, waitForMessageSentEvent)
.then(() => messageQueueStub.processPending(device));
});
@ -160,7 +160,7 @@ describe('MessageQueue', () => {
const device = TestUtils.generateFakePubKey();
const message = TestUtils.generateVisibleMessage();
void pendingMessageCache
.add(device, message, SnodeNamespaces.UserMessages)
.add(device, message, SnodeNamespaces.Default)
.then(() => messageQueueStub.processPending(device));
// The cb is only invoke is all reties fails. Here we poll until the messageSentHandlerFailed was invoked as this is what we want to do
@ -188,7 +188,7 @@ describe('MessageQueue', () => {
const stub = Sinon.stub(messageQueueStub as any, 'process').resolves();
const message = TestUtils.generateVisibleMessage();
await messageQueueStub.sendToPubKey(device, message, SnodeNamespaces.UserMessages);
await messageQueueStub.sendToPubKey(device, message, SnodeNamespaces.Default);
const args = stub.lastCall.args as [Array<PubKey>, ContentMessage];
expect(args[0]).to.be.equal(device);
@ -202,7 +202,7 @@ describe('MessageQueue', () => {
return expect(
messageQueueStub.sendToGroup({
message: chatMessage as any,
namespace: SnodeNamespaces.ClosedGroupMessage,
namespace: SnodeNamespaces.LegacyClosedGroup,
})
).to.be.rejectedWith('Invalid group message passed in sendToGroup.');
});
@ -217,7 +217,7 @@ describe('MessageQueue', () => {
const message = TestUtils.generateClosedGroupMessage();
await messageQueueStub.sendToGroup({
message,
namespace: SnodeNamespaces.ClosedGroupMessage,
namespace: SnodeNamespaces.LegacyClosedGroup,
});
expect(send.callCount).to.equal(1);

@ -62,7 +62,7 @@ describe('MessageSender', () => {
rawMessage = await MessageUtils.toRawMessage(
TestUtils.generateFakePubKey(),
TestUtils.generateVisibleMessage(),
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
});
@ -111,7 +111,7 @@ describe('MessageSender', () => {
const rawMessage = await MessageUtils.toRawMessage(
device,
visibleMessage,
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
await MessageSender.send(rawMessage, 3, 10);
@ -123,7 +123,7 @@ describe('MessageSender', () => {
// expect(args[3]).to.equal(visibleMessage.timestamp); the timestamp is overwritten on sending by the network clock offset
expect(firstArg[0].ttl).to.equal(visibleMessage.ttl());
expect(firstArg[0].pubkey).to.equal(device.key);
expect(firstArg[0].namespace).to.equal(SnodeNamespaces.UserMessages);
expect(firstArg[0].namespace).to.equal(SnodeNamespaces.Default);
});
it('should correctly build the envelope and override the timestamp', async () => {
@ -136,7 +136,7 @@ describe('MessageSender', () => {
const rawMessage = await MessageUtils.toRawMessage(
device,
visibleMessage,
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
const offset = 200000;
Sinon.stub(GetNetworkTime, 'getLatestTimestampOffset').returns(offset);
@ -192,7 +192,7 @@ describe('MessageSender', () => {
const rawMessage = await MessageUtils.toRawMessage(
device,
visibleMessage,
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
await MessageSender.send(rawMessage, 3, 10);

@ -58,13 +58,9 @@ describe('PendingMessageCache', () => {
it('can add to cache', async () => {
const device = TestUtils.generateFakePubKey();
const message = TestUtils.generateVisibleMessage();
const rawMessage = await MessageUtils.toRawMessage(
device,
message,
SnodeNamespaces.UserMessages
);
const rawMessage = await MessageUtils.toRawMessage(device, message, SnodeNamespaces.Default);
await pendingMessageCacheStub.add(device, message, SnodeNamespaces.UserMessages);
await pendingMessageCacheStub.add(device, message, SnodeNamespaces.Default);
// Verify that the message is in the cache
const finalCache = await pendingMessageCacheStub.getAllPending();
@ -81,20 +77,20 @@ describe('PendingMessageCache', () => {
await pendingMessageCacheStub.add(
device,
TestUtils.generateVisibleMessage(),
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
// We have to timeout here otherwise it's processed too fast and messages start having the same timestamp
await TestUtils.timeout(5);
await pendingMessageCacheStub.add(
device,
TestUtils.generateVisibleMessage(),
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
await TestUtils.timeout(5);
await pendingMessageCacheStub.add(
device,
TestUtils.generateVisibleMessage(),
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
// Verify that the message is in the cache
@ -106,13 +102,9 @@ describe('PendingMessageCache', () => {
it('can remove from cache', async () => {
const device = TestUtils.generateFakePubKey();
const message = TestUtils.generateVisibleMessage();
const rawMessage = await MessageUtils.toRawMessage(
device,
message,
SnodeNamespaces.UserMessages
);
const rawMessage = await MessageUtils.toRawMessage(device, message, SnodeNamespaces.Default);
await pendingMessageCacheStub.add(device, message, SnodeNamespaces.UserMessages);
await pendingMessageCacheStub.add(device, message, SnodeNamespaces.Default);
const initialCache = await pendingMessageCacheStub.getAllPending();
expect(initialCache).to.have.length(1);
@ -129,23 +121,19 @@ describe('PendingMessageCache', () => {
it('should only remove messages with different identifier and device', async () => {
const device = TestUtils.generateFakePubKey();
const message = TestUtils.generateVisibleMessage();
const rawMessage = await MessageUtils.toRawMessage(
device,
message,
SnodeNamespaces.UserMessages
);
const rawMessage = await MessageUtils.toRawMessage(device, message, SnodeNamespaces.Default);
await pendingMessageCacheStub.add(device, message, SnodeNamespaces.UserMessages);
await pendingMessageCacheStub.add(device, message, SnodeNamespaces.Default);
await TestUtils.timeout(5);
const one = await pendingMessageCacheStub.add(
device,
TestUtils.generateVisibleMessage(),
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
const two = await pendingMessageCacheStub.add(
TestUtils.generateFakePubKey(),
message,
SnodeNamespaces.UserMessages
SnodeNamespaces.Default
);
const initialCache = await pendingMessageCacheStub.getAllPending();
@ -178,7 +166,7 @@ describe('PendingMessageCache', () => {
];
for (const item of cacheItems) {
await pendingMessageCacheStub.add(item.device, item.message, SnodeNamespaces.UserMessages);
await pendingMessageCacheStub.add(item.device, item.message, SnodeNamespaces.Default);
}
const cache = await pendingMessageCacheStub.getAllPending();
@ -206,7 +194,7 @@ describe('PendingMessageCache', () => {
];
for (const item of cacheItems) {
await pendingMessageCacheStub.add(item.device, item.message, SnodeNamespaces.UserMessages);
await pendingMessageCacheStub.add(item.device, item.message, SnodeNamespaces.Default);
}
const initialCache = await pendingMessageCacheStub.getAllPending();
@ -223,11 +211,7 @@ describe('PendingMessageCache', () => {
it('can find nothing when empty', async () => {
const device = TestUtils.generateFakePubKey();
const message = TestUtils.generateVisibleMessage();
const rawMessage = await MessageUtils.toRawMessage(
device,
message,
SnodeNamespaces.UserMessages
);
const rawMessage = await MessageUtils.toRawMessage(device, message, SnodeNamespaces.Default);
const foundMessage = pendingMessageCacheStub.find(rawMessage);
expect(foundMessage, 'a message was found in empty cache').to.be.undefined;
@ -236,13 +220,9 @@ describe('PendingMessageCache', () => {
it('can find message in cache', async () => {
const device = TestUtils.generateFakePubKey();
const message = TestUtils.generateVisibleMessage();
const rawMessage = await MessageUtils.toRawMessage(
device,
message,
SnodeNamespaces.UserMessages
);
const rawMessage = await MessageUtils.toRawMessage(device, message, SnodeNamespaces.Default);
await pendingMessageCacheStub.add(device, message, SnodeNamespaces.UserMessages);
await pendingMessageCacheStub.add(device, message, SnodeNamespaces.Default);
const finalCache = await pendingMessageCacheStub.getAllPending();
expect(finalCache).to.have.length(1);
@ -269,7 +249,7 @@ describe('PendingMessageCache', () => {
];
for (const item of cacheItems) {
await pendingMessageCacheStub.add(item.device, item.message, SnodeNamespaces.UserMessages);
await pendingMessageCacheStub.add(item.device, item.message, SnodeNamespaces.Default);
}
const initialCache = await pendingMessageCacheStub.getAllPending();
@ -299,7 +279,7 @@ describe('PendingMessageCache', () => {
];
for (const item of cacheItems) {
await pendingMessageCacheStub.add(item.device, item.message, SnodeNamespaces.UserMessages);
await pendingMessageCacheStub.add(item.device, item.message, SnodeNamespaces.Default);
}
const addedMessages = await pendingMessageCacheStub.getAllPending();

@ -65,11 +65,7 @@ describe('Message Utils', () => {
const device = TestUtils.generateFakePubKey();
const message = TestUtils.generateVisibleMessage();
const rawMessage = await MessageUtils.toRawMessage(
device,
message,
SnodeNamespaces.UserMessages
);
const rawMessage = await MessageUtils.toRawMessage(device, message, SnodeNamespaces.Default);
const rawBuffer = rawMessage.plainTextBuffer;
const rawBufferJSON = JSON.stringify(rawBuffer);
@ -89,11 +85,7 @@ describe('Message Utils', () => {
const device = TestUtils.generateFakePubKey();
const message = TestUtils.generateVisibleMessage();
const rawMessage = await MessageUtils.toRawMessage(
device,
message,
SnodeNamespaces.UserMessages
);
const rawMessage = await MessageUtils.toRawMessage(device, message, SnodeNamespaces.Default);
const derivedPubKey = PubKey.from(rawMessage.device);
expect(derivedPubKey).to.not.be.eq(undefined, 'should maintain pubkey');
@ -109,22 +101,14 @@ describe('Message Utils', () => {
const chatMessage = TestUtils.generateVisibleMessage();
const message = new ClosedGroupVisibleMessage({ chatMessage, groupId });
const rawMessage = await MessageUtils.toRawMessage(
device,
message,
SnodeNamespaces.UserMessages
);
const rawMessage = await MessageUtils.toRawMessage(device, message, SnodeNamespaces.Default);
expect(rawMessage.encryption).to.equal(SignalService.Envelope.Type.CLOSED_GROUP_MESSAGE);
});
it('should set encryption to Fallback on other messages', async () => {
const device = TestUtils.generateFakePubKey();
const message = TestUtils.generateVisibleMessage();
const rawMessage = await MessageUtils.toRawMessage(
device,
message,
SnodeNamespaces.UserMessages
);
const rawMessage = await MessageUtils.toRawMessage(device, message, SnodeNamespaces.Default);
expect(rawMessage.encryption).to.equal(SignalService.Envelope.Type.SESSION_MESSAGE);
});
@ -142,7 +126,7 @@ describe('Message Utils', () => {
keypair: TestUtils.generateFakeECKeyPair(),
expireTimer: 0,
});
const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.UserMessages);
const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.Default);
expect(rawMessage.encryption).to.equal(SignalService.Envelope.Type.SESSION_MESSAGE);
});
@ -154,7 +138,7 @@ describe('Message Utils', () => {
name: 'df',
groupId: TestUtils.generateFakePubKey().key,
});
const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.UserMessages);
const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.Default);
expect(rawMessage.encryption).to.equal(SignalService.Envelope.Type.CLOSED_GROUP_MESSAGE);
});
@ -166,7 +150,7 @@ describe('Message Utils', () => {
addedMembers: [TestUtils.generateFakePubKey().key],
groupId: TestUtils.generateFakePubKey().key,
});
const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.UserMessages);
const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.Default);
expect(rawMessage.encryption).to.equal(SignalService.Envelope.Type.CLOSED_GROUP_MESSAGE);
});
@ -178,7 +162,7 @@ describe('Message Utils', () => {
removedMembers: [TestUtils.generateFakePubKey().key],
groupId: TestUtils.generateFakePubKey().key,
});
const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.UserMessages);
const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.Default);
expect(rawMessage.encryption).to.equal(SignalService.Envelope.Type.CLOSED_GROUP_MESSAGE);
});
@ -199,7 +183,7 @@ describe('Message Utils', () => {
groupId: TestUtils.generateFakePubKey().key,
encryptedKeyPairs: fakeWrappers,
});
const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.UserMessages);
const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.Default);
expect(rawMessage.encryption).to.equal(SignalService.Envelope.Type.CLOSED_GROUP_MESSAGE);
});
@ -220,7 +204,7 @@ describe('Message Utils', () => {
groupId: TestUtils.generateFakePubKey().key,
encryptedKeyPairs: fakeWrappers,
});
const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.UserMessages);
const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.Default);
expect(rawMessage.encryption).to.equal(SignalService.Envelope.Type.SESSION_MESSAGE);
});
@ -234,7 +218,7 @@ describe('Message Utils', () => {
displayName: 'displayName',
contacts: [],
});
const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.UserMessages);
const rawMessage = await MessageUtils.toRawMessage(device, msg, SnodeNamespaces.Default);
expect(rawMessage.encryption).to.equal(SignalService.Envelope.Type.SESSION_MESSAGE);
});
});

Loading…
Cancel
Save