Refresh PNI on startup
This commit is contained in:
parent
a4cf2e0948
commit
5c2016ec40
7 changed files with 90 additions and 75 deletions
|
@ -146,7 +146,7 @@ import { showToast } from './util/showToast';
|
|||
import { startInteractionMode } from './windows/startInteractionMode';
|
||||
import type { MainWindowStatsType } from './windows/context';
|
||||
import { deliveryReceiptsJobQueue } from './jobs/deliveryReceiptsJobQueue';
|
||||
import { updateOurUsername } from './util/updateOurUsername';
|
||||
import { updateOurUsernameAndPni } from './util/updateOurUsernameAndPni';
|
||||
import { ReactionSource } from './reactions/ReactionSource';
|
||||
import { singleProtoJobQueue } from './jobs/singleProtoJobQueue';
|
||||
import { getInitialState } from './state/getInitialState';
|
||||
|
@ -2213,18 +2213,6 @@ export async function startApp(): Promise<void> {
|
|||
return unlinkAndDisconnect(RemoveAllConfiguration.Full);
|
||||
}
|
||||
|
||||
if (!window.textsecure.storage.user.getUuid(UUIDKind.PNI)) {
|
||||
log.info('PNI not captured during registration, fetching');
|
||||
const { pni } = await server.whoami();
|
||||
if (!pni) {
|
||||
log.error('No PNI found, unlinking');
|
||||
return unlinkAndDisconnect(RemoveAllConfiguration.Soft);
|
||||
}
|
||||
|
||||
log.info('Setting PNI to', pni);
|
||||
await window.textsecure.storage.user.setPni(pni);
|
||||
}
|
||||
|
||||
if (connectCount === 1) {
|
||||
try {
|
||||
// Note: we always have to register our capabilities all at once, so we do this
|
||||
|
@ -2239,7 +2227,7 @@ export async function startApp(): Promise<void> {
|
|||
changeNumber: true,
|
||||
stories: true,
|
||||
}),
|
||||
updateOurUsername(),
|
||||
updateOurUsernameAndPni(),
|
||||
]);
|
||||
} catch (error) {
|
||||
log.error(
|
||||
|
@ -2249,6 +2237,11 @@ export async function startApp(): Promise<void> {
|
|||
}
|
||||
}
|
||||
|
||||
if (!window.textsecure.storage.user.getUuid(UUIDKind.PNI)) {
|
||||
log.error('PNI not captured during registration, unlinking softly');
|
||||
return unlinkAndDisconnect(RemoveAllConfiguration.Soft);
|
||||
}
|
||||
|
||||
if (firstRun === true && deviceId !== 1) {
|
||||
const hasThemeSetting = Boolean(window.storage.get('theme-setting'));
|
||||
if (
|
||||
|
@ -3625,7 +3618,10 @@ export async function startApp(): Promise<void> {
|
|||
case FETCH_LATEST_ENUM.LOCAL_PROFILE: {
|
||||
const ourUuid = window.textsecure.storage.user.getUuid()?.toString();
|
||||
const ourE164 = window.textsecure.storage.user.getNumber();
|
||||
await Promise.all([getProfile(ourUuid, ourE164), updateOurUsername()]);
|
||||
await Promise.all([
|
||||
getProfile(ourUuid, ourE164),
|
||||
updateOurUsernameAndPni(),
|
||||
]);
|
||||
break;
|
||||
}
|
||||
case FETCH_LATEST_ENUM.STORAGE_MANIFEST:
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import { singleProtoJobQueue } from '../jobs/singleProtoJobQueue';
|
||||
import dataInterface from '../sql/Client';
|
||||
import { updateOurUsername } from '../util/updateOurUsername';
|
||||
import { updateOurUsernameAndPni } from '../util/updateOurUsernameAndPni';
|
||||
import * as Errors from '../types/errors';
|
||||
import * as log from '../logging/log';
|
||||
import MessageSender from '../textsecure/SendMessage';
|
||||
|
@ -21,7 +21,7 @@ export async function writeUsername({
|
|||
}
|
||||
|
||||
const me = window.ConversationController.getOurConversationOrThrow();
|
||||
await updateOurUsername();
|
||||
await updateOurUsernameAndPni();
|
||||
|
||||
if (me.get('username') !== previousUsername) {
|
||||
throw new Error('Username has changed on another device');
|
||||
|
|
|
@ -33,6 +33,7 @@ import { ourProfileKeyService } from '../services/ourProfileKey';
|
|||
import { assert, strictAssert } from '../util/assert';
|
||||
import { getRegionCodeForNumber } from '../util/libphonenumberUtil';
|
||||
import { getProvisioningUrl } from '../util/getProvisioningUrl';
|
||||
import { isNotNil } from '../util/isNotNil';
|
||||
import { SignalService as Proto } from '../protobuf';
|
||||
import * as log from '../logging/log';
|
||||
|
||||
|
@ -43,19 +44,6 @@ const PREKEY_ROTATION_AGE = DAY * 1.5;
|
|||
const PROFILE_KEY_LENGTH = 32;
|
||||
const SIGNED_KEY_GEN_BATCH_SIZE = 100;
|
||||
|
||||
function getIdentifier(id: string | undefined) {
|
||||
if (!id || !id.length) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const parts = id.split('.');
|
||||
if (!parts.length) {
|
||||
return id;
|
||||
}
|
||||
|
||||
return parts[0];
|
||||
}
|
||||
|
||||
export type GeneratedKeysType = {
|
||||
preKeys: Array<{
|
||||
keyId: number;
|
||||
|
@ -529,8 +517,9 @@ export default class AccountManager extends EventTarget {
|
|||
password = password.substring(0, password.length - 2);
|
||||
const registrationId = generateRegistrationId();
|
||||
|
||||
const previousNumber = getIdentifier(storage.get('number_id'));
|
||||
const previousUuid = getIdentifier(storage.get('uuid_id'));
|
||||
const previousNumber = storage.user.getNumber();
|
||||
const previousACI = storage.user.getUuid(UUIDKind.ACI)?.toString();
|
||||
const previousPNI = storage.user.getUuid(UUIDKind.PNI)?.toString();
|
||||
|
||||
let encryptedDeviceName;
|
||||
if (deviceName) {
|
||||
|
@ -556,11 +545,11 @@ export default class AccountManager extends EventTarget {
|
|||
const ourUuid = UUID.cast(response.uuid);
|
||||
const ourPni = UUID.cast(response.pni);
|
||||
|
||||
const uuidChanged = previousUuid && ourUuid && previousUuid !== ourUuid;
|
||||
const uuidChanged = previousACI && ourUuid && previousACI !== ourUuid;
|
||||
|
||||
// We only consider the number changed if we didn't have a UUID before
|
||||
const numberChanged =
|
||||
!previousUuid && previousNumber && previousNumber !== number;
|
||||
!previousACI && previousNumber && previousNumber !== number;
|
||||
|
||||
if (uuidChanged || numberChanged) {
|
||||
if (uuidChanged) {
|
||||
|
@ -592,15 +581,17 @@ export default class AccountManager extends EventTarget {
|
|||
|
||||
await senderCertificateService.clear();
|
||||
|
||||
if (previousUuid) {
|
||||
const previousUuids = [previousACI, previousPNI].filter(isNotNil);
|
||||
|
||||
if (previousUuids.length > 0) {
|
||||
await Promise.all([
|
||||
storage.put(
|
||||
'identityKeyMap',
|
||||
omit(storage.get('identityKeyMap') || {}, previousUuid)
|
||||
omit(storage.get('identityKeyMap') || {}, previousUuids)
|
||||
),
|
||||
storage.put(
|
||||
'registrationIdMap',
|
||||
omit(storage.get('registrationIdMap') || {}, previousUuid)
|
||||
omit(storage.get('registrationIdMap') || {}, previousUuids)
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
@ -849,4 +840,31 @@ export default class AccountManager extends EventTarget {
|
|||
log.info('registration done');
|
||||
this.dispatchEvent(new Event('registration'));
|
||||
}
|
||||
|
||||
async setPni(pni: string): Promise<void> {
|
||||
const { storage } = window.textsecure;
|
||||
|
||||
const oldPni = storage.user.getUuid(UUIDKind.PNI)?.toString();
|
||||
if (oldPni === pni) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldPni) {
|
||||
await Promise.all([
|
||||
storage.put(
|
||||
'identityKeyMap',
|
||||
omit(storage.get('identityKeyMap') || {}, oldPni)
|
||||
),
|
||||
storage.put(
|
||||
'registrationIdMap',
|
||||
omit(storage.get('registrationIdMap') || {}, oldPni)
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
log.info(`AccountManager.setPni: updating pni from ${oldPni} to ${pni}`);
|
||||
await storage.user.setPni(pni);
|
||||
|
||||
await storage.protocol.hydrateCaches();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2407,7 +2407,4 @@ export default class MessageSender {
|
|||
async deleteUsername(): Promise<ReturnType<WebAPIType['deleteUsername']>> {
|
||||
return this.server.deleteUsername();
|
||||
}
|
||||
async whoami(): Promise<ReturnType<WebAPIType['whoami']>> {
|
||||
return this.server.whoami();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ import type { SocketStatus } from '../types/SocketStatus';
|
|||
import { toLogFormat } from '../types/errors';
|
||||
import { isPackIdValid, redactPackId } from '../types/Stickers';
|
||||
import type { UUID, UUIDStringType } from '../types/UUID';
|
||||
import { isValidUuid, UUIDKind } from '../types/UUID';
|
||||
import { UUIDKind } from '../types/UUID';
|
||||
import * as Bytes from '../Bytes';
|
||||
import { getRandomValue } from '../Crypto';
|
||||
import * as linkPreviewFetch from '../linkPreviews/linkPreviewFetch';
|
||||
|
@ -750,12 +750,15 @@ export type MakeProxiedRequestResultType =
|
|||
totalSize: number;
|
||||
};
|
||||
|
||||
export type WhoamiResultType = Readonly<{
|
||||
uuid?: UUIDStringType;
|
||||
pni?: UUIDStringType;
|
||||
number?: string;
|
||||
username?: string;
|
||||
}>;
|
||||
const whoamiResultZod = z
|
||||
.object({
|
||||
uuid: z.string(),
|
||||
pni: z.string(),
|
||||
number: z.string(),
|
||||
username: z.string().or(z.null()).optional(),
|
||||
})
|
||||
.passthrough();
|
||||
export type WhoamiResultType = z.infer<typeof whoamiResultZod>;
|
||||
|
||||
export type ConfirmCodeResultType = Readonly<{
|
||||
uuid: UUIDStringType;
|
||||
|
@ -1396,18 +1399,7 @@ export function initialize({
|
|||
responseType: 'json',
|
||||
});
|
||||
|
||||
if (!isRecord(response)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
uuid: isValidUuid(response.uuid) ? response.uuid : undefined,
|
||||
pni: isValidUuid(response.pni) ? response.pni : undefined,
|
||||
number:
|
||||
typeof response.number === 'string' ? response.number : undefined,
|
||||
username:
|
||||
typeof response.username === 'string' ? response.username : undefined,
|
||||
};
|
||||
return whoamiResultZod.parse(response);
|
||||
}
|
||||
|
||||
async function sendChallengeResponse(challengeResponse: ChallengeType) {
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
export async function updateOurUsername(): Promise<void> {
|
||||
if (!window.textsecure.messaging) {
|
||||
throw new Error(
|
||||
'updateOurUsername: window.textsecure.messaging not available'
|
||||
);
|
||||
}
|
||||
|
||||
const me = window.ConversationController.getOurConversationOrThrow();
|
||||
const { username } = await window.textsecure.messaging.whoami();
|
||||
|
||||
me.set({ username });
|
||||
window.Signal.Data.updateConversation(me.attributes);
|
||||
}
|
28
ts/util/updateOurUsernameAndPni.ts
Normal file
28
ts/util/updateOurUsernameAndPni.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2021-2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { strictAssert } from './assert';
|
||||
import { dropNull } from './dropNull';
|
||||
|
||||
export async function updateOurUsernameAndPni(): Promise<void> {
|
||||
const { server } = window.textsecure;
|
||||
|
||||
strictAssert(
|
||||
server,
|
||||
'updateOurUsernameAndPni: window.textsecure.server not available'
|
||||
);
|
||||
|
||||
const me = window.ConversationController.getOurConversationOrThrow();
|
||||
const { username, pni } = await server.whoami();
|
||||
|
||||
me.set({ username: dropNull(username) });
|
||||
window.Signal.Data.updateConversation(me.attributes);
|
||||
|
||||
const manager = window.getAccountManager();
|
||||
strictAssert(
|
||||
manager,
|
||||
'updateOurUsernameAndPni: AccountManager not available'
|
||||
);
|
||||
|
||||
await manager.setPni(pni);
|
||||
}
|
Loading…
Add table
Reference in a new issue