Use the profile key from the latest group change
This commit is contained in:
parent
69c0cad14c
commit
1efc9274ab
1 changed files with 61 additions and 54 deletions
107
ts/groups.ts
107
ts/groups.ts
|
@ -24,6 +24,7 @@ import { toWebSafeBase64, fromWebSafeBase64 } from './util/webSafeBase64';
|
||||||
import { assertDev, strictAssert } from './util/assert';
|
import { assertDev, strictAssert } from './util/assert';
|
||||||
import { isMoreRecentThan } from './util/timestamp';
|
import { isMoreRecentThan } from './util/timestamp';
|
||||||
import { MINUTE, DurationInSeconds, SECOND } from './util/durations';
|
import { MINUTE, DurationInSeconds, SECOND } from './util/durations';
|
||||||
|
import { drop } from './util/drop';
|
||||||
import { dropNull } from './util/dropNull';
|
import { dropNull } from './util/dropNull';
|
||||||
import type {
|
import type {
|
||||||
ConversationAttributesType,
|
ConversationAttributesType,
|
||||||
|
@ -267,16 +268,12 @@ if (!isNumber(MAX_MESSAGE_SCHEMA)) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
type MemberType = {
|
|
||||||
profileKey: string;
|
|
||||||
aci: ServiceIdString;
|
|
||||||
};
|
|
||||||
type UpdatesResultType = {
|
type UpdatesResultType = {
|
||||||
// The array of new messages to be added into the message timeline
|
// The array of new messages to be added into the message timeline
|
||||||
groupChangeMessages: Array<GroupChangeMessageType>;
|
groupChangeMessages: Array<GroupChangeMessageType>;
|
||||||
// The set of members in the group, and we largely just pull profile keys for each,
|
// The map of members in the group, and we largely just pull profile keys for each,
|
||||||
// because the group membership is updated in newAttributes
|
// because the group membership is updated in newAttributes
|
||||||
members: Array<MemberType>;
|
newProfileKeys: Map<AciString, string>;
|
||||||
// To be merged into the conversation model
|
// To be merged into the conversation model
|
||||||
newAttributes: ConversationAttributesType;
|
newAttributes: ConversationAttributesType;
|
||||||
};
|
};
|
||||||
|
@ -2442,7 +2439,7 @@ export async function initiateMigrationToGroupV2(
|
||||||
updates: {
|
updates: {
|
||||||
newAttributes,
|
newAttributes,
|
||||||
groupChangeMessages,
|
groupChangeMessages,
|
||||||
members: [],
|
newProfileKeys: new Map(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2645,7 +2642,7 @@ export async function joinGroupV2ViaLinkAndMigrate({
|
||||||
updates: {
|
updates: {
|
||||||
newAttributes,
|
newAttributes,
|
||||||
groupChangeMessages,
|
groupChangeMessages,
|
||||||
members: [],
|
newProfileKeys: new Map(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2806,7 +2803,7 @@ export async function respondToGroupV2Migration({
|
||||||
seenStatus: SeenStatus.Unseen,
|
seenStatus: SeenStatus.Unseen,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
members: [],
|
newProfileKeys: new Map(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
@ -2828,7 +2825,7 @@ export async function respondToGroupV2Migration({
|
||||||
seenStatus: SeenStatus.Seen,
|
seenStatus: SeenStatus.Seen,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
members: [],
|
newProfileKeys: new Map(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
@ -2899,7 +2896,7 @@ export async function respondToGroupV2Migration({
|
||||||
updates: {
|
updates: {
|
||||||
newAttributes,
|
newAttributes,
|
||||||
groupChangeMessages,
|
groupChangeMessages,
|
||||||
members: profileKeysToMembers(newProfileKeys),
|
newProfileKeys: profileKeysToMap(newProfileKeys),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3035,7 +3032,7 @@ async function updateGroup(
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const logId = conversation.idForLogging();
|
const logId = conversation.idForLogging();
|
||||||
|
|
||||||
const { newAttributes, groupChangeMessages, members } = updates;
|
const { newAttributes, groupChangeMessages, newProfileKeys } = updates;
|
||||||
const ourAci = window.textsecure.storage.user.getCheckedAci();
|
const ourAci = window.textsecure.storage.user.getCheckedAci();
|
||||||
const ourPni = window.textsecure.storage.user.getPni();
|
const ourPni = window.textsecure.storage.user.getPni();
|
||||||
|
|
||||||
|
@ -3105,22 +3102,19 @@ async function updateGroup(
|
||||||
const contactsWithoutProfileKey = new Array<ConversationModel>();
|
const contactsWithoutProfileKey = new Array<ConversationModel>();
|
||||||
|
|
||||||
// Capture profile key for each member in the group, if we don't have it yet
|
// Capture profile key for each member in the group, if we don't have it yet
|
||||||
members.forEach(member => {
|
for (const [aci, profileKey] of newProfileKeys) {
|
||||||
const contact = window.ConversationController.getOrCreate(
|
const contact = window.ConversationController.getOrCreate(aci, 'private');
|
||||||
member.aci,
|
|
||||||
'private'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!isMe(contact.attributes) &&
|
!isMe(contact.attributes) &&
|
||||||
member.profileKey &&
|
profileKey &&
|
||||||
member.profileKey.length > 0 &&
|
profileKey.length > 0 &&
|
||||||
contact.get('profileKey') !== member.profileKey
|
contact.get('profileKey') !== profileKey
|
||||||
) {
|
) {
|
||||||
contactsWithoutProfileKey.push(contact);
|
contactsWithoutProfileKey.push(contact);
|
||||||
void contact.setProfileKey(member.profileKey);
|
drop(contact.setProfileKey(profileKey));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
let profileFetches: Promise<Array<void>> | undefined;
|
let profileFetches: Promise<Array<void>> | undefined;
|
||||||
if (contactsWithoutProfileKey.length !== 0) {
|
if (contactsWithoutProfileKey.length !== 0) {
|
||||||
|
@ -3469,7 +3463,7 @@ async function getGroupUpdates({
|
||||||
return {
|
return {
|
||||||
newAttributes: group,
|
newAttributes: group,
|
||||||
groupChangeMessages: [],
|
groupChangeMessages: [],
|
||||||
members: [],
|
newProfileKeys: new Map(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3563,7 +3557,7 @@ async function getGroupUpdates({
|
||||||
return {
|
return {
|
||||||
newAttributes: group,
|
newAttributes: group,
|
||||||
groupChangeMessages: [],
|
groupChangeMessages: [],
|
||||||
members: [],
|
newProfileKeys: new Map(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3637,7 +3631,7 @@ async function updateGroupViaPreJoinInfo({
|
||||||
current: newAttributes,
|
current: newAttributes,
|
||||||
dropInitialJoinMessage: false,
|
dropInitialJoinMessage: false,
|
||||||
}),
|
}),
|
||||||
members: [],
|
newProfileKeys: new Map(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3687,7 +3681,7 @@ async function updateGroupViaState({
|
||||||
current: newAttributes,
|
current: newAttributes,
|
||||||
dropInitialJoinMessage,
|
dropInitialJoinMessage,
|
||||||
}),
|
}),
|
||||||
members: profileKeysToMembers(newProfileKeys),
|
newProfileKeys: profileKeysToMap(newProfileKeys),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3721,7 +3715,7 @@ async function updateGroupViaSingleChange({
|
||||||
);
|
);
|
||||||
const {
|
const {
|
||||||
newAttributes,
|
newAttributes,
|
||||||
members,
|
newProfileKeys,
|
||||||
groupChangeMessages: catchupMessages,
|
groupChangeMessages: catchupMessages,
|
||||||
} = await updateGroupViaLogs({
|
} = await updateGroupViaLogs({
|
||||||
group: singleChangeResult.newAttributes,
|
group: singleChangeResult.newAttributes,
|
||||||
|
@ -3756,7 +3750,10 @@ async function updateGroupViaSingleChange({
|
||||||
// keep the final group attributes generated, as well as any new members.
|
// keep the final group attributes generated, as well as any new members.
|
||||||
return {
|
return {
|
||||||
groupChangeMessages,
|
groupChangeMessages,
|
||||||
members: [...singleChangeResult.members, ...members],
|
newProfileKeys: new Map([
|
||||||
|
...singleChangeResult.newProfileKeys,
|
||||||
|
...newProfileKeys,
|
||||||
|
]),
|
||||||
newAttributes,
|
newAttributes,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -3886,7 +3883,7 @@ async function generateLeftGroupChanges(
|
||||||
current: newAttributes,
|
current: newAttributes,
|
||||||
old: group,
|
old: group,
|
||||||
}),
|
}),
|
||||||
members: [],
|
newProfileKeys: new Map(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3929,7 +3926,7 @@ async function integrateGroupChanges({
|
||||||
const logId = idForLogging(group.groupId);
|
const logId = idForLogging(group.groupId);
|
||||||
let attributes = group;
|
let attributes = group;
|
||||||
const finalMessages: Array<Array<GroupChangeMessageType>> = [];
|
const finalMessages: Array<Array<GroupChangeMessageType>> = [];
|
||||||
const finalMembers: Array<Array<MemberType>> = [];
|
const finalNewProfileKeys = new Map<AciString, string>();
|
||||||
|
|
||||||
const imax = changes.length;
|
const imax = changes.length;
|
||||||
for (let i = 0; i < imax; i += 1) {
|
for (let i = 0; i < imax; i += 1) {
|
||||||
|
@ -3956,7 +3953,7 @@ async function integrateGroupChanges({
|
||||||
const {
|
const {
|
||||||
newAttributes,
|
newAttributes,
|
||||||
groupChangeMessages,
|
groupChangeMessages,
|
||||||
members,
|
newProfileKeys,
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
} = await integrateGroupChange({
|
} = await integrateGroupChange({
|
||||||
group: attributes,
|
group: attributes,
|
||||||
|
@ -3967,7 +3964,9 @@ async function integrateGroupChanges({
|
||||||
|
|
||||||
attributes = newAttributes;
|
attributes = newAttributes;
|
||||||
finalMessages.push(groupChangeMessages);
|
finalMessages.push(groupChangeMessages);
|
||||||
finalMembers.push(members);
|
for (const [aci, profileKey] of newProfileKeys) {
|
||||||
|
finalNewProfileKeys.set(aci, profileKey);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(
|
log.error(
|
||||||
`integrateGroupChanges/${logId}: Failed to apply change log, continuing to apply remaining change logs.`,
|
`integrateGroupChanges/${logId}: Failed to apply change log, continuing to apply remaining change logs.`,
|
||||||
|
@ -4000,14 +3999,14 @@ async function integrateGroupChanges({
|
||||||
return {
|
return {
|
||||||
newAttributes: attributes,
|
newAttributes: attributes,
|
||||||
groupChangeMessages,
|
groupChangeMessages,
|
||||||
members: flatten(finalMembers),
|
newProfileKeys: finalNewProfileKeys,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
newAttributes: attributes,
|
newAttributes: attributes,
|
||||||
groupChangeMessages: flatten(finalMessages),
|
groupChangeMessages: flatten(finalMessages),
|
||||||
members: flatten(finalMembers),
|
newProfileKeys: finalNewProfileKeys,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4067,7 +4066,7 @@ async function integrateGroupChange({
|
||||||
return {
|
return {
|
||||||
newAttributes: group,
|
newAttributes: group,
|
||||||
groupChangeMessages: [],
|
groupChangeMessages: [],
|
||||||
members: [],
|
newProfileKeys: new Map(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4099,7 +4098,7 @@ async function integrateGroupChange({
|
||||||
return {
|
return {
|
||||||
newAttributes: group,
|
newAttributes: group,
|
||||||
groupChangeMessages: [],
|
groupChangeMessages: [],
|
||||||
members: [],
|
newProfileKeys: new Map(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (groupChangeActions.version === group.revision) {
|
if (groupChangeActions.version === group.revision) {
|
||||||
|
@ -4115,7 +4114,7 @@ async function integrateGroupChange({
|
||||||
|
|
||||||
let attributes = group;
|
let attributes = group;
|
||||||
const aggregatedChangeMessages = [];
|
const aggregatedChangeMessages = [];
|
||||||
const aggregatedMembers = [];
|
const finalNewProfileKeys = new Map<AciString, string>();
|
||||||
|
|
||||||
const canApplyChange =
|
const canApplyChange =
|
||||||
groupChange &&
|
groupChange &&
|
||||||
|
@ -4153,7 +4152,9 @@ async function integrateGroupChange({
|
||||||
|
|
||||||
attributes = newAttributes;
|
attributes = newAttributes;
|
||||||
aggregatedChangeMessages.push(groupChangeMessages);
|
aggregatedChangeMessages.push(groupChangeMessages);
|
||||||
aggregatedMembers.push(profileKeysToMembers(newProfileKeys));
|
for (const [aci, profileKey] of profileKeysToMap(newProfileKeys)) {
|
||||||
|
finalNewProfileKeys.set(aci, profileKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the group state afterwards to verify that we didn't miss anything
|
// Apply the group state afterwards to verify that we didn't miss anything
|
||||||
|
@ -4177,8 +4178,11 @@ async function integrateGroupChange({
|
||||||
logId
|
logId
|
||||||
);
|
);
|
||||||
|
|
||||||
const { newAttributes, newProfileKeys, otherChanges } =
|
const {
|
||||||
await applyGroupState({
|
newAttributes,
|
||||||
|
newProfileKeys: newProfileKeysList,
|
||||||
|
otherChanges,
|
||||||
|
} = await applyGroupState({
|
||||||
group: attributes,
|
group: attributes,
|
||||||
groupState: decryptedGroupState,
|
groupState: decryptedGroupState,
|
||||||
sourceServiceId: isFirstFetch ? sourceServiceId : undefined,
|
sourceServiceId: isFirstFetch ? sourceServiceId : undefined,
|
||||||
|
@ -4190,12 +4194,12 @@ async function integrateGroupChange({
|
||||||
sourceServiceId: isFirstFetch ? sourceServiceId : undefined,
|
sourceServiceId: isFirstFetch ? sourceServiceId : undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const newMembers = profileKeysToMembers(newProfileKeys);
|
const newProfileKeys = profileKeysToMap(newProfileKeysList);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
canApplyChange &&
|
canApplyChange &&
|
||||||
(groupChangeMessages.length !== 0 ||
|
(groupChangeMessages.length !== 0 ||
|
||||||
newMembers.length !== 0 ||
|
newProfileKeys.size !== 0 ||
|
||||||
otherChanges)
|
otherChanges)
|
||||||
) {
|
) {
|
||||||
assertDev(
|
assertDev(
|
||||||
|
@ -4207,14 +4211,16 @@ async function integrateGroupChange({
|
||||||
`integrateGroupChange/${logId}: local state was different from ` +
|
`integrateGroupChange/${logId}: local state was different from ` +
|
||||||
'the remote final state. ' +
|
'the remote final state. ' +
|
||||||
`Got ${groupChangeMessages.length} change messages, ` +
|
`Got ${groupChangeMessages.length} change messages, ` +
|
||||||
`${newMembers.length} updated members, and ` +
|
`${newProfileKeys.size} updated members, and ` +
|
||||||
`otherChanges=${otherChanges}`
|
`otherChanges=${otherChanges}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes = newAttributes;
|
attributes = newAttributes;
|
||||||
aggregatedChangeMessages.push(groupChangeMessages);
|
aggregatedChangeMessages.push(groupChangeMessages);
|
||||||
aggregatedMembers.push(newMembers);
|
for (const [aci, profileKey] of newProfileKeys) {
|
||||||
|
finalNewProfileKeys.set(aci, profileKey);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
strictAssert(
|
strictAssert(
|
||||||
canApplyChange,
|
canApplyChange,
|
||||||
|
@ -4225,7 +4231,7 @@ async function integrateGroupChange({
|
||||||
return {
|
return {
|
||||||
newAttributes: attributes,
|
newAttributes: attributes,
|
||||||
groupChangeMessages: aggregatedChangeMessages.flat(),
|
groupChangeMessages: aggregatedChangeMessages.flat(),
|
||||||
members: aggregatedMembers.flat(),
|
newProfileKeys: finalNewProfileKeys,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4774,11 +4780,12 @@ function extractDiffs({
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function profileKeysToMembers(items: ReadonlyArray<GroupChangeMemberType>) {
|
function profileKeysToMap(items: ReadonlyArray<GroupChangeMemberType>) {
|
||||||
return items.map(item => ({
|
const map = new Map<AciString, string>();
|
||||||
profileKey: Bytes.toBase64(item.profileKey),
|
for (const { aci, profileKey } of items) {
|
||||||
aci: item.aci,
|
map.set(aci, Bytes.toBase64(profileKey));
|
||||||
}));
|
}
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
type GroupChangeMemberType = {
|
type GroupChangeMemberType = {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue