mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-05-08 08:58:38 +01:00
Fix some import cycles
Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
This commit is contained in:
@@ -51,6 +51,7 @@ import { validateConversation } from './util/validateConversation.dom.js';
|
||||
import { ConversationModel } from './models/conversations.preload.js';
|
||||
import { INITIAL_EXPIRE_TIMER_VERSION } from './util/expirationTimer.std.js';
|
||||
import { missingCaseError } from './util/missingCaseError.std.js';
|
||||
import { removeConversation } from './util/Conversation.preload.js';
|
||||
import { signalProtocolStore } from './SignalProtocolStore.preload.js';
|
||||
|
||||
import type {
|
||||
@@ -159,7 +160,6 @@ const { getAllConversations, getMessagesBySentAt } = DataReader;
|
||||
|
||||
const {
|
||||
migrateConversationMessages,
|
||||
removeConversation,
|
||||
saveConversation,
|
||||
updateConversation,
|
||||
updateConversations,
|
||||
@@ -370,6 +370,7 @@ export class ConversationController {
|
||||
conversationsUpdated([conversation.format()]);
|
||||
}
|
||||
}
|
||||
|
||||
#removeConversation(conversation: ConversationModel): void {
|
||||
this.#_conversations = without(this.#_conversations, conversation);
|
||||
this.#removeFromLookup(conversation);
|
||||
|
||||
@@ -32,7 +32,7 @@ import { Address } from './types/Address.std.js';
|
||||
import { QualifiedAddress } from './types/QualifiedAddress.std.js';
|
||||
import type { ServiceIdString } from './types/ServiceId.std.js';
|
||||
import { normalizeServiceId } from './types/ServiceId.std.js';
|
||||
import { signalProtocolStore } from './SignalProtocolStore.preload.js';
|
||||
import type { SignalProtocolStore } from './SignalProtocolStore.preload.js';
|
||||
|
||||
import type { Zone } from './util/Zone.std.js';
|
||||
|
||||
@@ -52,17 +52,20 @@ function toQualifiedAddress(
|
||||
}
|
||||
|
||||
export type SessionsOptions = Readonly<{
|
||||
signalProtocolStore: SignalProtocolStore;
|
||||
ourServiceId: ServiceIdString;
|
||||
zone?: Zone;
|
||||
}>;
|
||||
|
||||
export class Sessions extends SessionStore {
|
||||
readonly #signalProtocolStore: SignalProtocolStore;
|
||||
readonly #ourServiceId: ServiceIdString;
|
||||
readonly #zone: Zone | undefined;
|
||||
|
||||
constructor({ ourServiceId, zone }: SessionsOptions) {
|
||||
constructor({ signalProtocolStore, ourServiceId, zone }: SessionsOptions) {
|
||||
super();
|
||||
|
||||
this.#signalProtocolStore = signalProtocolStore;
|
||||
this.#ourServiceId = ourServiceId;
|
||||
this.#zone = zone;
|
||||
}
|
||||
@@ -71,7 +74,7 @@ export class Sessions extends SessionStore {
|
||||
address: ProtocolAddress,
|
||||
record: SessionRecord
|
||||
): Promise<void> {
|
||||
await signalProtocolStore.storeSession(
|
||||
await this.#signalProtocolStore.storeSession(
|
||||
toQualifiedAddress(this.#ourServiceId, address),
|
||||
record,
|
||||
{ zone: this.#zone }
|
||||
@@ -80,7 +83,7 @@ export class Sessions extends SessionStore {
|
||||
|
||||
async getSession(name: ProtocolAddress): Promise<SessionRecord | null> {
|
||||
const encodedAddress = toQualifiedAddress(this.#ourServiceId, name);
|
||||
const record = await signalProtocolStore.loadSession(encodedAddress, {
|
||||
const record = await this.#signalProtocolStore.loadSession(encodedAddress, {
|
||||
zone: this.#zone,
|
||||
});
|
||||
|
||||
@@ -93,30 +96,39 @@ export class Sessions extends SessionStore {
|
||||
const encodedAddresses = addresses.map(addr =>
|
||||
toQualifiedAddress(this.#ourServiceId, addr)
|
||||
);
|
||||
return signalProtocolStore.loadSessions(encodedAddresses, {
|
||||
return this.#signalProtocolStore.loadSessions(encodedAddresses, {
|
||||
zone: this.#zone,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export type IdentityKeysOptions = Readonly<{
|
||||
signalProtocolStore: SignalProtocolStore;
|
||||
ourServiceId: ServiceIdString;
|
||||
zone?: Zone;
|
||||
}>;
|
||||
|
||||
export class IdentityKeys extends IdentityKeyStore {
|
||||
readonly #signalProtocolStore: SignalProtocolStore;
|
||||
readonly #ourServiceId: ServiceIdString;
|
||||
readonly #zone: Zone | undefined;
|
||||
|
||||
constructor({ ourServiceId, zone }: IdentityKeysOptions) {
|
||||
constructor({
|
||||
signalProtocolStore,
|
||||
ourServiceId,
|
||||
zone,
|
||||
}: IdentityKeysOptions) {
|
||||
super();
|
||||
|
||||
this.#signalProtocolStore = signalProtocolStore;
|
||||
this.#ourServiceId = ourServiceId;
|
||||
this.#zone = zone;
|
||||
}
|
||||
|
||||
async getIdentityKey(): Promise<PrivateKey> {
|
||||
const keyPair = signalProtocolStore.getIdentityKeyPair(this.#ourServiceId);
|
||||
const keyPair = this.#signalProtocolStore.getIdentityKeyPair(
|
||||
this.#ourServiceId
|
||||
);
|
||||
if (!keyPair) {
|
||||
throw new Error('IdentityKeyStore/getIdentityKey: No identity key!');
|
||||
}
|
||||
@@ -124,7 +136,7 @@ export class IdentityKeys extends IdentityKeyStore {
|
||||
}
|
||||
|
||||
async getLocalRegistrationId(): Promise<number> {
|
||||
const id = await signalProtocolStore.getLocalRegistrationId(
|
||||
const id = await this.#signalProtocolStore.getLocalRegistrationId(
|
||||
this.#ourServiceId
|
||||
);
|
||||
if (!isNumber(id)) {
|
||||
@@ -137,7 +149,7 @@ export class IdentityKeys extends IdentityKeyStore {
|
||||
|
||||
async getIdentity(address: ProtocolAddress): Promise<PublicKey | null> {
|
||||
const encodedAddress = encodeAddress(address);
|
||||
const key = await signalProtocolStore.loadIdentityKey(
|
||||
const key = await this.#signalProtocolStore.loadIdentityKey(
|
||||
encodedAddress.serviceId
|
||||
);
|
||||
|
||||
@@ -157,9 +169,14 @@ export class IdentityKeys extends IdentityKeyStore {
|
||||
|
||||
// Pass `zone` to let `saveIdentity` archive sibling sessions when identity
|
||||
// key changes.
|
||||
return signalProtocolStore.saveIdentity(encodedAddress, publicKey, false, {
|
||||
zone: this.#zone,
|
||||
});
|
||||
return this.#signalProtocolStore.saveIdentity(
|
||||
encodedAddress,
|
||||
publicKey,
|
||||
false,
|
||||
{
|
||||
zone: this.#zone,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async isTrustedIdentity(
|
||||
@@ -170,7 +187,7 @@ export class IdentityKeys extends IdentityKeyStore {
|
||||
const encodedAddress = encodeAddress(name);
|
||||
const publicKey = key.serialize();
|
||||
|
||||
return signalProtocolStore.isTrustedIdentity(
|
||||
return this.#signalProtocolStore.isTrustedIdentity(
|
||||
encodedAddress,
|
||||
publicKey,
|
||||
direction
|
||||
@@ -179,16 +196,19 @@ export class IdentityKeys extends IdentityKeyStore {
|
||||
}
|
||||
|
||||
export type PreKeysOptions = Readonly<{
|
||||
signalProtocolStore: SignalProtocolStore;
|
||||
ourServiceId: ServiceIdString;
|
||||
zone?: Zone;
|
||||
}>;
|
||||
|
||||
export class PreKeys extends PreKeyStore {
|
||||
readonly #signalProtocolStore: SignalProtocolStore;
|
||||
readonly #ourServiceId: ServiceIdString;
|
||||
readonly #zone: Zone | undefined;
|
||||
|
||||
constructor({ ourServiceId, zone }: PreKeysOptions) {
|
||||
constructor({ signalProtocolStore, ourServiceId, zone }: PreKeysOptions) {
|
||||
super();
|
||||
this.#signalProtocolStore = signalProtocolStore;
|
||||
this.#ourServiceId = ourServiceId;
|
||||
this.#zone = zone;
|
||||
}
|
||||
@@ -198,7 +218,10 @@ export class PreKeys extends PreKeyStore {
|
||||
}
|
||||
|
||||
async getPreKey(id: number): Promise<PreKeyRecord> {
|
||||
const preKey = await signalProtocolStore.loadPreKey(this.#ourServiceId, id);
|
||||
const preKey = await this.#signalProtocolStore.loadPreKey(
|
||||
this.#ourServiceId,
|
||||
id
|
||||
);
|
||||
|
||||
if (preKey === undefined) {
|
||||
throw new Error(`getPreKey: PreKey ${id} not found`);
|
||||
@@ -208,18 +231,20 @@ export class PreKeys extends PreKeyStore {
|
||||
}
|
||||
|
||||
async removePreKey(id: number): Promise<void> {
|
||||
await signalProtocolStore.removePreKeys(this.#ourServiceId, [id], {
|
||||
await this.#signalProtocolStore.removePreKeys(this.#ourServiceId, [id], {
|
||||
zone: this.#zone,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class KyberPreKeys extends KyberPreKeyStore {
|
||||
readonly #signalProtocolStore: SignalProtocolStore;
|
||||
readonly #ourServiceId: ServiceIdString;
|
||||
readonly #zone: Zone | undefined;
|
||||
|
||||
constructor({ ourServiceId, zone }: PreKeysOptions) {
|
||||
constructor({ signalProtocolStore, ourServiceId, zone }: PreKeysOptions) {
|
||||
super();
|
||||
this.#signalProtocolStore = signalProtocolStore;
|
||||
this.#ourServiceId = ourServiceId;
|
||||
this.#zone = zone;
|
||||
}
|
||||
@@ -229,7 +254,7 @@ export class KyberPreKeys extends KyberPreKeyStore {
|
||||
}
|
||||
|
||||
async getKyberPreKey(id: number): Promise<KyberPreKeyRecord> {
|
||||
const kyberPreKey = await signalProtocolStore.loadKyberPreKey(
|
||||
const kyberPreKey = await this.#signalProtocolStore.loadKyberPreKey(
|
||||
this.#ourServiceId,
|
||||
id
|
||||
);
|
||||
@@ -246,7 +271,7 @@ export class KyberPreKeys extends KyberPreKeyStore {
|
||||
signedPreKeyId: number,
|
||||
baseKey: PublicKey
|
||||
): Promise<void> {
|
||||
await signalProtocolStore.maybeRemoveKyberPreKey(
|
||||
await this.#signalProtocolStore.maybeRemoveKyberPreKey(
|
||||
this.#ourServiceId,
|
||||
{ keyId, signedPreKeyId, baseKey },
|
||||
{ zone: this.#zone }
|
||||
@@ -255,16 +280,19 @@ export class KyberPreKeys extends KyberPreKeyStore {
|
||||
}
|
||||
|
||||
export type SenderKeysOptions = Readonly<{
|
||||
readonly ourServiceId: ServiceIdString;
|
||||
readonly zone: Zone | undefined;
|
||||
signalProtocolStore: SignalProtocolStore;
|
||||
ourServiceId: ServiceIdString;
|
||||
zone: Zone | undefined;
|
||||
}>;
|
||||
|
||||
export class SenderKeys extends SenderKeyStore {
|
||||
readonly #signalProtocolStore: SignalProtocolStore;
|
||||
readonly #ourServiceId: ServiceIdString;
|
||||
readonly zone: Zone | undefined;
|
||||
|
||||
constructor({ ourServiceId, zone }: SenderKeysOptions) {
|
||||
constructor({ signalProtocolStore, ourServiceId, zone }: SenderKeysOptions) {
|
||||
super();
|
||||
this.#signalProtocolStore = signalProtocolStore;
|
||||
this.#ourServiceId = ourServiceId;
|
||||
this.zone = zone;
|
||||
}
|
||||
@@ -276,7 +304,7 @@ export class SenderKeys extends SenderKeyStore {
|
||||
): Promise<void> {
|
||||
const encodedAddress = toQualifiedAddress(this.#ourServiceId, sender);
|
||||
|
||||
await signalProtocolStore.saveSenderKey(
|
||||
await this.#signalProtocolStore.saveSenderKey(
|
||||
encodedAddress,
|
||||
distributionId,
|
||||
record,
|
||||
@@ -290,7 +318,7 @@ export class SenderKeys extends SenderKeyStore {
|
||||
): Promise<SenderKeyRecord | null> {
|
||||
const encodedAddress = toQualifiedAddress(this.#ourServiceId, sender);
|
||||
|
||||
const senderKey = await signalProtocolStore.getSenderKey(
|
||||
const senderKey = await this.#signalProtocolStore.getSenderKey(
|
||||
encodedAddress,
|
||||
distributionId,
|
||||
{ zone: this.zone }
|
||||
@@ -301,15 +329,18 @@ export class SenderKeys extends SenderKeyStore {
|
||||
}
|
||||
|
||||
export type SignedPreKeysOptions = Readonly<{
|
||||
signalProtocolStore: SignalProtocolStore;
|
||||
ourServiceId: ServiceIdString;
|
||||
}>;
|
||||
|
||||
// No need for zone awareness, since no mutation happens in this store
|
||||
export class SignedPreKeys extends SignedPreKeyStore {
|
||||
readonly #signalProtocolStore: SignalProtocolStore;
|
||||
readonly #ourServiceId: ServiceIdString;
|
||||
|
||||
constructor({ ourServiceId }: SignedPreKeysOptions) {
|
||||
constructor({ signalProtocolStore, ourServiceId }: SignedPreKeysOptions) {
|
||||
super();
|
||||
this.#signalProtocolStore = signalProtocolStore;
|
||||
this.#ourServiceId = ourServiceId;
|
||||
}
|
||||
|
||||
@@ -318,7 +349,7 @@ export class SignedPreKeys extends SignedPreKeyStore {
|
||||
}
|
||||
|
||||
async getSignedPreKey(id: number): Promise<SignedPreKeyRecord> {
|
||||
const signedPreKey = await signalProtocolStore.loadSignedPreKey(
|
||||
const signedPreKey = await this.#signalProtocolStore.loadSignedPreKey(
|
||||
this.#ourServiceId,
|
||||
id
|
||||
);
|
||||
@@ -332,24 +363,30 @@ export class SignedPreKeys extends SignedPreKeyStore {
|
||||
}
|
||||
|
||||
export class KeyTransparencyStore implements KeyTransparencyStoreInterface {
|
||||
readonly #signalProtocolStore: SignalProtocolStore;
|
||||
|
||||
constructor(signalProtocolStore: SignalProtocolStore) {
|
||||
this.#signalProtocolStore = signalProtocolStore;
|
||||
}
|
||||
|
||||
async getLastDistinguishedTreeHead(): Promise<Uint8Array<ArrayBuffer> | null> {
|
||||
return signalProtocolStore.getLastDistinguishedTreeHead();
|
||||
return this.#signalProtocolStore.getLastDistinguishedTreeHead();
|
||||
}
|
||||
|
||||
async setLastDistinguishedTreeHead(
|
||||
bytes: Readonly<Uint8Array<ArrayBuffer>> | null
|
||||
): Promise<void> {
|
||||
return signalProtocolStore.setLastDistinguishedTreeHead(bytes);
|
||||
return this.#signalProtocolStore.setLastDistinguishedTreeHead(bytes);
|
||||
}
|
||||
|
||||
async getAccountData(aci: Aci): Promise<Uint8Array<ArrayBuffer> | null> {
|
||||
return signalProtocolStore.getKTAccountData(aci);
|
||||
return this.#signalProtocolStore.getKTAccountData(aci);
|
||||
}
|
||||
|
||||
async setAccountData(
|
||||
aci: Aci,
|
||||
bytes: Readonly<Uint8Array<ArrayBuffer>>
|
||||
): Promise<void> {
|
||||
return signalProtocolStore.setKTAccountData(aci, bytes);
|
||||
return this.#signalProtocolStore.setKTAccountData(aci, bytes);
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,7 @@ import { dropNull } from '../util/dropNull.std.js';
|
||||
import { getLocalAttachmentUrl } from '../util/getLocalAttachmentUrl.std.js';
|
||||
import { type Loadable, LoadingState } from '../util/loadable.std.js';
|
||||
import { missingCaseError } from '../util/missingCaseError.std.js';
|
||||
import { removeConversation } from '../util/Conversation.preload.js';
|
||||
import { itemStorage } from '../textsecure/Storage.preload.js';
|
||||
|
||||
const log = createLogger('joinViaLink');
|
||||
@@ -371,7 +372,7 @@ export async function joinViaLink(value: string): Promise<void> {
|
||||
window.ConversationController.dangerouslyRemoveById(
|
||||
tempConversation.id
|
||||
);
|
||||
await DataWriter.removeConversation(tempConversation.id);
|
||||
await removeConversation(tempConversation.id);
|
||||
}
|
||||
|
||||
throw error;
|
||||
|
||||
@@ -86,7 +86,7 @@ import { JobCancelReason } from './types.std.js';
|
||||
import { isAbortError } from '../util/isAbortError.std.js';
|
||||
import { itemStorage } from '../textsecure/Storage.preload.js';
|
||||
import { calculateExpirationTimestamp } from '../util/expirationTimer.std.js';
|
||||
import { cleanupAttachmentFiles } from '../types/Message2.preload.js';
|
||||
import { cleanupAttachmentFiles } from '../util/cleanup.preload.js';
|
||||
import { getExistingAttachmentDataForReuse } from '../util/attachments/deduplicateAttachment.preload.js';
|
||||
|
||||
const { noop, omit, throttle } = lodash;
|
||||
|
||||
@@ -67,7 +67,7 @@ import type {
|
||||
GroupCallPeekInfoType,
|
||||
} from '../state/ducks/calling.preload.js';
|
||||
import type { ConversationType } from '../state/ducks/conversations.preload.js';
|
||||
import { getConversationCallMode } from '../state/ducks/conversations.preload.js';
|
||||
import { getConversationCallMode } from '../util/getConversationCallMode.std.js';
|
||||
import { isMe } from '../util/whatTypeOfConversation.dom.js';
|
||||
import { getAbsoluteTempPath } from '../util/migrations.preload.js';
|
||||
import { isKnownProtoEnumMember } from '../util/isKnownProtoEnumMember.std.js';
|
||||
|
||||
@@ -13,11 +13,9 @@ import * as Bytes from '../Bytes.std.js';
|
||||
import { createLogger } from '../logging/log.std.js';
|
||||
import * as Errors from '../types/errors.std.js';
|
||||
|
||||
import { deleteExternalFiles } from '../types/Conversation.std.js';
|
||||
import { createBatcher } from '../util/batcher.std.js';
|
||||
import { assertDev, softAssert } from '../util/assert.std.js';
|
||||
import { mapObjectWithSpec } from '../util/mapObjectWithSpec.std.js';
|
||||
import { maybeDeleteAttachmentFile } from '../util/migrations.preload.js';
|
||||
import { cleanDataForIpc } from './cleanDataForIpc.std.js';
|
||||
import { runTaskWithTimeout } from '../textsecure/TaskWithTimeout.std.js';
|
||||
import { isValidUuid, isValidUuidV7 } from '../util/isValidUuid.std.js';
|
||||
@@ -131,7 +129,6 @@ const clientOnlyWritable: ClientOnlyWritableInterface = {
|
||||
createOrUpdateItem,
|
||||
|
||||
updateConversation,
|
||||
removeConversation,
|
||||
|
||||
removeMessageById,
|
||||
removeMessagesById,
|
||||
@@ -553,19 +550,6 @@ async function updateConversations(
|
||||
await writableChannel.updateConversations(cleaned);
|
||||
}
|
||||
|
||||
async function removeConversation(id: string): Promise<void> {
|
||||
const existing = await readableChannel.getConversationById(id);
|
||||
|
||||
// Note: It's important to have a fully database-hydrated model to delete here because
|
||||
// it needs to delete all associated on-disk files along with the database delete.
|
||||
if (existing) {
|
||||
await writableChannel.removeConversation(id);
|
||||
await deleteExternalFiles(existing, {
|
||||
maybeDeleteAttachmentFile,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleSearchMessageJSON(
|
||||
messages: Array<ServerSearchResultMessageType>
|
||||
): Array<ClientSearchResultMessageType> {
|
||||
|
||||
@@ -1190,7 +1190,8 @@ type WritableInterface = {
|
||||
saveConversations: (array: Array<ConversationType>) => void;
|
||||
// updateConversation is a normal data method on Server, a sync batch-add on Client
|
||||
updateConversations: (array: Array<ConversationType>) => void;
|
||||
// removeConversation handles either one id or an array on Server, and one id on Client
|
||||
/** @internal use ts/util/Conversation.preload.ts */
|
||||
_removeConversation: (id: string) => void;
|
||||
_removeAllConversations: () => void;
|
||||
updateAllConversationColors: (
|
||||
conversationColor?: ConversationColorType,
|
||||
@@ -1583,7 +1584,6 @@ export type ServerWritableDirectInterface = WritableInterface & {
|
||||
// Differing signature on client/server
|
||||
|
||||
updateConversation: (data: ConversationType) => void;
|
||||
removeConversation: (id: Array<string> | string) => void;
|
||||
|
||||
saveMessage: (
|
||||
data: ReadonlyDeep<MessageType>,
|
||||
@@ -1689,7 +1689,6 @@ export type ClientOnlyReadableInterface = ClientInterfaceWrap<{
|
||||
export type ClientOnlyWritableInterface = ClientInterfaceWrap<{
|
||||
// Differing signature on client/server
|
||||
updateConversation: (data: ConversationType) => void;
|
||||
removeConversation: (id: string) => void;
|
||||
flushUpdateConversationBatcher: () => void;
|
||||
|
||||
saveMessage: (
|
||||
|
||||
+5
-32
@@ -637,7 +637,7 @@ export const DataWriter: ServerWritableInterface = {
|
||||
saveConversations,
|
||||
updateConversation,
|
||||
updateConversations,
|
||||
removeConversation,
|
||||
_removeConversation,
|
||||
_removeAllConversations,
|
||||
updateAllConversationColors,
|
||||
removeAllProfileKeyCredentials,
|
||||
@@ -2046,37 +2046,10 @@ function updateConversations(
|
||||
})();
|
||||
}
|
||||
|
||||
function removeConversations(
|
||||
db: WritableDB,
|
||||
ids: ReadonlyArray<string>,
|
||||
persistent: boolean
|
||||
): void {
|
||||
// Our node interface doesn't seem to allow you to replace one single ? with an array
|
||||
db.prepare(
|
||||
`
|
||||
DELETE FROM conversations
|
||||
WHERE id IN ( ${ids.map(() => '?').join(', ')} );
|
||||
`,
|
||||
{ persistent }
|
||||
).run(ids);
|
||||
}
|
||||
|
||||
function removeConversation(db: WritableDB, id: Array<string> | string): void {
|
||||
if (!Array.isArray(id)) {
|
||||
db.prepare('DELETE FROM conversations WHERE id = $id;').run({
|
||||
id,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!id.length) {
|
||||
throw new Error('removeConversation: No ids to delete!');
|
||||
}
|
||||
|
||||
batchMultiVarQuery(db, id, (ids, persistent) =>
|
||||
removeConversations(db, ids, persistent)
|
||||
);
|
||||
function _removeConversation(db: WritableDB, id: string): void {
|
||||
db.prepare('DELETE FROM conversations WHERE id = $id;').run({
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
function _removeAllConversations(db: WritableDB): void {
|
||||
|
||||
@@ -69,12 +69,10 @@ import type {
|
||||
ConversationsUpdatedActionType,
|
||||
ConversationRemovedActionType,
|
||||
} from './conversations.preload.js';
|
||||
import {
|
||||
getConversationCallMode,
|
||||
updateLastMessage,
|
||||
} from './conversations.preload.js';
|
||||
import { updateLastMessage } from './conversations.preload.js';
|
||||
import { createLogger } from '../../logging/log.std.js';
|
||||
import { strictAssert } from '../../util/assert.std.js';
|
||||
import { getConversationCallMode } from '../../util/getConversationCallMode.std.js';
|
||||
import { waitForOnline } from '../../util/waitForOnline.dom.js';
|
||||
import * as mapUtil from '../../util/mapUtil.std.js';
|
||||
import { isCallSafe } from '../../util/isCallSafe.dom.js';
|
||||
|
||||
@@ -657,31 +657,6 @@ export type ConversationsStateType = ReadonlyDeep<{
|
||||
hasProfileUpdateError?: boolean;
|
||||
}>;
|
||||
|
||||
// Helpers
|
||||
|
||||
export const getConversationCallMode = (
|
||||
conversation: ConversationType
|
||||
): CallMode | null => {
|
||||
if (
|
||||
conversation.left ||
|
||||
conversation.isBlocked ||
|
||||
conversation.isMe ||
|
||||
!conversation.acceptedMessageRequest
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (conversation.type === 'direct') {
|
||||
return CallMode.Direct;
|
||||
}
|
||||
|
||||
if (conversation.type === 'group' && conversation.groupVersion === 2) {
|
||||
return CallMode.Group;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
// Actions
|
||||
|
||||
const CANCEL_CONVERSATION_PENDING_VERIFICATION =
|
||||
|
||||
@@ -97,7 +97,7 @@ import {
|
||||
AttachmentDisposition,
|
||||
} from '../../util/getLocalAttachmentUrl.std.js';
|
||||
import { isVoiceMessagePlayed } from '../../util/isVoiceMessagePlayed.std.js';
|
||||
import { isPermanentlyUndownloadable } from '../../jobs/AttachmentDownloadManager.preload.js';
|
||||
import { isPermanentlyUndownloadable } from '../../jobs/helpers/attachmentBackfill.preload.js';
|
||||
|
||||
import { getAccountSelector } from './accounts.std.js';
|
||||
import {
|
||||
|
||||
@@ -20,13 +20,11 @@ import { isConversationSMSOnly } from '../../util/isConversationSMSOnly.std.js';
|
||||
import { isGroupOrAdhocCallState } from '../../util/isGroupOrAdhocCall.std.js';
|
||||
import { isSignalConversation } from '../../util/isSignalConversation.dom.js';
|
||||
import { missingCaseError } from '../../util/missingCaseError.std.js';
|
||||
import { getConversationCallMode } from '../../util/getConversationCallMode.std.js';
|
||||
import { useCallingActions } from '../ducks/calling.preload.js';
|
||||
import { isAnybodyElseInGroupCall } from '../ducks/callingHelpers.std.js';
|
||||
import type { ConversationType } from '../ducks/conversations.preload.js';
|
||||
import {
|
||||
getConversationCallMode,
|
||||
useConversationsActions,
|
||||
} from '../ducks/conversations.preload.js';
|
||||
import { useConversationsActions } from '../ducks/conversations.preload.js';
|
||||
import { useSearchActions } from '../ducks/search.preload.js';
|
||||
import { useStoriesActions } from '../ducks/stories.preload.js';
|
||||
import { getPreferredBadgeSelector } from '../selectors/badges.preload.js';
|
||||
|
||||
@@ -26,14 +26,14 @@ import { strictAssert } from '../util/assert.std.js';
|
||||
import {
|
||||
cleanupAllMessageAttachmentFiles,
|
||||
cleanupAttachmentFiles,
|
||||
} from '../types/Message2.preload.js';
|
||||
cleanupMessages,
|
||||
} from '../util/cleanup.preload.js';
|
||||
import { DataReader, DataWriter } from '../sql/Client.preload.js';
|
||||
import { generateAci } from '../types/ServiceId.std.js';
|
||||
import {
|
||||
testAttachmentLocalKey,
|
||||
testPlaintextHash,
|
||||
} from '../test-helpers/attachments.node.js';
|
||||
import { cleanupMessages } from '../util/cleanup.preload.js';
|
||||
|
||||
const { emptyDir, ensureFile } = fsExtra;
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ import {
|
||||
actions,
|
||||
cancelConversationVerification,
|
||||
clearCanceledConversationVerification,
|
||||
getConversationCallMode,
|
||||
getEmptyState,
|
||||
reducer,
|
||||
updateConversationLookups,
|
||||
@@ -69,6 +68,7 @@ import {
|
||||
import { MY_STORY_ID } from '../../../types/Stories.std.js';
|
||||
import type { ReadonlyMessageAttributesType } from '../../../model-types.d.ts';
|
||||
import { strictAssert } from '../../../util/assert.std.js';
|
||||
import { getConversationCallMode } from '../../../util/getConversationCallMode.std.js';
|
||||
import { itemStorage } from '../../../textsecure/Storage.preload.js';
|
||||
|
||||
const { times } = lodash;
|
||||
|
||||
@@ -14,6 +14,7 @@ import * as KeyChangeListener from '../../textsecure/KeyChangeListener.dom.js';
|
||||
import { itemStorage } from '../../textsecure/Storage.preload.js';
|
||||
import * as Bytes from '../../Bytes.std.js';
|
||||
import { cleanupMessages } from '../../util/cleanup.preload.js';
|
||||
import { removeConversation } from '../../util/Conversation.preload.js';
|
||||
|
||||
describe('KeyChangeListener', () => {
|
||||
let oldNumberId: string | undefined;
|
||||
@@ -71,7 +72,7 @@ describe('KeyChangeListener', () => {
|
||||
logId: ourServiceIdWithKeyChange,
|
||||
cleanupMessages,
|
||||
});
|
||||
await DataWriter.removeConversation(convo.id);
|
||||
await removeConversation(convo.id);
|
||||
|
||||
await store.removeIdentityKey(ourServiceIdWithKeyChange);
|
||||
});
|
||||
@@ -113,7 +114,7 @@ describe('KeyChangeListener', () => {
|
||||
logId: ourServiceIdWithKeyChange,
|
||||
cleanupMessages,
|
||||
});
|
||||
await DataWriter.removeConversation(groupConvo.id);
|
||||
await removeConversation(groupConvo.id);
|
||||
});
|
||||
|
||||
it('generates a key change notice in the group conversation with this contact', async () => {
|
||||
|
||||
@@ -38,7 +38,7 @@ import {
|
||||
SenderKeys,
|
||||
Sessions,
|
||||
SignedPreKeys,
|
||||
} from '../LibSignalStores.preload.js';
|
||||
} from '../LibSignalStores.node.js';
|
||||
import { createName } from '../util/attachmentPath.node.js';
|
||||
import { assertDev, strictAssert } from '../util/assert.std.js';
|
||||
import type { BatcherType } from '../util/batcher.std.js';
|
||||
@@ -1022,6 +1022,7 @@ export default class MessageReceiver
|
||||
let stores = storesMap.get(destinationServiceId);
|
||||
if (!stores) {
|
||||
const sharedParams = {
|
||||
signalProtocolStore,
|
||||
ourServiceId: destinationServiceId,
|
||||
zone,
|
||||
};
|
||||
|
||||
@@ -45,7 +45,7 @@ import * as Errors from '../types/errors.std.js';
|
||||
import { HTTPError } from '../types/HTTPError.std.js';
|
||||
import { QualifiedAddress } from '../types/QualifiedAddress.std.js';
|
||||
import type { ServiceIdString } from '../types/ServiceId.std.js';
|
||||
import { Sessions, IdentityKeys } from '../LibSignalStores.preload.js';
|
||||
import { Sessions, IdentityKeys } from '../LibSignalStores.node.js';
|
||||
import { getKeysForServiceId } from './getKeysForServiceId.preload.js';
|
||||
import { SignalService as Proto } from '../protobuf/index.std.js';
|
||||
import { createLogger } from '../logging/log.std.js';
|
||||
@@ -438,8 +438,14 @@ export default class OutgoingMessage {
|
||||
);
|
||||
}
|
||||
|
||||
const sessionStore = new Sessions({ ourServiceId: ourAci });
|
||||
const identityKeyStore = new IdentityKeys({ ourServiceId: ourAci });
|
||||
const sessionStore = new Sessions({
|
||||
signalProtocolStore,
|
||||
ourServiceId: ourAci,
|
||||
});
|
||||
const identityKeyStore = new IdentityKeys({
|
||||
signalProtocolStore,
|
||||
ourServiceId: ourAci,
|
||||
});
|
||||
|
||||
return Promise.all(
|
||||
deviceIds.map(async destinationDeviceId => {
|
||||
|
||||
@@ -27,7 +27,7 @@ import { uuidToBytes } from '../util/uuidToBytes.std.js';
|
||||
import { Address } from '../types/Address.std.js';
|
||||
import { QualifiedAddress } from '../types/QualifiedAddress.std.js';
|
||||
import type { StoryMessageRecipientsType } from '../types/Stories.std.js';
|
||||
import { SenderKeys } from '../LibSignalStores.preload.js';
|
||||
import { SenderKeys } from '../LibSignalStores.node.js';
|
||||
import type {
|
||||
TextAttachmentType,
|
||||
UploadedAttachmentType,
|
||||
@@ -2722,6 +2722,7 @@ export class MessageSender {
|
||||
const senderKeyDistributionMessage =
|
||||
await signalProtocolStore.enqueueSenderKeyJob(address, async () => {
|
||||
const senderKeyStore = new SenderKeys({
|
||||
signalProtocolStore,
|
||||
ourServiceId: ourAci,
|
||||
zone: GLOBAL_ZONE,
|
||||
});
|
||||
|
||||
@@ -129,7 +129,8 @@ import {
|
||||
type RemoteMegaphoneId,
|
||||
} from '../types/Megaphone.std.js';
|
||||
import { bindRemoteConfigToLibsignalNet } from '../LibsignalNetRemoteConfig.preload.js';
|
||||
import { KeyTransparencyStore } from '../LibSignalStores.preload.js';
|
||||
import { KeyTransparencyStore } from '../LibSignalStores.node.js';
|
||||
import { signalProtocolStore } from '../SignalProtocolStore.preload.js';
|
||||
|
||||
const { escapeRegExp, isNumber, throttle } = lodash;
|
||||
|
||||
@@ -2501,7 +2502,7 @@ export async function keyTransparencySearch(
|
||||
throw new Error('Aborted');
|
||||
}
|
||||
const kt = chat.keyTransparencyClient();
|
||||
const store = new KeyTransparencyStore();
|
||||
const store = new KeyTransparencyStore(signalProtocolStore);
|
||||
return kt.search(request, store, { abortSignal });
|
||||
});
|
||||
}
|
||||
@@ -2517,7 +2518,7 @@ export async function keyTransparencyMonitor(
|
||||
throw new Error('Aborted');
|
||||
}
|
||||
const kt = chat.keyTransparencyClient();
|
||||
const store = new KeyTransparencyStore();
|
||||
const store = new KeyTransparencyStore(signalProtocolStore);
|
||||
return kt.monitor(
|
||||
{
|
||||
...request,
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
OutgoingIdentityKeyError,
|
||||
UnregisteredUserError,
|
||||
} from './Errors.std.js';
|
||||
import { Sessions, IdentityKeys } from '../LibSignalStores.preload.js';
|
||||
import { Sessions, IdentityKeys } from '../LibSignalStores.node.js';
|
||||
import { Address } from '../types/Address.std.js';
|
||||
import { QualifiedAddress } from '../types/QualifiedAddress.std.js';
|
||||
import type { ServiceIdString } from '../types/ServiceId.std.js';
|
||||
@@ -133,8 +133,14 @@ async function handleServerKeys(
|
||||
devicesToUpdate: Array<number> | null
|
||||
): Promise<void> {
|
||||
const ourAci = itemStorage.user.getCheckedAci();
|
||||
const sessionStore = new Sessions({ ourServiceId: ourAci });
|
||||
const identityKeyStore = new IdentityKeys({ ourServiceId: ourAci });
|
||||
const sessionStore = new Sessions({
|
||||
signalProtocolStore,
|
||||
ourServiceId: ourAci,
|
||||
});
|
||||
const identityKeyStore = new IdentityKeys({
|
||||
signalProtocolStore,
|
||||
ourServiceId: ourAci,
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
response.devices.map(async device => {
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
// Copyright 2018 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { ConversationAttributesType } from '../model-types.d.ts';
|
||||
|
||||
export async function deleteExternalFiles(
|
||||
conversation: ConversationAttributesType,
|
||||
{
|
||||
maybeDeleteAttachmentFile,
|
||||
}: {
|
||||
maybeDeleteAttachmentFile: (
|
||||
path: string
|
||||
) => Promise<{ wasDeleted: boolean }>;
|
||||
}
|
||||
): Promise<void> {
|
||||
if (!conversation) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { avatar, profileAvatar } = conversation;
|
||||
|
||||
if (avatar && avatar.path) {
|
||||
await maybeDeleteAttachmentFile(avatar.path);
|
||||
}
|
||||
|
||||
if (profileAvatar && profileAvatar.path) {
|
||||
await maybeDeleteAttachmentFile(profileAvatar.path);
|
||||
}
|
||||
}
|
||||
@@ -56,14 +56,6 @@ import { deepClone } from '../util/deepClone.std.js';
|
||||
import * as Bytes from '../Bytes.std.js';
|
||||
import { isBodyTooLong } from '../util/longAttachment.std.js';
|
||||
import type { MessageAttachmentType } from './AttachmentDownload.std.js';
|
||||
import {
|
||||
getFilePathsReferencedByAttachment,
|
||||
getFilePathsReferencedByMessage,
|
||||
} from '../util/messageFilePaths.std.js';
|
||||
import {
|
||||
deleteDownloadFile,
|
||||
maybeDeleteAttachmentFile,
|
||||
} from '../util/migrations.preload.js';
|
||||
import type { getExistingAttachmentDataForReuse } from '../util/attachments/deduplicateAttachment.preload.js';
|
||||
import type { getPlaintextHashForInMemoryAttachment } from '../AttachmentCrypto.node.js';
|
||||
import { strictAssert } from '../util/assert.std.js';
|
||||
@@ -1050,31 +1042,6 @@ export const loadStickerData = (
|
||||
};
|
||||
};
|
||||
|
||||
export const cleanupAllMessageAttachmentFiles = async (
|
||||
message: MessageAttributesType
|
||||
): Promise<void> => {
|
||||
const { externalAttachments, externalDownloads } =
|
||||
getFilePathsReferencedByMessage(message);
|
||||
await Promise.all(
|
||||
[...externalAttachments].map(attachmentPath =>
|
||||
maybeDeleteAttachmentFile(attachmentPath)
|
||||
)
|
||||
);
|
||||
await Promise.all(
|
||||
[...externalDownloads].map(downloadPath => deleteDownloadFile(downloadPath))
|
||||
);
|
||||
};
|
||||
|
||||
export async function cleanupAttachmentFiles(
|
||||
attachment: AttachmentType
|
||||
): Promise<void> {
|
||||
const result = getFilePathsReferencedByAttachment(attachment);
|
||||
await Promise.all(
|
||||
[...result.externalAttachments].map(maybeDeleteAttachmentFile)
|
||||
);
|
||||
await Promise.all([...result.externalDownloads].map(deleteDownloadFile));
|
||||
}
|
||||
|
||||
export async function migrateBodyAttachmentToDisk(
|
||||
message: MessageAttributesType,
|
||||
{ logger, writeNewAttachmentData }: ContextType
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2018 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { DataReader, DataWriter } from '../sql/Client.preload.js';
|
||||
import type { ConversationAttributesType } from '../model-types.d.ts';
|
||||
import { maybeDeleteAttachmentFile } from './migrations.preload.js';
|
||||
|
||||
async function deleteExternalFiles(
|
||||
conversation: ConversationAttributesType
|
||||
): Promise<void> {
|
||||
if (!conversation) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { avatar, profileAvatar } = conversation;
|
||||
|
||||
if (avatar && avatar.path) {
|
||||
await maybeDeleteAttachmentFile(avatar.path);
|
||||
}
|
||||
|
||||
if (profileAvatar && profileAvatar.path) {
|
||||
await maybeDeleteAttachmentFile(profileAvatar.path);
|
||||
}
|
||||
}
|
||||
|
||||
export async function removeConversation(id: string): Promise<void> {
|
||||
const existing = await DataReader.getConversationById(id);
|
||||
|
||||
// Note: It's important to have a fully database-hydrated model to delete here because
|
||||
// it needs to delete all associated on-disk files along with the database delete.
|
||||
if (existing) {
|
||||
await DataWriter._removeConversation(id);
|
||||
await deleteExternalFiles(existing);
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,20 @@ import { getMessageIdForLogging } from './idForLogging.preload.js';
|
||||
import { singleProtoJobQueue } from '../jobs/singleProtoJobQueue.preload.js';
|
||||
import { MINUTE } from './durations/index.std.js';
|
||||
import { drop } from './drop.std.js';
|
||||
import {
|
||||
getFilePathsReferencedByAttachment,
|
||||
getFilePathsReferencedByMessage,
|
||||
} from './messageFilePaths.std.js';
|
||||
import {
|
||||
deleteDownloadFile,
|
||||
maybeDeleteAttachmentFile,
|
||||
} from './migrations.preload.js';
|
||||
import { hydrateStoryContext } from './hydrateStoryContext.preload.js';
|
||||
import { update as updateExpiringMessagesService } from '../services/expiringMessagesDeletion.preload.js';
|
||||
import { tapToViewMessagesDeletionService } from '../services/tapToViewMessagesDeletionService.preload.js';
|
||||
import { throttledUpdateBackupMediaDownloadProgress } from './updateBackupMediaDownloadProgress.preload.js';
|
||||
import { messageAttrsToPreserveAfterErase } from '../types/Message.std.js';
|
||||
import { cleanupAllMessageAttachmentFiles } from '../types/Message2.preload.js';
|
||||
import type { AttachmentType } from '../types/Attachment.std.js';
|
||||
|
||||
const log = createLogger('cleanup');
|
||||
|
||||
@@ -281,3 +289,28 @@ export async function maybeDeleteCall(
|
||||
await DataWriter.markCallHistoryDeleted(callId);
|
||||
window.reduxActions.callHistory.removeCallHistory(callId);
|
||||
}
|
||||
|
||||
export const cleanupAllMessageAttachmentFiles = async (
|
||||
message: MessageAttributesType
|
||||
): Promise<void> => {
|
||||
const { externalAttachments, externalDownloads } =
|
||||
getFilePathsReferencedByMessage(message);
|
||||
await Promise.all(
|
||||
[...externalAttachments].map(attachmentPath =>
|
||||
maybeDeleteAttachmentFile(attachmentPath)
|
||||
)
|
||||
);
|
||||
await Promise.all(
|
||||
[...externalDownloads].map(downloadPath => deleteDownloadFile(downloadPath))
|
||||
);
|
||||
};
|
||||
|
||||
export async function cleanupAttachmentFiles(
|
||||
attachment: AttachmentType
|
||||
): Promise<void> {
|
||||
const result = getFilePathsReferencedByAttachment(attachment);
|
||||
await Promise.all(
|
||||
[...result.externalAttachments].map(maybeDeleteAttachmentFile)
|
||||
);
|
||||
await Promise.all([...result.externalDownloads].map(deleteDownloadFile));
|
||||
}
|
||||
|
||||
@@ -11,13 +11,16 @@ import type { ConversationModel } from '../models/conversations.preload.js';
|
||||
import type { AddressableMessage } from '../textsecure/messageReceiverEvents.std.js';
|
||||
import type { AttachmentType } from '../types/Attachment.std.js';
|
||||
import { MessageModel } from '../models/messages.preload.js';
|
||||
import { cleanupMessages, postSaveUpdates } from './cleanup.preload.js';
|
||||
import {
|
||||
cleanupMessages,
|
||||
cleanupAttachmentFiles,
|
||||
postSaveUpdates,
|
||||
} from './cleanup.preload.js';
|
||||
import {
|
||||
findMatchingMessage,
|
||||
getMessageQueryFromTarget,
|
||||
} from './syncIdentifiers.preload.js';
|
||||
import { itemStorage } from '../textsecure/Storage.preload.js';
|
||||
import { cleanupAttachmentFiles } from '../types/Message2.preload.js';
|
||||
|
||||
const { last, sortBy } = lodash;
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright 2026 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { ConversationType } from '../state/ducks/conversations.preload.js';
|
||||
import { CallMode } from '../types/CallDisposition.std.js';
|
||||
|
||||
export const getConversationCallMode = (
|
||||
conversation: ConversationType
|
||||
): CallMode | null => {
|
||||
if (
|
||||
conversation.left ||
|
||||
conversation.isBlocked ||
|
||||
conversation.isMe ||
|
||||
!conversation.acceptedMessageRequest
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (conversation.type === 'direct') {
|
||||
return CallMode.Direct;
|
||||
}
|
||||
|
||||
if (conversation.type === 'group' && conversation.groupVersion === 2) {
|
||||
return CallMode.Group;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
@@ -53,11 +53,7 @@ import {
|
||||
UnknownRecipientError,
|
||||
UnregisteredUserError,
|
||||
} from '../textsecure/Errors.std.js';
|
||||
import {
|
||||
IdentityKeys,
|
||||
SenderKeys,
|
||||
Sessions,
|
||||
} from '../LibSignalStores.preload.js';
|
||||
import { IdentityKeys, SenderKeys, Sessions } from '../LibSignalStores.node.js';
|
||||
import type { ConversationModel } from '../models/conversations.preload.js';
|
||||
import type { DeviceType, CallbackResultType } from '../textsecure/Types.d.ts';
|
||||
import { getKeysForServiceId } from '../textsecure/getKeysForServiceId.preload.js';
|
||||
@@ -1297,6 +1293,7 @@ async function encryptForSenderKey({
|
||||
);
|
||||
const ourAddress = getOurAddress();
|
||||
const senderKeyStore = new SenderKeys({
|
||||
signalProtocolStore,
|
||||
ourServiceId: ourAci,
|
||||
zone: GLOBAL_ZONE,
|
||||
});
|
||||
@@ -1341,8 +1338,14 @@ async function encryptForSenderKey({
|
||||
.map(device => {
|
||||
return ProtocolAddress.new(device.serviceId, device.id);
|
||||
});
|
||||
const identityKeyStore = new IdentityKeys({ ourServiceId: ourAci });
|
||||
const sessionStore = new Sessions({ ourServiceId: ourAci });
|
||||
const identityKeyStore = new IdentityKeys({
|
||||
signalProtocolStore,
|
||||
ourServiceId: ourAci,
|
||||
});
|
||||
const sessionStore = new Sessions({
|
||||
signalProtocolStore,
|
||||
ourServiceId: ourAci,
|
||||
});
|
||||
return sealedSenderMultiRecipientEncrypt(
|
||||
content,
|
||||
recipients,
|
||||
|
||||
Reference in New Issue
Block a user