signal-desktop/ts/services/writeProfile.ts

108 lines
3.1 KiB
TypeScript
Raw Normal View History

// Copyright 2021-2022 Signal Messenger, LLC
2021-07-19 19:26:06 +00:00
// SPDX-License-Identifier: AGPL-3.0-only
import dataInterface from '../sql/Client';
import type { ConversationType } from '../state/ducks/conversations';
2022-01-26 21:58:00 +00:00
import * as Errors from '../types/errors';
import * as log from '../logging/log';
import { computeHash } from '../Crypto';
2021-07-19 19:26:06 +00:00
import { encryptProfileData } from '../util/encryptProfileData';
import { getProfile } from '../util/getProfile';
import { singleProtoJobQueue } from '../jobs/singleProtoJobQueue';
2022-01-26 21:58:00 +00:00
import { strictAssert } from '../util/assert';
import { isWhitespace } from '../util/whitespaceStringUtil';
2021-07-19 19:26:06 +00:00
export async function writeProfile(
conversation: ConversationType,
2021-09-24 00:49:05 +00:00
avatarBuffer?: Uint8Array
2021-07-19 19:26:06 +00:00
): Promise<void> {
// Before we write anything we request the user's profile so that we can
// have an up-to-date paymentAddress to be able to include it when we write
const model = window.ConversationController.get(conversation.id);
if (!model) {
return;
}
await getProfile(model.get('uuid'), model.get('e164'));
2021-07-19 19:26:06 +00:00
// Encrypt the profile data, update profile, and if needed upload the avatar
const {
aboutEmoji,
aboutText,
avatarHash,
avatarPath,
familyName,
firstName,
} = conversation;
2022-01-26 21:58:00 +00:00
strictAssert(
!isWhitespace(String(conversation.firstName)),
'writeProfile: Cannot set an empty profile name'
);
2021-07-19 19:26:06 +00:00
const [profileData, encryptedAvatarData] = await encryptProfileData(
conversation,
2021-08-06 00:17:05 +00:00
avatarBuffer
2021-07-19 19:26:06 +00:00
);
const avatarRequestHeaders = await window.textsecure.messaging.putProfile(
profileData
);
// Upload the avatar if provided
// delete existing files on disk if avatar has been removed
// update the account's avatar path and hash if it's a new avatar
let profileAvatar:
| {
hash: string;
path: string;
}
| undefined;
2021-08-06 00:17:05 +00:00
if (avatarRequestHeaders && encryptedAvatarData && avatarBuffer) {
2021-07-19 19:26:06 +00:00
await window.textsecure.messaging.uploadAvatar(
avatarRequestHeaders,
encryptedAvatarData
);
2021-08-06 00:17:05 +00:00
const hash = await computeHash(avatarBuffer);
2021-07-19 19:26:06 +00:00
if (hash !== avatarHash) {
const [path] = await Promise.all([
2021-08-06 00:17:05 +00:00
window.Signal.Migrations.writeNewAttachmentData(avatarBuffer),
2021-07-19 19:26:06 +00:00
avatarPath
? window.Signal.Migrations.deleteAttachmentData(avatarPath)
: undefined,
]);
profileAvatar = {
hash,
path,
};
}
} else if (avatarPath) {
await window.Signal.Migrations.deleteAttachmentData(avatarPath);
}
const profileAvatarData = profileAvatar ? { profileAvatar } : {};
2021-07-19 19:26:06 +00:00
// Update backbone, update DB, run storage service upload
model.set({
about: aboutText,
aboutEmoji,
profileName: firstName,
profileFamilyName: familyName,
...profileAvatarData,
2021-07-19 19:26:06 +00:00
});
dataInterface.updateConversation(model.attributes);
model.captureChange('writeProfile');
try {
await singleProtoJobQueue.add(
window.textsecure.messaging.getFetchLocalProfileSyncMessage()
);
} catch (error) {
log.error(
'writeProfile: Failed to queue sync message',
Errors.toLogFormat(error)
);
}
2021-07-19 19:26:06 +00:00
}