Always refetch profile key credential if expired
This commit is contained in:
parent
2f252b8e26
commit
a4cf2e0948
4 changed files with 61 additions and 37 deletions
|
@ -818,7 +818,7 @@ export async function startApp(): Promise<void> {
|
||||||
await window.Signal.Data.clearAllErrorStickerPackAttempts();
|
await window.Signal.Data.clearAllErrorStickerPackAttempts();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.isBeforeVersion(lastVersion, 'v5.50.0-alpha.1')) {
|
if (window.isBeforeVersion(lastVersion, 'v5.51.0-beta.2')) {
|
||||||
await window.storage.put('groupCredentials', []);
|
await window.storage.put('groupCredentials', []);
|
||||||
await window.Signal.Data.removeAllProfileKeyCredentials();
|
await window.Signal.Data.removeAllProfileKeyCredentials();
|
||||||
}
|
}
|
||||||
|
|
89
ts/groups.ts
89
ts/groups.ts
|
@ -60,6 +60,7 @@ import type {
|
||||||
GroupCredentialsType,
|
GroupCredentialsType,
|
||||||
GroupLogResponseType,
|
GroupLogResponseType,
|
||||||
} from './textsecure/WebAPI';
|
} from './textsecure/WebAPI';
|
||||||
|
import { HTTPError } from './textsecure/Errors';
|
||||||
import type MessageSender from './textsecure/SendMessage';
|
import type MessageSender from './textsecure/SendMessage';
|
||||||
import { CURRENT_SCHEMA_VERSION as MAX_MESSAGE_SCHEMA } from './types/Message2';
|
import { CURRENT_SCHEMA_VERSION as MAX_MESSAGE_SCHEMA } from './types/Message2';
|
||||||
import type { ConversationModel } from './models/conversations';
|
import type { ConversationModel } from './models/conversations';
|
||||||
|
@ -1491,13 +1492,6 @@ export async function modifyGroupV2({
|
||||||
log.info(`modifyGroupV2/${logId}: Fetching profiles for ${logIds}`);
|
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
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
membersMissingCredentials.map(member => member.getProfiles())
|
membersMissingCredentials.map(member => member.getProfiles())
|
||||||
|
@ -1735,19 +1729,25 @@ export async function fetchMembershipProof({
|
||||||
|
|
||||||
// Creating a group
|
// Creating a group
|
||||||
|
|
||||||
export async function createGroupV2({
|
export async function createGroupV2(
|
||||||
name,
|
options: Readonly<{
|
||||||
avatar,
|
name: string;
|
||||||
expireTimer,
|
avatar: undefined | Uint8Array;
|
||||||
conversationIds,
|
expireTimer: undefined | number;
|
||||||
avatars,
|
conversationIds: Array<string>;
|
||||||
}: Readonly<{
|
avatars?: Array<AvatarDataType>;
|
||||||
name: string;
|
refreshedCredentials?: boolean;
|
||||||
avatar: undefined | Uint8Array;
|
}>
|
||||||
expireTimer: undefined | number;
|
): Promise<ConversationModel> {
|
||||||
conversationIds: Array<string>;
|
const {
|
||||||
avatars?: Array<AvatarDataType>;
|
name,
|
||||||
}>): Promise<ConversationModel> {
|
avatar,
|
||||||
|
expireTimer,
|
||||||
|
conversationIds,
|
||||||
|
avatars,
|
||||||
|
refreshedCredentials = false,
|
||||||
|
} = options;
|
||||||
|
|
||||||
// Ensure we have the credentials we need before attempting GroupsV2 operations
|
// Ensure we have the credentials we need before attempting GroupsV2 operations
|
||||||
await maybeFetchNewCredentials();
|
await maybeFetchNewCredentials();
|
||||||
|
|
||||||
|
@ -1770,10 +1770,6 @@ export async function createGroupV2({
|
||||||
window.ConversationController.getOurConversationOrThrow();
|
window.ConversationController.getOurConversationOrThrow();
|
||||||
if (ourConversation.hasProfileKeyCredentialExpired()) {
|
if (ourConversation.hasProfileKeyCredentialExpired()) {
|
||||||
log.info(`createGroupV2/${logId}: fetching our own credentials`);
|
log.info(`createGroupV2/${logId}: fetching our own credentials`);
|
||||||
ourConversation.set({
|
|
||||||
profileKeyCredential: null,
|
|
||||||
profileKeyCredentialExpiration: null,
|
|
||||||
});
|
|
||||||
await ourConversation.getProfiles();
|
await ourConversation.getProfiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1869,12 +1865,45 @@ export async function createGroupV2({
|
||||||
...protoAndConversationAttributes,
|
...protoAndConversationAttributes,
|
||||||
});
|
});
|
||||||
|
|
||||||
await makeRequestWithTemporalRetry({
|
try {
|
||||||
logId: `createGroupV2/${logId}`,
|
await makeRequestWithTemporalRetry({
|
||||||
publicParams,
|
logId: `createGroupV2/${logId}`,
|
||||||
secretParams,
|
publicParams,
|
||||||
request: (sender, options) => sender.createGroup(groupProto, options),
|
secretParams,
|
||||||
});
|
request: (sender, requestOptions) =>
|
||||||
|
sender.createGroup(groupProto, requestOptions),
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (!(error instanceof HTTPError)) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
if (error.code !== 400 || refreshedCredentials) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
const logIds = conversationIds.map(conversationId => {
|
||||||
|
const contact = window.ConversationController.get(conversationId);
|
||||||
|
if (!contact) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
contact.set({
|
||||||
|
profileKeyCredential: null,
|
||||||
|
profileKeyCredentialExpiration: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
return contact.idForLogging();
|
||||||
|
});
|
||||||
|
|
||||||
|
log.warn(
|
||||||
|
`createGroupV2/${logId}: Profile key credentials were not ` +
|
||||||
|
`up-to-date. Updating profiles for ${logIds} and retrying`
|
||||||
|
);
|
||||||
|
|
||||||
|
return createGroupV2({
|
||||||
|
...options,
|
||||||
|
refreshedCredentials: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let avatarAttribute: ConversationAttributesType['avatar'];
|
let avatarAttribute: ConversationAttributesType['avatar'];
|
||||||
if (uploadedAvatar) {
|
if (uploadedAvatar) {
|
||||||
|
|
|
@ -196,10 +196,6 @@ function* getFilteredConversations(
|
||||||
(conversation.id === ourConversationId ||
|
(conversation.id === ourConversationId ||
|
||||||
!conversationIdsSeen.has(conversation.id))
|
!conversationIdsSeen.has(conversation.id))
|
||||||
) {
|
) {
|
||||||
conversation.set({
|
|
||||||
profileKeyCredential: null,
|
|
||||||
profileKeyCredentialExpiration: null,
|
|
||||||
});
|
|
||||||
conversationIdsSeen.add(conversation.id);
|
conversationIdsSeen.add(conversation.id);
|
||||||
yield conversation;
|
yield conversation;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -230,7 +230,6 @@ async function doGetProfile(c: ConversationModel): Promise<void> {
|
||||||
const profileKey = c.get('profileKey');
|
const profileKey = c.get('profileKey');
|
||||||
const profileKeyVersion = c.deriveProfileKeyVersion();
|
const profileKeyVersion = c.deriveProfileKeyVersion();
|
||||||
const uuid = c.getCheckedUuid('getProfile');
|
const uuid = c.getCheckedUuid('getProfile');
|
||||||
const existingProfileKeyCredential = c.get('profileKeyCredential');
|
|
||||||
const lastProfile = c.get('lastProfile');
|
const lastProfile = c.get('lastProfile');
|
||||||
|
|
||||||
let profileCredentialRequestContext:
|
let profileCredentialRequestContext:
|
||||||
|
@ -246,7 +245,7 @@ async function doGetProfile(c: ConversationModel): Promise<void> {
|
||||||
'profileKeyVersion and accessKey are derived from profileKey'
|
'profileKeyVersion and accessKey are derived from profileKey'
|
||||||
);
|
);
|
||||||
|
|
||||||
if (existingProfileKeyCredential) {
|
if (!c.hasProfileKeyCredentialExpired()) {
|
||||||
getProfileOptions = {
|
getProfileOptions = {
|
||||||
accessKey,
|
accessKey,
|
||||||
profileKeyVersion,
|
profileKeyVersion,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue