Lazily fetch profiles when modifying groups
This commit is contained in:
parent
712c9597c5
commit
07cc399550
2 changed files with 71 additions and 21 deletions
49
ts/groups.ts
49
ts/groups.ts
|
@ -1472,12 +1472,43 @@ export async function modifyGroupV2({
|
||||||
|
|
||||||
let refreshedCredentials = false;
|
let refreshedCredentials = false;
|
||||||
|
|
||||||
|
const profileFetchQueue = new PQueue({
|
||||||
|
concurrency: 3,
|
||||||
|
});
|
||||||
|
|
||||||
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt += 1) {
|
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt += 1) {
|
||||||
log.info(`modifyGroupV2/${logId}: Starting attempt ${attempt}`);
|
log.info(`modifyGroupV2/${logId}: Starting attempt ${attempt}`);
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await window.waitForEmptyEventQueue();
|
await window.waitForEmptyEventQueue();
|
||||||
|
|
||||||
|
// Fetch profiles for contacts that do not have credentials (or have
|
||||||
|
// expired credentials)
|
||||||
|
{
|
||||||
|
const membersMissingCredentials = usingCredentialsFrom.filter(member =>
|
||||||
|
member.hasProfileKeyCredentialExpired()
|
||||||
|
);
|
||||||
|
const logIds = membersMissingCredentials.map(member =>
|
||||||
|
member.idForLogging()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (logIds.length !== 0) {
|
||||||
|
log.info(`modifyGroupV2/${logId}: Fetching profiles for ${logIds}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const member of membersMissingCredentials) {
|
||||||
|
member.set({
|
||||||
|
profileKeyCredential: null,
|
||||||
|
profileKeyCredentialExpiration: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await profileFetchQueue.addAll(
|
||||||
|
membersMissingCredentials.map(member => () => member.getProfiles())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
log.info(`modifyGroupV2/${logId}: Queuing attempt ${attempt}`);
|
log.info(`modifyGroupV2/${logId}: Queuing attempt ${attempt}`);
|
||||||
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
@ -1557,10 +1588,12 @@ export async function modifyGroupV2({
|
||||||
const logIds = usingCredentialsFrom.map(member =>
|
const logIds = usingCredentialsFrom.map(member =>
|
||||||
member.idForLogging()
|
member.idForLogging()
|
||||||
);
|
);
|
||||||
|
if (logIds.length !== 0) {
|
||||||
log.warn(
|
log.warn(
|
||||||
`modifyGroupV2/${logId}: Profile key credentials were not ` +
|
`modifyGroupV2/${logId}: Profile key credentials were not ` +
|
||||||
`up-to-date. Updating profiles for ${logIds} and retrying`
|
`up-to-date. Updating profiles for ${logIds} and retrying`
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
for (const member of usingCredentialsFrom) {
|
for (const member of usingCredentialsFrom) {
|
||||||
member.set({
|
member.set({
|
||||||
|
@ -1569,9 +1602,6 @@ export async function modifyGroupV2({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const profileFetchQueue = new PQueue({
|
|
||||||
concurrency: 3,
|
|
||||||
});
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await profileFetchQueue.addAll(
|
await profileFetchQueue.addAll(
|
||||||
usingCredentialsFrom.map(member => () => member.getProfiles())
|
usingCredentialsFrom.map(member => () => member.getProfiles())
|
||||||
|
@ -1741,6 +1771,17 @@ export async function createGroupV2({
|
||||||
|
|
||||||
const ourACI = window.storage.user.getCheckedUuid(UUIDKind.ACI).toString();
|
const ourACI = window.storage.user.getCheckedUuid(UUIDKind.ACI).toString();
|
||||||
|
|
||||||
|
const ourConversation =
|
||||||
|
window.ConversationController.getOurConversationOrThrow();
|
||||||
|
if (ourConversation.hasProfileKeyCredentialExpired()) {
|
||||||
|
log.info(`createGroupV2/${logId}: fetching our own credentials`);
|
||||||
|
ourConversation.set({
|
||||||
|
profileKeyCredential: null,
|
||||||
|
profileKeyCredentialExpiration: null,
|
||||||
|
});
|
||||||
|
await ourConversation.getProfiles();
|
||||||
|
}
|
||||||
|
|
||||||
const membersV2: Array<GroupV2MemberType> = [
|
const membersV2: Array<GroupV2MemberType> = [
|
||||||
{
|
{
|
||||||
uuid: ourACI,
|
uuid: ourACI,
|
||||||
|
@ -1770,7 +1811,7 @@ export async function createGroupV2({
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh our local data to be sure
|
// Refresh our local data to be sure
|
||||||
if (!contact.get('profileKey') || !contact.get('profileKeyCredential')) {
|
if (contact.hasProfileKeyCredentialExpired()) {
|
||||||
await contact.getProfiles();
|
await contact.getProfiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2056,6 +2056,8 @@ export class ConversationModel extends window.Backbone
|
||||||
UUIDKind.ACI
|
UUIDKind.ACI
|
||||||
);
|
);
|
||||||
const ourPNI = window.textsecure.storage.user.getUuid(UUIDKind.PNI);
|
const ourPNI = window.textsecure.storage.user.getUuid(UUIDKind.PNI);
|
||||||
|
const ourConversation =
|
||||||
|
window.ConversationController.getOurConversationOrThrow();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isGroupV1(this.attributes) ||
|
isGroupV1(this.attributes) ||
|
||||||
|
@ -2068,7 +2070,7 @@ export class ConversationModel extends window.Backbone
|
||||||
) {
|
) {
|
||||||
await this.modifyGroupV2({
|
await this.modifyGroupV2({
|
||||||
name: 'promotePendingMember',
|
name: 'promotePendingMember',
|
||||||
usingCredentialsFrom: [],
|
usingCredentialsFrom: [ourConversation],
|
||||||
createGroupChange: () => this.promotePendingMember(UUIDKind.ACI),
|
createGroupChange: () => this.promotePendingMember(UUIDKind.ACI),
|
||||||
});
|
});
|
||||||
} else if (
|
} else if (
|
||||||
|
@ -2078,7 +2080,7 @@ export class ConversationModel extends window.Backbone
|
||||||
) {
|
) {
|
||||||
await this.modifyGroupV2({
|
await this.modifyGroupV2({
|
||||||
name: 'promotePendingMember',
|
name: 'promotePendingMember',
|
||||||
usingCredentialsFrom: [],
|
usingCredentialsFrom: [ourConversation],
|
||||||
createGroupChange: () => this.promotePendingMember(UUIDKind.PNI),
|
createGroupChange: () => this.promotePendingMember(UUIDKind.PNI),
|
||||||
});
|
});
|
||||||
} else if (isGroupV2(this.attributes) && this.isMember(ourACI)) {
|
} else if (isGroupV2(this.attributes) && this.isMember(ourACI)) {
|
||||||
|
@ -2170,18 +2172,20 @@ export class ConversationModel extends window.Backbone
|
||||||
approvalRequired: boolean;
|
approvalRequired: boolean;
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
const ourACI = window.textsecure.storage.user.getCheckedUuid();
|
const ourACI = window.textsecure.storage.user.getCheckedUuid();
|
||||||
|
const ourConversation =
|
||||||
|
window.ConversationController.getOurConversationOrThrow();
|
||||||
try {
|
try {
|
||||||
if (approvalRequired) {
|
if (approvalRequired) {
|
||||||
await this.modifyGroupV2({
|
await this.modifyGroupV2({
|
||||||
name: 'requestToJoin',
|
name: 'requestToJoin',
|
||||||
usingCredentialsFrom: [],
|
usingCredentialsFrom: [ourConversation],
|
||||||
inviteLinkPassword,
|
inviteLinkPassword,
|
||||||
createGroupChange: () => this.addPendingApprovalRequest(),
|
createGroupChange: () => this.addPendingApprovalRequest(),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
await this.modifyGroupV2({
|
await this.modifyGroupV2({
|
||||||
name: 'joinGroup',
|
name: 'joinGroup',
|
||||||
usingCredentialsFrom: [],
|
usingCredentialsFrom: [ourConversation],
|
||||||
inviteLinkPassword,
|
inviteLinkPassword,
|
||||||
createGroupChange: () => this.addMember(ourACI),
|
createGroupChange: () => this.addMember(ourACI),
|
||||||
});
|
});
|
||||||
|
@ -2284,6 +2288,8 @@ export class ConversationModel extends window.Backbone
|
||||||
|
|
||||||
const ourACI = window.textsecure.storage.user.getCheckedUuid(UUIDKind.ACI);
|
const ourACI = window.textsecure.storage.user.getCheckedUuid(UUIDKind.ACI);
|
||||||
const ourPNI = window.textsecure.storage.user.getUuid(UUIDKind.PNI);
|
const ourPNI = window.textsecure.storage.user.getUuid(UUIDKind.PNI);
|
||||||
|
const ourConversation =
|
||||||
|
window.ConversationController.getOurConversationOrThrow();
|
||||||
|
|
||||||
if (this.isMemberPending(ourACI)) {
|
if (this.isMemberPending(ourACI)) {
|
||||||
await this.modifyGroupV2({
|
await this.modifyGroupV2({
|
||||||
|
@ -2294,7 +2300,7 @@ export class ConversationModel extends window.Backbone
|
||||||
} else if (this.isMember(ourACI)) {
|
} else if (this.isMember(ourACI)) {
|
||||||
await this.modifyGroupV2({
|
await this.modifyGroupV2({
|
||||||
name: 'delete',
|
name: 'delete',
|
||||||
usingCredentialsFrom: [],
|
usingCredentialsFrom: [ourConversation],
|
||||||
createGroupChange: () => this.removeMember(ourACI),
|
createGroupChange: () => this.removeMember(ourACI),
|
||||||
});
|
});
|
||||||
// Keep PNI in pending if ACI was a member.
|
// Keep PNI in pending if ACI was a member.
|
||||||
|
@ -2418,9 +2424,7 @@ export class ConversationModel extends window.Backbone
|
||||||
});
|
});
|
||||||
await this.modifyGroupV2({
|
await this.modifyGroupV2({
|
||||||
name: 'removePendingMember',
|
name: 'removePendingMember',
|
||||||
usingCredentialsFrom: conversationIds
|
usingCredentialsFrom: [],
|
||||||
.map(id => window.ConversationController.get(id))
|
|
||||||
.filter(isNotNil),
|
|
||||||
createGroupChange: () => this.removePendingMember(uuids),
|
createGroupChange: () => this.removePendingMember(uuids),
|
||||||
extraConversationsForSend: conversationIds,
|
extraConversationsForSend: conversationIds,
|
||||||
});
|
});
|
||||||
|
@ -2444,14 +2448,14 @@ export class ConversationModel extends window.Backbone
|
||||||
if (this.isMemberRequestingToJoin(uuid)) {
|
if (this.isMemberRequestingToJoin(uuid)) {
|
||||||
await this.modifyGroupV2({
|
await this.modifyGroupV2({
|
||||||
name: 'denyPendingApprovalRequest',
|
name: 'denyPendingApprovalRequest',
|
||||||
usingCredentialsFrom: [pendingMember],
|
usingCredentialsFrom: [],
|
||||||
createGroupChange: () => this.denyPendingApprovalRequest(uuid),
|
createGroupChange: () => this.denyPendingApprovalRequest(uuid),
|
||||||
extraConversationsForSend: [conversationId],
|
extraConversationsForSend: [conversationId],
|
||||||
});
|
});
|
||||||
} else if (this.isMemberPending(uuid)) {
|
} else if (this.isMemberPending(uuid)) {
|
||||||
await this.modifyGroupV2({
|
await this.modifyGroupV2({
|
||||||
name: 'removePendingMember',
|
name: 'removePendingMember',
|
||||||
usingCredentialsFrom: [pendingMember],
|
usingCredentialsFrom: [],
|
||||||
createGroupChange: () => this.removePendingMember([uuid]),
|
createGroupChange: () => this.removePendingMember([uuid]),
|
||||||
extraConversationsForSend: [conversationId],
|
extraConversationsForSend: [conversationId],
|
||||||
});
|
});
|
||||||
|
@ -2476,14 +2480,14 @@ export class ConversationModel extends window.Backbone
|
||||||
if (this.isMemberRequestingToJoin(uuid)) {
|
if (this.isMemberRequestingToJoin(uuid)) {
|
||||||
await this.modifyGroupV2({
|
await this.modifyGroupV2({
|
||||||
name: 'denyPendingApprovalRequest',
|
name: 'denyPendingApprovalRequest',
|
||||||
usingCredentialsFrom: [pendingMember],
|
usingCredentialsFrom: [],
|
||||||
createGroupChange: () => this.denyPendingApprovalRequest(uuid),
|
createGroupChange: () => this.denyPendingApprovalRequest(uuid),
|
||||||
extraConversationsForSend: [conversationId],
|
extraConversationsForSend: [conversationId],
|
||||||
});
|
});
|
||||||
} else if (this.isMemberPending(uuid)) {
|
} else if (this.isMemberPending(uuid)) {
|
||||||
await this.modifyGroupV2({
|
await this.modifyGroupV2({
|
||||||
name: 'removePendingMember',
|
name: 'removePendingMember',
|
||||||
usingCredentialsFrom: [pendingMember],
|
usingCredentialsFrom: [],
|
||||||
createGroupChange: () => this.removePendingMember([uuid]),
|
createGroupChange: () => this.removePendingMember([uuid]),
|
||||||
extraConversationsForSend: [conversationId],
|
extraConversationsForSend: [conversationId],
|
||||||
});
|
});
|
||||||
|
@ -4783,13 +4787,18 @@ export class ConversationModel extends window.Backbone
|
||||||
}
|
}
|
||||||
|
|
||||||
hasProfileKeyCredentialExpired(): boolean {
|
hasProfileKeyCredentialExpired(): boolean {
|
||||||
|
const profileKey = this.get('profileKey');
|
||||||
|
if (!profileKey) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const profileKeyCredential = this.get('profileKeyCredential');
|
const profileKeyCredential = this.get('profileKeyCredential');
|
||||||
const profileKeyCredentialExpiration = this.get(
|
const profileKeyCredentialExpiration = this.get(
|
||||||
'profileKeyCredentialExpiration'
|
'profileKeyCredentialExpiration'
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!profileKeyCredential) {
|
if (!profileKeyCredential) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isNumber(profileKeyCredentialExpiration)) {
|
if (!isNumber(profileKeyCredentialExpiration)) {
|
||||||
|
|
Loading…
Reference in a new issue