fix: make pushChangesToGroupSwarm take an extraStoreRequest
parent
9b124d384e
commit
cd122c7252
@ -0,0 +1,35 @@
|
||||
import { UserGroupsGet } from 'libsession_util_nodejs';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { ed25519Str } from '../../../utils/String';
|
||||
import { DeleteHashesFromGroupNodeSubRequest } from '../SnodeRequestTypes';
|
||||
|
||||
function makeGroupHashesToDeleteSubRequest({
|
||||
allOldHashes,
|
||||
group,
|
||||
}: {
|
||||
group: Pick<UserGroupsGet, 'secretKey' | 'pubkeyHex'>;
|
||||
allOldHashes: Set<string>;
|
||||
}) {
|
||||
const groupPk = group.pubkeyHex;
|
||||
const allOldHashesArray = [...allOldHashes];
|
||||
if (allOldHashesArray.length) {
|
||||
if (!group.secretKey || isEmpty(group.secretKey)) {
|
||||
window.log.debug(
|
||||
`makeGroupHashesToDeleteSubRequest: ${ed25519Str(groupPk)}: allOldHashesArray not empty but we do not have the secretKey`
|
||||
);
|
||||
|
||||
throw new Error(
|
||||
'makeGroupHashesToDeleteSubRequest: allOldHashesArray not empty but we do not have the secretKey'
|
||||
);
|
||||
}
|
||||
|
||||
return new DeleteHashesFromGroupNodeSubRequest({
|
||||
messagesHashes: [...allOldHashes],
|
||||
groupPk,
|
||||
secretKey: group.secretKey,
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export const DeleteGroupHashesFactory = { makeGroupHashesToDeleteSubRequest };
|
@ -0,0 +1,184 @@
|
||||
import { UserGroupsGet } from 'libsession_util_nodejs';
|
||||
import { compact, isEmpty } from 'lodash';
|
||||
import { SignalService } from '../../../../protobuf';
|
||||
import { MetaGroupWrapperActions } from '../../../../webworker/workers/browser/libsession_worker_interface';
|
||||
import { GroupUpdateInfoChangeMessage } from '../../../messages/outgoing/controlMessage/group_v2/to_group/GroupUpdateInfoChangeMessage';
|
||||
import { GroupUpdateMemberChangeMessage } from '../../../messages/outgoing/controlMessage/group_v2/to_group/GroupUpdateMemberChangeMessage';
|
||||
import { MessageSender } from '../../../sending';
|
||||
import { ed25519Str } from '../../../utils/String';
|
||||
import { PendingChangesForGroup } from '../../../utils/libsession/libsession_utils';
|
||||
import {
|
||||
StoreGroupExtraData,
|
||||
StoreGroupInfoSubRequest,
|
||||
StoreGroupKeysSubRequest,
|
||||
StoreGroupMembersSubRequest,
|
||||
StoreGroupMessageSubRequest,
|
||||
} from '../SnodeRequestTypes';
|
||||
import { SnodeNamespaces } from '../namespaces';
|
||||
|
||||
export type StoreMessageToSubRequestType =
|
||||
| GroupUpdateMemberChangeMessage
|
||||
| GroupUpdateInfoChangeMessage;
|
||||
|
||||
async function makeGroupMessageSubRequest(
|
||||
updateMessages: Array<StoreMessageToSubRequestType | null>,
|
||||
group: Pick<UserGroupsGet, 'authData' | 'secretKey'>
|
||||
) {
|
||||
const compactedMessages = compact(updateMessages);
|
||||
if (isEmpty(compactedMessages)) {
|
||||
return [];
|
||||
}
|
||||
const groupPk = compactedMessages[0].destination;
|
||||
const allForSameDestination = compactedMessages.every(m => m.destination === groupPk);
|
||||
if (!allForSameDestination) {
|
||||
throw new Error('makeGroupMessageSubRequest: not all messages are for the same destination');
|
||||
}
|
||||
|
||||
const messagesToEncrypt: Array<StoreGroupExtraData> = compactedMessages.map(updateMessage => {
|
||||
const wrapped = MessageSender.wrapContentIntoEnvelope(
|
||||
SignalService.Envelope.Type.SESSION_MESSAGE,
|
||||
undefined,
|
||||
updateMessage.createAtNetworkTimestamp, // message is signed with this timestmap
|
||||
updateMessage.plainTextBuffer()
|
||||
);
|
||||
|
||||
return {
|
||||
namespace: SnodeNamespaces.ClosedGroupMessages,
|
||||
pubkey: updateMessage.destination,
|
||||
ttl: updateMessage.ttl(),
|
||||
networkTimestamp: updateMessage.createAtNetworkTimestamp,
|
||||
data: SignalService.Envelope.encode(wrapped).finish(),
|
||||
dbMessageIdentifier: updateMessage.identifier,
|
||||
};
|
||||
});
|
||||
|
||||
const encryptedContent = messagesToEncrypt.length
|
||||
? await MetaGroupWrapperActions.encryptMessages(
|
||||
groupPk,
|
||||
messagesToEncrypt.map(m => m.data)
|
||||
)
|
||||
: [];
|
||||
if (encryptedContent.length !== messagesToEncrypt.length) {
|
||||
throw new Error(
|
||||
'makeGroupMessageSubRequest: MetaGroupWrapperActions.encryptMessages did not return the right count of items'
|
||||
);
|
||||
}
|
||||
|
||||
const updateMessagesEncrypted = messagesToEncrypt.map((requestDetails, index) => ({
|
||||
...requestDetails,
|
||||
data: encryptedContent[index],
|
||||
}));
|
||||
|
||||
const updateMessagesRequests = updateMessagesEncrypted.map(m => {
|
||||
return new StoreGroupMessageSubRequest({
|
||||
encryptedData: m.data,
|
||||
groupPk,
|
||||
ttlMs: m.ttl,
|
||||
dbMessageIdentifier: m.dbMessageIdentifier,
|
||||
...group,
|
||||
createdAtNetworkTimestamp: m.networkTimestamp,
|
||||
});
|
||||
});
|
||||
|
||||
return updateMessagesRequests;
|
||||
}
|
||||
|
||||
function makeStoreGroupKeysSubRequest({
|
||||
encryptedSupplementKeys,
|
||||
group,
|
||||
}: {
|
||||
group: Pick<UserGroupsGet, 'secretKey' | 'pubkeyHex'>;
|
||||
encryptedSupplementKeys: Array<Uint8Array>;
|
||||
}) {
|
||||
const groupPk = group.pubkeyHex;
|
||||
if (!encryptedSupplementKeys.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// supplementalKeys are already encrypted, but we still need the secretKey to sign the request
|
||||
|
||||
if (!group.secretKey || isEmpty(group.secretKey)) {
|
||||
window.log.debug(
|
||||
`pushChangesToGroupSwarmIfNeeded: ${ed25519Str(groupPk)}: keysEncryptedmessage not empty but we do not have the secretKey`
|
||||
);
|
||||
|
||||
throw new Error(
|
||||
'pushChangesToGroupSwarmIfNeeded: keysEncryptedmessage not empty but we do not have the secretKey'
|
||||
);
|
||||
}
|
||||
return encryptedSupplementKeys.map(encryptedData => {
|
||||
return new StoreGroupKeysSubRequest({
|
||||
encryptedData,
|
||||
groupPk,
|
||||
secretKey: group.secretKey,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function makeStoreGroupConfigSubRequest({
|
||||
group,
|
||||
pendingConfigData,
|
||||
}: {
|
||||
group: Pick<UserGroupsGet, 'secretKey' | 'pubkeyHex'>;
|
||||
pendingConfigData: Array<PendingChangesForGroup>;
|
||||
}) {
|
||||
if (!pendingConfigData.length) {
|
||||
return [];
|
||||
}
|
||||
const groupPk = group.pubkeyHex;
|
||||
|
||||
if (!group.secretKey || isEmpty(group.secretKey)) {
|
||||
window.log.debug(
|
||||
`pushChangesToGroupSwarmIfNeeded: ${ed25519Str(groupPk)}: pendingConfigMsgs not empty but we do not have the secretKey`
|
||||
);
|
||||
|
||||
throw new Error(
|
||||
'pushChangesToGroupSwarmIfNeeded: pendingConfigMsgs not empty but we do not have the secretKey'
|
||||
);
|
||||
}
|
||||
|
||||
const groupInfoSubRequests = compact(
|
||||
pendingConfigData.map(m =>
|
||||
m.namespace === SnodeNamespaces.ClosedGroupInfo
|
||||
? new StoreGroupInfoSubRequest({
|
||||
encryptedData: m.ciphertext,
|
||||
groupPk,
|
||||
secretKey: group.secretKey,
|
||||
})
|
||||
: null
|
||||
)
|
||||
);
|
||||
|
||||
const groupMembersSubRequests = compact(
|
||||
pendingConfigData.map(m =>
|
||||
m.namespace === SnodeNamespaces.ClosedGroupMembers
|
||||
? new StoreGroupMembersSubRequest({
|
||||
encryptedData: m.ciphertext,
|
||||
groupPk,
|
||||
secretKey: group.secretKey,
|
||||
})
|
||||
: null
|
||||
)
|
||||
);
|
||||
|
||||
const groupKeysSubRequests = compact(
|
||||
pendingConfigData.map(m =>
|
||||
m.namespace === SnodeNamespaces.ClosedGroupKeys
|
||||
? new StoreGroupKeysSubRequest({
|
||||
encryptedData: m.ciphertext,
|
||||
groupPk,
|
||||
secretKey: group.secretKey,
|
||||
})
|
||||
: null
|
||||
)
|
||||
);
|
||||
|
||||
// we want to store first the keys (as the info and members might already be encrypted with them)
|
||||
return [...groupKeysSubRequests, ...groupInfoSubRequests, ...groupMembersSubRequests];
|
||||
}
|
||||
|
||||
export const StoreGroupRequestFactory = {
|
||||
makeGroupMessageSubRequest,
|
||||
makeStoreGroupConfigSubRequest,
|
||||
makeStoreGroupKeysSubRequest,
|
||||
};
|
Loading…
Reference in New Issue