UUID-keyed lookups in SignalProtocolStore

This commit is contained in:
Fedor Indutny 2021-09-09 19:38:11 -07:00 committed by GitHub
parent 6323aedd9b
commit c7e7d55af4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 2094 additions and 1447 deletions

30
ts/types/Address.ts Normal file
View file

@ -0,0 +1,30 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { strictAssert } from '../util/assert';
import { UUID, UUIDStringType } from './UUID';
export type AddressStringType = `${UUIDStringType}.${number}`;
const ADDRESS_REGEXP = /^([0-9a-f-]+).(\d+)$/i;
export class Address {
constructor(public readonly uuid: UUID, public readonly deviceId: number) {}
public toString(): AddressStringType {
return `${this.uuid.toString()}.${this.deviceId}`;
}
public static parse(value: string): Address {
const match = value.match(ADDRESS_REGEXP);
strictAssert(match !== null, `Invalid Address: ${value}`);
const [whole, uuid, deviceId] = match;
strictAssert(whole === value, 'Integrity check');
return Address.create(uuid, parseInt(deviceId, 10));
}
public static create(uuid: string, deviceId: number): Address {
return new Address(new UUID(uuid), deviceId);
}
}

View file

@ -0,0 +1,48 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { strictAssert } from '../util/assert';
import { UUID, UUIDStringType } from './UUID';
import { Address, AddressStringType } from './Address';
const QUALIFIED_ADDRESS_REGEXP = /^([0-9a-f-]+):([0-9a-f-]+).(\d+)$/i;
export type QualifiedAddressCreateOptionsType = Readonly<{
ourUuid: string;
uuid: string;
deviceId: number;
}>;
export type QualifiedAddressStringType = `${UUIDStringType}:${AddressStringType}`;
export class QualifiedAddress {
constructor(
public readonly ourUuid: UUID,
public readonly address: Address
) {}
public get uuid(): UUID {
return this.address.uuid;
}
public get deviceId(): number {
return this.address.deviceId;
}
public toString(): QualifiedAddressStringType {
return `${this.ourUuid.toString()}:${this.address.toString()}`;
}
public static parse(value: string): QualifiedAddress {
const match = value.match(QUALIFIED_ADDRESS_REGEXP);
strictAssert(match !== null, `Invalid QualifiedAddress: ${value}`);
const [whole, ourUuid, uuid, deviceId] = match;
strictAssert(whole === value, 'Integrity check');
return new QualifiedAddress(
new UUID(ourUuid),
Address.create(uuid, parseInt(deviceId, 10))
);
}
}

12
ts/types/Storage.d.ts vendored
View file

@ -30,6 +30,14 @@ export type ThemeSettingType = 'system' | 'light' | 'dark';
export type NotificationSettingType = 'message' | 'name' | 'count' | 'off';
export type IdentityKeyMap = Record<
string,
{
privKey: string;
pubKey: string;
}
>;
// This should be in sync with `STORAGE_UI_KEYS` in `ts/types/StorageUIKeys.ts`.
export type StorageAccessType = {
'always-relay-calls': boolean;
@ -55,7 +63,7 @@ export type StorageAccessType = {
customColors: CustomColorsItemType;
device_name: string;
hasRegisterSupportForUnauthenticatedDelivery: boolean;
identityKey: KeyPairType;
identityKeyMap: IdentityKeyMap;
lastHeartbeat: number;
lastStartup: number;
lastAttemptedToRefreshProfilesAt: number;
@ -64,7 +72,7 @@ export type StorageAccessType = {
password: string;
profileKey: ArrayBuffer;
regionCode: string;
registrationId: number;
registrationIdMap: Record<string, number>;
remoteBuildExpiration: number;
sessionResets: SessionResetsType;
showStickerPickerHint: boolean;

44
ts/types/UUID.ts Normal file
View file

@ -0,0 +1,44 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { strictAssert } from '../util/assert';
import { isValidGuid } from '../util/isValidGuid';
export type UUIDStringType = `${string}-${string}-${string}-${string}-${string}`;
export class UUID {
constructor(protected readonly value: string) {
strictAssert(isValidGuid(value), `Invalid UUID: ${value}`);
}
public toString(): UUIDStringType {
return (this.value as unknown) as UUIDStringType;
}
public isEqual(other: UUID): boolean {
return this.value === other.value;
}
public static parse(value: string): UUID {
return new UUID(value);
}
public static lookup(identifier: string): UUID | undefined {
const conversation = window.ConversationController.get(identifier);
const uuid = conversation?.get('uuid');
if (uuid === undefined) {
return undefined;
}
return new UUID(uuid);
}
public static checkedLookup(identifier: string): UUID {
const uuid = UUID.lookup(identifier);
strictAssert(
uuid !== undefined,
`Conversation ${identifier} not found or has no uuid`
);
return uuid;
}
}