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