diff --git a/app/sql.js b/app/sql.js index 7cb0bb7d9..c953fd0c5 100644 --- a/app/sql.js +++ b/app/sql.js @@ -72,7 +72,6 @@ module.exports = { removeContactSignedPreKeyByIdentityKey, removeAllContactSignedPreKeys, - createOrUpdateItem, getItemById, getAllItems, @@ -906,7 +905,6 @@ async function updateToLokiSchemaVersion3(currentVersion, instance) { const SENDER_KEYS_TABLE = 'senderKeys'; - async function removeAllClosedGroupRatchets(groupId) { await db.run(`DELETE FROM ${SENDER_KEYS_TABLE} WHERE groupId = $groupId;`, { $groupId: groupId, @@ -1550,7 +1548,6 @@ async function removeAllSignedPreKeys() { return removeAllFromTable(SIGNED_PRE_KEYS_TABLE); } - const GUARD_NODE_TABLE = 'guardNodes'; async function getGuardNodes() { diff --git a/js/background.js b/js/background.js index c13e06d88..47fc03cbc 100644 --- a/js/background.js +++ b/js/background.js @@ -2,7 +2,6 @@ $, _, Backbone, - getAccountManager, Signal, storage, textsecure, @@ -481,9 +480,7 @@ if (Whisper.Import.isIncomplete()) { window.log.info('Import was interrupted, showing import error screen'); appView.openImporter(); - } else if ( - Whisper.Registration.isDone() - ) { + } else if (Whisper.Registration.isDone()) { connect(); appView.openInbox({ initialLoadComplete, diff --git a/js/delivery_receipts.js b/js/delivery_receipts.js index 28b62611f..fad68e824 100644 --- a/js/delivery_receipts.js +++ b/js/delivery_receipts.js @@ -34,17 +34,20 @@ return null; } - const message = messages.find( - item => !item.isIncoming() && originalSource === item.get('conversationId') + item => + !item.isIncoming() && originalSource === item.get('conversationId') ); if (message) { return message; } - const groups = await window.Signal.Data.getAllGroupsInvolvingId(originalSource, { - ConversationCollection: Whisper.ConversationCollection, - }); + const groups = await window.Signal.Data.getAllGroupsInvolvingId( + originalSource, + { + ConversationCollection: Whisper.ConversationCollection, + } + ); const ids = groups.pluck('id'); ids.push(originalSource); diff --git a/js/models/conversations.js b/js/models/conversations.js index 1ce776f53..098d5c32b 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -921,8 +921,6 @@ } }, - - async updateExpirationTimer( providedExpireTimer, providedSource, diff --git a/js/models/messages.js b/js/models/messages.js index 6a20ecbac..35f804f16 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -990,7 +990,7 @@ // Special-case the self-send case - we send only a sync message if (recipients.length === 1) { - const isOurDevice = await libsession.Utils.UserUtil.isUs( + const isOurDevice = await libsession.Utils.UserUtils.isUs( recipients[0] ); if (isOurDevice) { @@ -1102,7 +1102,7 @@ async handleMessageSentSuccess(sentMessage, wrappedEnvelope) { let sentTo = this.get('sent_to') || []; - const isOurDevice = await window.libsession.Utils.UserUtil.isUs( + const isOurDevice = await window.libsession.Utils.UserUtils.isUs( sentMessage.device ); // FIXME this is not correct and will cause issues with syncing @@ -1201,7 +1201,7 @@ await c.getProfiles(); } } - const isOurDevice = await window.libsession.Utils.UserUtil.isUs( + const isOurDevice = await window.libsession.Utils.UserUtils.isUs( sentMessage.device ); const expirationStartTimestamp = Date.now(); @@ -1366,12 +1366,14 @@ await this.sendSyncMessage(data); }, - async sendSyncMessage(dataMessage) { + async sendSyncMessage(/* dataMessage */) { if (this.get('synced') || this.get('sentSync')) { return; } - window.log.error('sendSyncMessage to upgrade to multi device protocol v2') + window.log.error( + 'sendSyncMessage to upgrade to multi device protocol v2' + ); // const data = // dataMessage instanceof libsession.Messages.Outgoing.DataMessage diff --git a/js/modules/data.js b/js/modules/data.js index 5193850de..e9a64f70b 100644 --- a/js/modules/data.js +++ b/js/modules/data.js @@ -1,4 +1,4 @@ -/* global window, setTimeout, clearTimeout, IDBKeyRange, dcodeIO */ +/* global window, setTimeout, clearTimeout, IDBKeyRange */ const electron = require('electron'); const { ipcRenderer } = electron; @@ -598,7 +598,6 @@ async function removeAllContactSignedPreKeys() { await channels.removeAllContactSignedPreKeys(); } - function getGuardNodes() { return channels.getGuardNodes(); } diff --git a/js/modules/loki_app_dot_net_api.js b/js/modules/loki_app_dot_net_api.js index b6f70bed6..03d68f80c 100644 --- a/js/modules/loki_app_dot_net_api.js +++ b/js/modules/loki_app_dot_net_api.js @@ -1862,137 +1862,11 @@ class LokiPublicChannelAPI { return; } - // slave to primary map for this group of messages - let slavePrimaryMap = {}; - - // reduce list of servers into verified maps and keys - const verifiedPrimaryPKs = await Object.keys(homeServerPubKeys).reduce( - async (curVal, serverUrl) => { - // get an API to this server - const serverAPI = await window.lokiFileServerAPIFactory.establishConnection( - serverUrl - ); - - // get list of verified primary PKs - const result = await serverAPI.verifyPrimaryPubKeys( - homeServerPubKeys[serverUrl] - ); - - // merged these device mappings into our slavePrimaryMap - // should not be any collisions, since each pubKey can only have one home server - slavePrimaryMap = { ...slavePrimaryMap, ...result.slaveMap }; - - // copy verified pub keys into result - return curVal.concat(result.verifiedPrimaryPKs); - }, - [] - ); - // filter out invalid messages pendingMessages = pendingMessages.filter(messageData => !!messageData); - // separate messages coming from primary and secondary devices - let [primaryMessages, slaveMessages] = _.partition( - pendingMessages, - message => !(message.source in slavePrimaryMap) - ); - // get minimum ID for primaryMessages and slaveMessages - const firstPrimaryId = _.min(primaryMessages.map(msg => msg.serverId)); - const firstSlaveId = _.min(slaveMessages.map(msg => msg.serverId)); - if (firstPrimaryId < firstSlaveId) { - // early send - // split off count from pendingMessages - let sendNow = []; - [sendNow, pendingMessages] = _.partition( - pendingMessages, - message => message.serverId < firstSlaveId - ); - sendNow.forEach(message => { - // send them out now - log.info( - 'emitting primary message', - message.serverId, - 'on', - this.channelId, - 'at', - this.serverAPI.baseServerUrl - ); - this.chatAPI.emit('publicMessage', { - message, - }); - }); - - sendNow = false; - } - primaryMessages = false; // free memory - - // get actual chat server data (mainly the name rn) of primary device - const verifiedDeviceResults = await this.serverAPI.getUsers( - verifiedPrimaryPKs - ); - - // build map of userProfileName to primaryKeys - /* eslint-disable no-param-reassign */ - this.primaryUserProfileName = verifiedDeviceResults.reduce( - (mapOut, user) => { - let avatar = null; - let profileKey = null; - const avatarNote = user.annotations.find( - note => note.type === AVATAR_USER_ANNOTATION_TYPE - ); - if (avatarNote) { - ({ profileKey, url: avatar } = avatarNote.value); - } - mapOut[user.username] = { - name: user.name, - avatar, - profileKey, - }; - return mapOut; - }, - {} - ); - /* eslint-enable no-param-reassign */ - - // process remaining messages - /* eslint-disable no-param-reassign */ - slaveMessages.forEach(messageData => { - const slaveKey = messageData.source; - - // prevent our own device sent messages from coming back in - if (slaveKey === ourNumberDevice) { - // we originally sent these - return; - } - - // look up primary device once - const primaryPubKey = slavePrimaryMap[slaveKey]; - - // send out remaining messages for this merged identity - /* eslint-disable no-param-reassign */ - if (slavePrimaryMap[slaveKey]) { - // rewrite source, profile - messageData.source = primaryPubKey; - const primaryProfile = this.primaryUserProfileName[primaryPubKey]; - if (primaryProfile) { - const { name, avatar, profileKey } = primaryProfile; - messageData.message.profile.displayName = name; - messageData.message.profile.avatar = avatar; - messageData.message.profileKey = profileKey; - } - } - }); - slaveMessages = false; // free memory // process all messages in the order received pendingMessages.forEach(message => { - // if slave device - if (message.source in slavePrimaryMap) { - // prevent our own device sent messages from coming back in - if (message.source === ourNumberDevice) { - // we originally sent these - return; - } - } if (this.running) { log.info( 'emitting pending message', diff --git a/js/modules/loki_file_server_api.js b/js/modules/loki_file_server_api.js index 45d72fa24..cc6673952 100644 --- a/js/modules/loki_file_server_api.js +++ b/js/modules/loki_file_server_api.js @@ -1,9 +1,8 @@ -/* global log, libloki, window */ +/* global log, window */ /* global log: false */ const LokiAppDotNetAPI = require('./loki_app_dot_net_api'); - // can have multiple of these instances as each user can have a // different home server class LokiFileServerInstance { diff --git a/libtextsecure/account_manager.js b/libtextsecure/account_manager.js index e41f8012a..b4f459517 100644 --- a/libtextsecure/account_manager.js +++ b/libtextsecure/account_manager.js @@ -2,16 +2,12 @@ window, textsecure, libsignal, - libloki, - libsession, - lokiFileServerAPI, mnemonic, btoa, getString, Event, dcodeIO, StringView, - log, Event, Whisper */ @@ -146,7 +142,6 @@ store.clearPreKeyStore(), store.clearSignedPreKeysStore(), ]); - }, async generateMnemonic(language = 'english') { // Note: 4 bytes are converted into 3 seed words, so length 12 seed words @@ -166,7 +161,7 @@ window.log.info('registration done'); textsecure.storage.put('primaryDevicePubKey', number); - + // Ensure that we always have a conversation for ourself const conversation = await window .getConversationController() diff --git a/stylesheets/_session_left_pane.scss b/stylesheets/_session_left_pane.scss index 115b6cd36..c30d9dcc2 100644 --- a/stylesheets/_session_left_pane.scss +++ b/stylesheets/_session_left_pane.scss @@ -469,6 +469,12 @@ $session-compose-margin: 20px; .left-pane-setting { &-bottom-buttons { @include bottom-buttons(); + + .session-button { + vertical-align: middle; + white-space: normal; + text-align: center; + } } &-content, diff --git a/ts/components/conversation/AddMentions.tsx b/ts/components/conversation/AddMentions.tsx index aebbc601a..b9c13962c 100644 --- a/ts/components/conversation/AddMentions.tsx +++ b/ts/components/conversation/AddMentions.tsx @@ -2,9 +2,10 @@ import React from 'react'; import { RenderTextCallbackType } from '../../types/Util'; import classNames from 'classnames'; -import { FindMember, UserUtil } from '../../util'; +import { FindMember } from '../../util'; import { useInterval } from '../../hooks/useInterval'; import { ConversationModel } from '../../../js/models/conversations'; +import { isUs } from '../../session/utils/User'; interface MentionProps { key: string; @@ -24,7 +25,7 @@ const Mention = (props: MentionProps) => { ); if (foundMember) { - const itsUs = await UserUtil.isUs(foundMember.id); + const itsUs = await isUs(foundMember.id); setUs(itsUs); setFound(foundMember); // FIXME stop this interval once we found it. diff --git a/ts/components/session/ActionsPanel.tsx b/ts/components/session/ActionsPanel.tsx index 96d5df5d2..4f1ae9c43 100644 --- a/ts/components/session/ActionsPanel.tsx +++ b/ts/components/session/ActionsPanel.tsx @@ -10,11 +10,11 @@ import { ConversationType } from '../../state/ducks/conversations'; import { noop } from 'lodash'; import { DefaultTheme } from 'styled-components'; import { StateType } from '../../state/reducer'; -import { UserUtil } from '../../util'; import { ConversationController } from '../../session/conversations'; import { getFocusedSection } from '../../state/selectors/section'; import { getTheme } from '../../state/selectors/theme'; import { getOurNumber } from '../../state/selectors/user'; +import { UserUtils } from '../../session/utils'; // tslint:disable-next-line: no-import-side-effect no-submodule-imports export enum SectionType { @@ -197,7 +197,7 @@ class ActionsPanelPrivate extends React.Component { }; private async showResetSessionIDDialogIfNeeded() { - const userED25519KeyPairHex = await UserUtil.getUserED25519KeyPair(); + const userED25519KeyPairHex = await UserUtils.getUserED25519KeyPair(); if (userED25519KeyPairHex) { return; } diff --git a/ts/components/session/LeftPaneSettingSection.tsx b/ts/components/session/LeftPaneSettingSection.tsx index abd64e14f..352738fa2 100644 --- a/ts/components/session/LeftPaneSettingSection.tsx +++ b/ts/components/session/LeftPaneSettingSection.tsx @@ -140,7 +140,6 @@ export class LeftPaneSettingSection extends React.Component { } public renderBottomButtons(): JSX.Element | undefined { - const dangerButtonText = window.i18n('clearAllData'); const showRecoveryPhrase = window.i18n('showRecoveryPhrase'); @@ -152,7 +151,7 @@ export class LeftPaneSettingSection extends React.Component { buttonColor={SessionButtonColor.Danger} onClick={this.onDeleteAccount} /> - + { } public onDeleteAccount() { - const title = window.i18n('clearAllData'); const message = window.i18n('unpairDeviceWarning'); diff --git a/ts/components/session/RegistrationTabs.tsx b/ts/components/session/RegistrationTabs.tsx index 2eef2b6a1..259ba7317 100644 --- a/ts/components/session/RegistrationTabs.tsx +++ b/ts/components/session/RegistrationTabs.tsx @@ -410,7 +410,7 @@ export class RegistrationTabs extends React.Component { ); } - + if (signUpMode === SignUpMode.EnterDetails) { return (
diff --git a/ts/components/session/SessionInboxView.tsx b/ts/components/session/SessionInboxView.tsx index cc4f9b73f..0ea6f8fb1 100644 --- a/ts/components/session/SessionInboxView.tsx +++ b/ts/components/session/SessionInboxView.tsx @@ -102,11 +102,7 @@ export class SessionInboxView extends React.Component { const category = this.state.settingsCategory || SessionSettingCategory.Appearance; - return ( - - ); + return ; } private renderSessionConversation() { diff --git a/ts/components/session/conversation/SessionConversation.tsx b/ts/components/session/conversation/SessionConversation.tsx index d30cb516f..13adc82ed 100644 --- a/ts/components/session/conversation/SessionConversation.tsx +++ b/ts/components/session/conversation/SessionConversation.tsx @@ -11,7 +11,7 @@ import { import { Constants } from '../../../session'; import _ from 'lodash'; -import { AttachmentUtil, GoogleChrome, UserUtil } from '../../../util'; +import { AttachmentUtil, GoogleChrome } from '../../../util'; import { ConversationHeaderWithDetails } from '../../conversation/ConversationHeader'; import { SessionRightPanelWithDetails } from './SessionRightPanel'; import { SessionTheme } from '../../../state/ducks/SessionTheme'; @@ -21,7 +21,7 @@ import { LightboxGallery, MediaItemType } from '../../LightboxGallery'; import { Message } from '../../conversation/media-gallery/types/Message'; import { AttachmentType, save } from '../../../types/Attachment'; -import { ToastUtils } from '../../../session/utils'; +import { ToastUtils, UserUtils } from '../../../session/utils'; import * as MIME from '../../../types/MIME'; import { SessionFileDropzone } from './SessionFileDropzone'; import { ConversationType } from '../../../state/ducks/conversations'; @@ -682,14 +682,15 @@ export class SessionConversation extends React.Component { if (selectedConversation.isPublic) { // Get our Moderator status - const ourDevicePubkey = await UserUtil.getCurrentDevicePubKey(); + const ourDevicePubkey = await UserUtils.getCurrentDevicePubKey(); if (!ourDevicePubkey) { return; } const isAdmin = conversationModel.isAdmin(ourDevicePubkey); - const isAllOurs = selectedMessages.every(message => - ourDevicePubkey === message.attributes.source); + const isAllOurs = selectedMessages.every( + message => ourDevicePubkey === message.attributes.source + ); if (!isAllOurs && !isAdmin) { ToastUtils.pushMessageDeleteForbidden(); diff --git a/ts/components/session/settings/SessionSettings.tsx b/ts/components/session/settings/SessionSettings.tsx index 7f75241ce..0ea3e995c 100644 --- a/ts/components/session/settings/SessionSettings.tsx +++ b/ts/components/session/settings/SessionSettings.tsx @@ -7,11 +7,9 @@ import { SessionButtonColor, SessionButtonType, } from '../SessionButton'; -import { BlockedNumberController, UserUtil } from '../../../util'; +import { BlockedNumberController } from '../../../util'; import { ToastUtils } from '../../../session/utils'; -import { - ConversationLookupType, -} from '../../../state/ducks/conversations'; +import { ConversationLookupType } from '../../../state/ducks/conversations'; import { StateType } from '../../../state/reducer'; import { ConversationController } from '../../../session/conversations'; import { @@ -102,7 +100,7 @@ class SettingsViewInner extends React.Component { const { category } = this.props; let settings: Array; - + if (category === SessionSettingCategory.Blocked) { // special case for blocked user settings = this.getBlockedUserSettings(); @@ -633,7 +631,6 @@ class SettingsViewInner extends React.Component { return results; } - private async onKeyUp(event: any) { const lockPasswordFocussed = ($('#password-lock-input') as any).is( ':focus' diff --git a/ts/components/session/settings/SessionSettingsHeader.tsx b/ts/components/session/settings/SessionSettingsHeader.tsx index e0f711879..828b9b43d 100644 --- a/ts/components/session/settings/SessionSettingsHeader.tsx +++ b/ts/components/session/settings/SessionSettingsHeader.tsx @@ -3,7 +3,9 @@ import { SettingsViewProps } from './SessionSettings'; import { DefaultTheme, withTheme } from 'styled-components'; interface Props extends SettingsViewProps { + // tslint:disable-next-line: react-unused-props-and-state categoryTitle: string; + // tslint:disable-next-line: react-unused-props-and-state theme: DefaultTheme; } @@ -14,6 +16,6 @@ const SettingsHeaderInner = (props: Props) => {
{categoryTitle}
); -} +}; export const SettingsHeader = withTheme(SettingsHeaderInner); diff --git a/ts/components/session/usingClosedConversationDetails.tsx b/ts/components/session/usingClosedConversationDetails.tsx index 3213a52a6..7f69780dc 100644 --- a/ts/components/session/usingClosedConversationDetails.tsx +++ b/ts/components/session/usingClosedConversationDetails.tsx @@ -1,5 +1,4 @@ -import { GroupUtils } from '../../session/utils'; -import { UserUtil } from '../../util'; +import { GroupUtils, UserUtils } from '../../session/utils'; import { PubKey } from '../../session/types'; import React from 'react'; import * as _ from 'lodash'; @@ -56,7 +55,9 @@ export function usingClosedConversationDetails(WrappedComponent: any) { (conversationType === 'group' || type === 'group' || isGroup) ) { const groupId = id || phoneNumber; - const ourPrimary = PubKey.cast(await UserUtil.getCurrentDevicePubKey()); + const ourPrimary = PubKey.cast( + await UserUtils.getCurrentDevicePubKey() + ); let members = await GroupUtils.getGroupMembers(PubKey.cast(groupId)); const ourself = members.find(m => m.key !== ourPrimary.key); diff --git a/ts/receiver/closedGroupsV2.ts b/ts/receiver/closedGroupsV2.ts index 5d4ed5feb..711652945 100644 --- a/ts/receiver/closedGroupsV2.ts +++ b/ts/receiver/closedGroupsV2.ts @@ -2,10 +2,10 @@ import { SignalService } from '../protobuf'; import { removeFromCache } from './cache'; import { EnvelopePlus } from './types'; import { PubKey } from '../session/types'; -import { fromHexToArray, toHex } from '../session/utils/String'; +import { toHex } from '../session/utils/String'; import { ConversationController } from '../session/conversations'; import * as ClosedGroupV2 from '../session/groupv2'; -import { BlockedNumberController, UserUtil } from '../util'; +import { BlockedNumberController } from '../util'; import { generateClosedGroupV2PublicKey, generateCurve25519KeyPairWithoutPrefix, @@ -18,55 +18,9 @@ import { ClosedGroupV2NewMessageParams, } from '../session/messages/outgoing/content/data/groupv2/ClosedGroupV2NewMessage'; -import { KeyPair } from '../../libtextsecure/libsignal-protocol'; -import { getOurNumber } from '../util/user'; - -export type HexKeyPair = { - publicHex: string; - privateHex: string; -}; - -export class ECKeyPair { - public readonly publicKeyData: Uint8Array; - public readonly privateKeyData: Uint8Array; - - constructor(publicKeyData: Uint8Array, privateKeyData: Uint8Array) { - this.publicKeyData = publicKeyData; - this.privateKeyData = privateKeyData; - } - - public static fromArrayBuffer(pub: ArrayBuffer, priv: ArrayBuffer) { - return new ECKeyPair(new Uint8Array(pub), new Uint8Array(priv)); - } - - public static fromKeyPair(pair: KeyPair) { - return new ECKeyPair( - new Uint8Array(pair.pubKey), - new Uint8Array(pair.privKey) - ); - } - - public static fromHexKeyPair(pair: HexKeyPair) { - return new ECKeyPair( - fromHexToArray(pair.publicHex), - fromHexToArray(pair.privateHex) - ); - } - - public toString() { - const hexKeypair = this.toHexKeyPair(); - return `ECKeyPair: ${hexKeypair.publicHex} ${hexKeypair.privateHex}`; - } - - public toHexKeyPair(): HexKeyPair { - const publicHex = toHex(this.publicKeyData); - const privateHex = toHex(this.privateKeyData); - return { - publicHex, - privateHex, - }; - } -} +import { ECKeyPair } from './keypairs'; +import { getOurNumber } from '../session/utils/User'; +import { UserUtils } from '../session/utils'; export async function handleClosedGroupV2( envelope: EnvelopePlus, @@ -161,7 +115,9 @@ async function handleNewClosedGroupV2( ) { const { log } = window; - if (groupUpdate.type !== SignalService.DataMessage.ClosedGroupUpdateV2.Type.NEW) { + if ( + groupUpdate.type !== SignalService.DataMessage.ClosedGroupUpdateV2.Type.NEW + ) { return; } if (!sanityCheckNewGroupV2(groupUpdate)) { @@ -182,7 +138,7 @@ async function handleNewClosedGroupV2( const members = membersAsData.map(toHex); const admins = adminsAsData.map(toHex); - const ourPrimary = await UserUtil.getOurNumber(); + const ourPrimary = await UserUtils.getOurNumber(); if (!members.includes(ourPrimary.key)) { log.info( 'Got a new group message but apparently we are not a member of it. Dropping it.' @@ -263,7 +219,10 @@ async function handleUpdateClosedGroupV2( envelope: EnvelopePlus, groupUpdate: SignalService.DataMessage.ClosedGroupUpdateV2 ) { - if (groupUpdate.type !== SignalService.DataMessage.ClosedGroupUpdateV2.Type.UPDATE) { + if ( + groupUpdate.type !== + SignalService.DataMessage.ClosedGroupUpdateV2.Type.UPDATE + ) { return; } const { name, members: membersBinary } = groupUpdate; @@ -317,7 +276,7 @@ async function handleUpdateClosedGroupV2( const diff = ClosedGroupV2.buildGroupDiff(convo, { name, members }); // Check whether we are still in the group - const ourNumber = await UserUtil.getOurNumber(); + const ourNumber = await UserUtils.getOurNumber(); const wasCurrentUserRemoved = !members.includes(ourNumber.key); const isCurrentUserAdmin = curAdmins?.includes(ourNumber.key); @@ -391,9 +350,9 @@ async function handleKeyPairClosedGroupV2( ) { return; } - const ourNumber = await UserUtil.getOurNumber(); + const ourNumber = await UserUtils.getOurNumber(); const groupPublicKey = envelope.source; - const ourKeyPair = await UserUtil.getIdentityKeyPair(); + const ourKeyPair = await UserUtils.getIdentityKeyPair(); if (!ourKeyPair) { window.log.warn("Couldn't find user X25519 key pair."); @@ -455,7 +414,9 @@ async function handleKeyPairClosedGroupV2( // Parse it let proto: SignalService.DataMessage.ClosedGroupUpdateV2.KeyPair; try { - proto = SignalService.DataMessage.ClosedGroupUpdateV2.KeyPair.decode(plaintext); + proto = SignalService.DataMessage.ClosedGroupUpdateV2.KeyPair.decode( + plaintext + ); if ( !proto || proto.privateKey.length === 0 || diff --git a/ts/receiver/common.ts b/ts/receiver/common.ts index 2b1a86f5d..570b2ade4 100644 --- a/ts/receiver/common.ts +++ b/ts/receiver/common.ts @@ -3,9 +3,9 @@ import { EnvelopePlus } from './types'; export function getEnvelopeId(envelope: EnvelopePlus) { if (envelope.source) { - return `${envelope.source} ${toNumber( - envelope.timestamp - )} (${envelope.id})`; + return `${envelope.source} ${toNumber(envelope.timestamp)} (${ + envelope.id + })`; } return envelope.id; diff --git a/ts/receiver/contentMessage.ts b/ts/receiver/contentMessage.ts index a0d5aa9dc..3c477d847 100644 --- a/ts/receiver/contentMessage.ts +++ b/ts/receiver/contentMessage.ts @@ -8,13 +8,12 @@ import * as Lodash from 'lodash'; import { PubKey } from '../session/types'; import { BlockedNumberController } from '../util/blockedNumberController'; -import { GroupUtils } from '../session/utils'; -import { UserUtil } from '../util'; +import { GroupUtils, UserUtils } from '../session/utils'; import { fromHexToArray, toHex } from '../session/utils/String'; import { concatUInt8Array, getSodium } from '../session/crypto'; import { ConversationController } from '../session/conversations'; import * as Data from '../../js/modules/data'; -import { ECKeyPair } from './closedGroupsV2'; +import { ECKeyPair } from './keypairs'; export async function handleContentMessage(envelope: EnvelopePlus) { try { @@ -91,7 +90,7 @@ async function decryptForClosedGroupV2( ); } window.log.info('ClosedGroupV2 Message decrypted successfully.'); - const ourDevicePubKey = await UserUtil.getCurrentDevicePubKey(); + const ourDevicePubKey = await UserUtils.getCurrentDevicePubKey(); if ( envelope.senderIdentity && @@ -221,7 +220,7 @@ async function decryptUnidentifiedSender( ): Promise { window.log.info('received unidentified sender message'); try { - const userX25519KeyPair = await UserUtil.getIdentityKeyPair(); + const userX25519KeyPair = await UserUtils.getIdentityKeyPair(); if (!userX25519KeyPair) { throw new Error('Failed to find User x25519 keypair from stage'); // noUserX25519KeyPair } diff --git a/ts/receiver/dataMessage.ts b/ts/receiver/dataMessage.ts index cb4dbc06f..33f408e76 100644 --- a/ts/receiver/dataMessage.ts +++ b/ts/receiver/dataMessage.ts @@ -8,12 +8,12 @@ import { PubKey } from '../session/types'; import { handleMessageJob } from './queuedJob'; import { downloadAttachment } from './attachments'; import _ from 'lodash'; -import { StringUtils } from '../session/utils'; +import { StringUtils, UserUtils } from '../session/utils'; import { DeliveryReceiptMessage } from '../session/messages/outgoing'; import { getMessageQueue } from '../session'; import { ConversationController } from '../session/conversations'; import { handleClosedGroupV2 } from './closedGroupsV2'; -import { UserUtil } from '../util'; +import { isUs } from '../session/utils/User'; export async function updateProfile( conversation: any, @@ -30,7 +30,8 @@ export async function updateProfile( // TODO: may need to allow users to reset their avatars to null if (profile.profilePicture) { const prevPointer = conversation.get('avatarPointer'); - const needsUpdate = !prevPointer || !_.isEqual(prevPointer, profile.profilePicture); + const needsUpdate = + !prevPointer || !_.isEqual(prevPointer, profile.profilePicture); if (needsUpdate) { conversation.set('avatarPointer', profile.profilePicture); @@ -276,7 +277,7 @@ export async function handleDataMessage( } const source = envelope.senderIdentity || senderPubKey; - const ownDevice = await UserUtil.isUs(source); + const ownDevice = await isUs(source); const ownMessage = conversation?.isMediumGroup() && ownDevice; @@ -563,8 +564,6 @@ export async function handleMessageEvent(event: MessageEvent): Promise { type, isIncoming ); - confirm(); - return; } const msg = createMessage(data, isIncoming); @@ -578,7 +577,7 @@ export async function handleMessageEvent(event: MessageEvent): Promise { } // TODO: this shouldn't be called when source is not a pubkey!!! - const isOurDevice = await UserUtil.isUs(source); + const isOurDevice = await UserUtils.isUs(source); const shouldSendReceipt = isIncoming && @@ -628,7 +627,7 @@ export async function handleMessageEvent(event: MessageEvent): Promise { message, ourNumber, confirm, - source, + source ).ignore(); }); } diff --git a/ts/receiver/keypairs.ts b/ts/receiver/keypairs.ts new file mode 100644 index 000000000..1af3b814d --- /dev/null +++ b/ts/receiver/keypairs.ts @@ -0,0 +1,49 @@ +import { KeyPair } from '../../libtextsecure/libsignal-protocol'; +import { fromHexToArray, toHex } from '../session/utils/String'; + +export type HexKeyPair = { + publicHex: string; + privateHex: string; +}; + +export class ECKeyPair { + public readonly publicKeyData: Uint8Array; + public readonly privateKeyData: Uint8Array; + + constructor(publicKeyData: Uint8Array, privateKeyData: Uint8Array) { + this.publicKeyData = publicKeyData; + this.privateKeyData = privateKeyData; + } + + public static fromArrayBuffer(pub: ArrayBuffer, priv: ArrayBuffer) { + return new ECKeyPair(new Uint8Array(pub), new Uint8Array(priv)); + } + + public static fromKeyPair(pair: KeyPair) { + return new ECKeyPair( + new Uint8Array(pair.pubKey), + new Uint8Array(pair.privKey) + ); + } + + public static fromHexKeyPair(pair: HexKeyPair) { + return new ECKeyPair( + fromHexToArray(pair.publicHex), + fromHexToArray(pair.privateHex) + ); + } + + public toString() { + const hexKeypair = this.toHexKeyPair(); + return `ECKeyPair: ${hexKeypair.publicHex} ${hexKeypair.privateHex}`; + } + + public toHexKeyPair(): HexKeyPair { + const publicHex = toHex(this.publicKeyData); + const privateHex = toHex(this.privateKeyData); + return { + publicHex, + privateHex, + }; + } +} diff --git a/ts/receiver/queuedJob.ts b/ts/receiver/queuedJob.ts index 195585532..d9b8f16f2 100644 --- a/ts/receiver/queuedJob.ts +++ b/ts/receiver/queuedJob.ts @@ -6,9 +6,8 @@ import { MessageModel } from '../../js/models/messages'; import { PubKey } from '../session/types'; import _ from 'lodash'; import { SignalService } from '../protobuf'; -import { StringUtils } from '../session/utils'; +import { StringUtils, UserUtils } from '../session/utils'; import { ConversationController } from '../session/conversations'; -import { UserUtil } from '../util'; async function handleGroups( conversation: ConversationModel, @@ -54,9 +53,7 @@ async function handleGroups( // Check if anyone got kicked: const removedMembers = _.difference(oldMembers, attributes.members); const isOurDeviceMap = await Promise.all( - removedMembers.map(async member => - UserUtil.isUs(member) - ) + removedMembers.map(async member => UserUtils.isUs(member)) ); const ourDeviceWasRemoved = isOurDeviceMap.includes(true); @@ -67,7 +64,7 @@ async function handleGroups( groupUpdate.kicked = removedMembers; } } else if (group.type === GROUP_TYPES.QUIT) { - if (await UserUtil.isUs(source)) { + if (await UserUtils.isUs(source)) { attributes.left = true; groupUpdate = { left: 'You' }; } else { @@ -356,7 +353,7 @@ async function handleRegularMessage( message: MessageModel, initialMessage: any, source: string, - ourNumber: string, + ourNumber: string ) { const { upgradeMessageSchema } = window.Signal.Migrations; @@ -413,7 +410,7 @@ async function handleRegularMessage( conversation ); - const ourPubKey = PubKey.cast(ourNumber) + const ourPubKey = PubKey.cast(ourNumber); handleMentions(message, conversation, ourPubKey); @@ -453,7 +450,7 @@ async function handleRegularMessage( // we just received a message from that user so we reset the typing indicator for this convo conversation.notifyTyping({ isTyping: false, - sender: ourPubKey.key, + sender: source, }); } @@ -495,7 +492,7 @@ export async function handleMessageJob( initialMessage: any, ourNumber: string, confirm: () => void, - source: string, + source: string ) { window.log.info( `Starting handleDataMessage for message ${message.idForLogging()} in conversation ${conversation.idForLogging()}` @@ -527,7 +524,7 @@ export async function handleMessageJob( message, initialMessage, source, - ourNumber, + ourNumber ); } diff --git a/ts/receiver/receiver.ts b/ts/receiver/receiver.ts index 78534fd2d..22bd112be 100644 --- a/ts/receiver/receiver.ts +++ b/ts/receiver/receiver.ts @@ -19,10 +19,9 @@ export { processMessage }; import { handleMessageEvent, updateProfile } from './dataMessage'; import { getEnvelopeId } from './common'; -import { StringUtils } from '../session/utils'; +import { StringUtils, UserUtils } from '../session/utils'; import { SignalService } from '../protobuf'; import { ConversationController } from '../session/conversations'; -import { UserUtil } from '../util'; // TODO: check if some of these exports no longer needed @@ -286,7 +285,7 @@ export async function handleUnencryptedMessage({ message: outerMessage }: any) { await updateProfile(conversation, profile, profileKey); } - const isOurDevice = await UserUtil.isUs(source); + const isOurDevice = await UserUtils.isUs(source); const isPublicChatMessage = group && group.id && !!group.id.match(/^publicChat:/); diff --git a/ts/session/crypto/MessageEncrypter.ts b/ts/session/crypto/MessageEncrypter.ts index 0bb8a7168..211348f58 100644 --- a/ts/session/crypto/MessageEncrypter.ts +++ b/ts/session/crypto/MessageEncrypter.ts @@ -1,13 +1,11 @@ import { EncryptionType } from '../types/EncryptionType'; import { SignalService } from '../../protobuf'; -import { UserUtil } from '../../util'; -import { CipherTextObject } from '../../../libtextsecure/libsignal-protocol'; import { PubKey } from '../types'; import { concatUInt8Array, getSodium } from '.'; import { fromHexToArray } from '../utils/String'; -import { ECKeyPair } from '../../receiver/closedGroupsV2'; export { concatUInt8Array, getSodium }; import { getLatestClosedGroupEncryptionKeyPair } from '../../../js/modules/data'; +import { UserUtils } from '../utils'; /** * Add padding to a message buffer @@ -104,7 +102,7 @@ export async function encryptUsingSessionProtocol( recipientHexEncodedX25519PublicKey: PubKey, plaintext: Uint8Array ): Promise { - const userED25519KeyPairHex = await UserUtil.getUserED25519KeyPair(); + const userED25519KeyPairHex = await UserUtils.getUserED25519KeyPair(); if ( !userED25519KeyPairHex || !userED25519KeyPairHex.pubKey?.length || diff --git a/ts/session/crypto/index.ts b/ts/session/crypto/index.ts index 50cac3635..a19d432dc 100644 --- a/ts/session/crypto/index.ts +++ b/ts/session/crypto/index.ts @@ -5,9 +5,8 @@ export { MessageEncrypter }; // libsodium-wrappers requires the `require` call to work // tslint:disable-next-line: no-require-imports import libsodiumwrappers = require('libsodium-wrappers'); -import { fromHex } from 'bytebuffer'; import { toHex } from '../utils/String'; -import { ECKeyPair } from '../../receiver/closedGroupsV2'; +import { ECKeyPair } from '../../receiver/keypairs'; export async function getSodium(): Promise { await libsodiumwrappers.ready; diff --git a/ts/session/groupv2/index.ts b/ts/session/groupv2/index.ts index e3f695938..a0e3cc8ab 100644 --- a/ts/session/groupv2/index.ts +++ b/ts/session/groupv2/index.ts @@ -3,24 +3,24 @@ import * as Data from '../../../js/modules/data'; import _ from 'lodash'; import { fromHex, fromHexToArray, toHex } from '../utils/String'; -import { UserUtil } from '../../util'; import { MessageModel, MessageModelType } from '../../../js/models/messages'; import { ConversationModel } from '../../../js/models/conversations'; import { BlockedNumberController } from '../../util/blockedNumberController'; import { ConversationController } from '../conversations'; import { updateOpenGroup } from '../../receiver/openGroups'; -import { ECKeyPair } from '../../receiver/closedGroupsV2'; import { getMessageQueue } from '../instance'; import { ClosedGroupV2EncryptionPairMessage, ClosedGroupV2NewMessage, ClosedGroupV2UpdateMessage, ExpirationTimerUpdateMessage, -} from '../messages/outgoing'; +} from '../messages/outgoing/'; import uuid from 'uuid'; import { SignalService } from '../../protobuf'; import { generateCurve25519KeyPairWithoutPrefix } from '../crypto'; import { encryptUsingSessionProtocol } from '../crypto/MessageEncrypter'; +import { ECKeyPair } from '../../receiver/keypairs'; +import { UserUtils } from '../utils'; export interface GroupInfo { id: string; @@ -255,7 +255,7 @@ export async function updateOrCreateClosedGroupV2(details: GroupInfo) { if (expireTimer === undefined || typeof expireTimer !== 'number') { return; } - const source = await UserUtil.getCurrentDevicePubKey(); + const source = await UserUtils.getCurrentDevicePubKey(); await conversation.updateExpirationTimer(expireTimer, source, Date.now(), { fromSync: true, }); @@ -270,7 +270,7 @@ export async function leaveClosedGroupV2(groupId: string) { window.log.error('Cannot leave non-existing v2 group'); return; } - const ourNumber = await UserUtil.getOurNumber(); + const ourNumber = await UserUtils.getOurNumber(); const isCurrentUserAdmin = convo.get('groupAdmins')?.includes(ourNumber.key); const now = Date.now(); @@ -320,7 +320,7 @@ export async function sendGroupUpdateForClosedV2( messageId: string ) { const { id: groupId, members, name: groupName, expireTimer } = groupUpdate; - const ourNumber = await UserUtil.getOurNumber(); + const ourNumber = await UserUtils.getOurNumber(); const removedMembers = diff.leavingMembers || []; const newMembers = diff.joiningMembers || []; // joining members @@ -461,7 +461,7 @@ export async function generateAndSendNewEncryptionKeyPair( return; } - const ourNumber = await UserUtil.getOurNumber(); + const ourNumber = await UserUtils.getOurNumber(); if (!groupConvo.get('groupAdmins')?.includes(ourNumber.key)) { window.log.warn( 'generateAndSendNewEncryptionKeyPair: cannot send it as a non admin' diff --git a/ts/session/messages/outgoing/content/data/groupv2/ClosedGroupV2EncryptionPairMessage.ts b/ts/session/messages/outgoing/content/data/groupv2/ClosedGroupV2EncryptionPairMessage.ts index 8d3a3c394..716be9725 100644 --- a/ts/session/messages/outgoing/content/data/groupv2/ClosedGroupV2EncryptionPairMessage.ts +++ b/ts/session/messages/outgoing/content/data/groupv2/ClosedGroupV2EncryptionPairMessage.ts @@ -7,7 +7,9 @@ import { interface ClosedGroupV2EncryptionPairMessageParams extends ClosedGroupV2MessageParams { - encryptedKeyPairs: Array; + encryptedKeyPairs: Array< + SignalService.DataMessage.ClosedGroupUpdateV2.KeyPairWrapper + >; } export class ClosedGroupV2EncryptionPairMessage extends ClosedGroupV2Message { diff --git a/ts/session/messages/outgoing/content/data/groupv2/ClosedGroupV2Message.ts b/ts/session/messages/outgoing/content/data/groupv2/ClosedGroupV2Message.ts index d0eb7514c..78cd2250c 100644 --- a/ts/session/messages/outgoing/content/data/groupv2/ClosedGroupV2Message.ts +++ b/ts/session/messages/outgoing/content/data/groupv2/ClosedGroupV2Message.ts @@ -1,7 +1,7 @@ import { DataMessage } from '../DataMessage'; import { MessageParams } from '../../../Message'; -import { PubKey } from '../../../../../types'; import { SignalService } from '../../../../../../protobuf'; +import { PubKey } from '../../../../../types/PubKey'; export interface ClosedGroupV2MessageParams extends MessageParams { groupId: string | PubKey; diff --git a/ts/session/messages/outgoing/content/data/groupv2/ClosedGroupV2NewMessage.ts b/ts/session/messages/outgoing/content/data/groupv2/ClosedGroupV2NewMessage.ts index 53f9e8b36..28814c6ac 100644 --- a/ts/session/messages/outgoing/content/data/groupv2/ClosedGroupV2NewMessage.ts +++ b/ts/session/messages/outgoing/content/data/groupv2/ClosedGroupV2NewMessage.ts @@ -4,7 +4,7 @@ import { ClosedGroupV2MessageParams, } from './ClosedGroupV2Message'; import { fromHexToArray } from '../../../../../utils/String'; -import { ECKeyPair } from '../../../../../../receiver/closedGroupsV2'; +import { ECKeyPair } from '../../../../../../receiver/keypairs'; export interface ClosedGroupV2NewMessageParams extends ClosedGroupV2MessageParams { diff --git a/ts/session/messages/outgoing/content/data/groupv2/index.ts b/ts/session/messages/outgoing/content/data/groupv2/index.ts index 47e166395..8a9bab553 100644 --- a/ts/session/messages/outgoing/content/data/groupv2/index.ts +++ b/ts/session/messages/outgoing/content/data/groupv2/index.ts @@ -1,5 +1,4 @@ export * from './ClosedGroupV2ChatMessage'; export * from './ClosedGroupV2EncryptionPairMessage'; -export * from './ClosedGroupV2Message'; export * from './ClosedGroupV2NewMessage'; export * from './ClosedGroupV2UpdateMessage'; diff --git a/ts/session/messages/outgoing/content/data/index.ts b/ts/session/messages/outgoing/content/data/index.ts index dd4cc7757..16b4f8dfb 100644 --- a/ts/session/messages/outgoing/content/data/index.ts +++ b/ts/session/messages/outgoing/content/data/index.ts @@ -1,5 +1,10 @@ export * from './DataMessage'; export * from './GroupInvitationMessage'; export * from './ChatMessage'; -export * from './groupv2'; +export * from './groupv2/ClosedGroupV2Message'; +export * from './groupv2/ClosedGroupV2ChatMessage'; +export * from './groupv2/ClosedGroupV2EncryptionPairMessage'; +export * from './groupv2/ClosedGroupV2NewMessage'; +export * from './groupv2/ClosedGroupV2UpdateMessage'; +export * from './groupv2/ClosedGroupV2Message'; export * from './ExpirationTimerUpdateMessage'; diff --git a/ts/session/sending/MessageQueue.ts b/ts/session/sending/MessageQueue.ts index 3306d4e8f..fbbbf1bd1 100644 --- a/ts/session/sending/MessageQueue.ts +++ b/ts/session/sending/MessageQueue.ts @@ -5,16 +5,15 @@ import { MessageQueueInterfaceEvents, } from './MessageQueueInterface'; import { - ClosedGroupV2Message, ContentMessage, ExpirationTimerUpdateMessage, OpenGroupMessage, } from '../messages/outgoing'; import { PendingMessageCache } from './PendingMessageCache'; -import { JobQueue, TypedEventEmitter } from '../utils'; +import { JobQueue, TypedEventEmitter, UserUtils } from '../utils'; import { PubKey, RawMessage } from '../types'; import { MessageSender } from '.'; -import { UserUtil } from '../../util'; +import { ClosedGroupV2Message } from '../messages/outgoing/content/data/groupv2/ClosedGroupV2Message'; export class MessageQueue implements MessageQueueInterface { public readonly events: TypedEventEmitter; @@ -115,13 +114,13 @@ export class MessageQueue implements MessageQueueInterface { return; } - const ourPubKey = await UserUtil.getCurrentDevicePubKey(); + const ourPubKey = await UserUtils.getCurrentDevicePubKey(); - if(!ourPubKey) { - throw new Error('ourNumber is not set') + if (!ourPubKey) { + throw new Error('ourNumber is not set'); } - window.log.warn('sendSyncMessage TODO with syncTarget') + window.log.warn('sendSyncMessage TODO with syncTarget'); await this.sendMessageToDevices([PubKey.cast(ourPubKey)], message, sentCb); } @@ -183,7 +182,7 @@ export class MessageQueue implements MessageQueueInterface { sentCb?: (message: RawMessage) => Promise ): Promise { // Don't send to ourselves - const currentDevice = await UserUtil.getCurrentDevicePubKey(); + const currentDevice = await UserUtils.getCurrentDevicePubKey(); if (currentDevice && device.isEqual(currentDevice)) { return; } diff --git a/ts/session/sending/MessageQueueInterface.ts b/ts/session/sending/MessageQueueInterface.ts index f725af535..b4ac03cc4 100644 --- a/ts/session/sending/MessageQueueInterface.ts +++ b/ts/session/sending/MessageQueueInterface.ts @@ -1,7 +1,4 @@ -import { - ContentMessage, - OpenGroupMessage, -} from '../messages/outgoing'; +import { ContentMessage, OpenGroupMessage } from '../messages/outgoing'; import { RawMessage } from '../types/RawMessage'; import { TypedEventEmitter } from '../utils'; import { PubKey } from '../types'; diff --git a/ts/session/sending/MessageSender.ts b/ts/session/sending/MessageSender.ts index a867d4743..db3f0b8a8 100644 --- a/ts/session/sending/MessageSender.ts +++ b/ts/session/sending/MessageSender.ts @@ -3,10 +3,10 @@ import { RawMessage } from '../types/RawMessage'; import { OpenGroupMessage } from '../messages/outgoing'; import { SignalService } from '../../protobuf'; -import { UserUtil } from '../../util'; import { MessageEncrypter } from '../crypto'; import pRetry from 'p-retry'; import { PubKey } from '../types'; +import { UserUtils } from '../utils'; // ================ Regular ================ @@ -70,10 +70,9 @@ async function buildEnvelope( if (type === SignalService.Envelope.Type.CLOSED_GROUP_CIPHERTEXT) { source = sskSource; - } else if (type !== SignalService.Envelope.Type.UNIDENTIFIED_SENDER) { - source = await UserUtil.getCurrentDevicePubKey(); } + return SignalService.Envelope.create({ type, source, diff --git a/ts/session/types/PubKey.ts b/ts/session/types/PubKey.ts index 6727d6b30..190220c6d 100644 --- a/ts/session/types/PubKey.ts +++ b/ts/session/types/PubKey.ts @@ -48,7 +48,7 @@ export class PubKey { * @param value The value to cast. */ public static cast(value?: string | PubKey): PubKey { - if(!value) { + if (!value) { throw new Error(`Invalid pubkey string passed: ${value}`); } return typeof value === 'string' ? new PubKey(value) : value; @@ -135,4 +135,4 @@ export class PubKey { public withoutPrefixToArray(): Uint8Array { return fromHexToArray(PubKey.remove05PrefixIfNeeded(this.key)); } -} \ No newline at end of file +} diff --git a/ts/session/utils/Groups.ts b/ts/session/utils/Groups.ts index 9bff1c888..27f535300 100644 --- a/ts/session/utils/Groups.ts +++ b/ts/session/utils/Groups.ts @@ -3,9 +3,7 @@ import { PubKey } from '../types'; import { ConversationController } from '../conversations'; import { fromHexToArray } from './String'; -export async function getGroupMembers( - groupId: PubKey -): Promise> { +export async function getGroupMembers(groupId: PubKey): Promise> { const groupConversation = ConversationController.getInstance().get( groupId.key ); diff --git a/ts/session/utils/Messages.ts b/ts/session/utils/Messages.ts index 0faf8c65e..04cce9a56 100644 --- a/ts/session/utils/Messages.ts +++ b/ts/session/utils/Messages.ts @@ -20,7 +20,8 @@ export function getEncryptionTypeFromMessageType( // 2. if TypingMessage or ExpirationTimer and groupId is set => must be encoded with ClosedGroup too if ( message instanceof ClosedGroupV2Message || - (message instanceof ExpirationTimerUpdateMessage && message.groupId)) { + (message instanceof ExpirationTimerUpdateMessage && message.groupId) + ) { return EncryptionType.ClosedGroup; } else { return EncryptionType.Fallback; @@ -33,7 +34,7 @@ export async function toRawMessage( ): Promise { const timestamp = message.timestamp; const ttl = message.ttl(); - window?.log?.debug('toRawMessage proto:', message.contentProto()); + // window?.log?.debug('toRawMessage proto:', message.contentProto()); const plainTextBuffer = message.plainTextBuffer(); const encryption = getEncryptionTypeFromMessageType(message); diff --git a/ts/util/user.ts b/ts/session/utils/User.ts similarity index 71% rename from ts/util/user.ts rename to ts/session/utils/User.ts index ffe38435a..8ff8e6142 100644 --- a/ts/util/user.ts +++ b/ts/session/utils/User.ts @@ -1,9 +1,23 @@ -import { getItemById } from '../../js/modules/data'; -import { KeyPair } from '../../libtextsecure/libsignal-protocol'; -import { StringUtils } from '../session/utils'; import _ from 'lodash'; -import { PubKey } from '../session/types'; -import { UserUtil } from '.'; +import { UserUtils } from '.'; +import { getItemById } from '../../../js/modules/data'; +import { KeyPair } from '../../../libtextsecure/libsignal-protocol'; +import { PubKey } from '../types'; +import { toHex } from './String'; + +export async function isUs( + pubKey: string | PubKey | undefined +): Promise { + if (!pubKey) { + throw new Error('pubKey is not set'); + } + const ourNumber = await UserUtils.getCurrentDevicePubKey(); + if (!ourNumber) { + throw new Error('ourNumber is not set'); + } + const pubKeyStr = pubKey instanceof PubKey ? pubKey.key : pubKey; + return pubKeyStr === ourNumber; +} export type HexKeyPair = { pubKey: string; @@ -23,25 +37,13 @@ export async function getCurrentDevicePubKey(): Promise { } export async function getOurNumber(): Promise { - const ourNumber = await UserUtil.getCurrentDevicePubKey(); - if(!ourNumber) { + const ourNumber = await UserUtils.getCurrentDevicePubKey(); + if (!ourNumber) { throw new Error('ourNumber is not set'); } return PubKey.cast(ourNumber); } -export async function isUs(pubKey: string | PubKey | undefined): Promise { - if(!pubKey) { - throw new Error('pubKey is not set'); - } - const ourNumber = await UserUtil.getCurrentDevicePubKey(); - if(!ourNumber) { - throw new Error('ourNumber is not set'); - } - const pubKeyStr = pubKey instanceof PubKey ? pubKey.key : pubKey; - return pubKeyStr === ourNumber; -} - /** * This return the stored x25519 identity keypair for the current logged in user */ @@ -60,8 +62,8 @@ export async function getUserED25519KeyPair(): Promise { const pubKeyAsArray = _.map(ed25519KeyPair.publicKey, a => a); const privKeyAsArray = _.map(ed25519KeyPair.privateKey, a => a); return { - pubKey: StringUtils.toHex(new Uint8Array(pubKeyAsArray)), - privKey: StringUtils.toHex(new Uint8Array(privKeyAsArray)), + pubKey: toHex(new Uint8Array(pubKeyAsArray)), + privKey: toHex(new Uint8Array(privKeyAsArray)), }; } return undefined; diff --git a/ts/session/utils/index.ts b/ts/session/utils/index.ts index 6901f1612..642c5171b 100644 --- a/ts/session/utils/index.ts +++ b/ts/session/utils/index.ts @@ -6,6 +6,7 @@ import * as PromiseUtils from './Promise'; import * as ProtobufUtils from './Protobuf'; import * as MenuUtils from '../../components/session/menu/Menu'; import * as ToastUtils from './Toast'; +import * as UserUtils from './User'; export * from './Attachments'; export * from './TypedEmitter'; @@ -20,4 +21,5 @@ export { ProtobufUtils, MenuUtils, ToastUtils, + UserUtils, }; diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 60e89a51e..a2f2d192f 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -578,9 +578,7 @@ export function reducer( if (action.type === 'CONVERSATION_CHANGED') { const { payload } = action; const { id, data } = payload; - const { conversationLookup } = state; - - let selectedConversation = state.selectedConversation; + const { conversationLookup, selectedConversation } = state; const existing = conversationLookup[id]; // In the change case we only modify the lookup if we already had that conversation diff --git a/ts/state/ducks/search.ts b/ts/state/ducks/search.ts index 3a804ee63..89a971a75 100644 --- a/ts/state/ducks/search.ts +++ b/ts/state/ducks/search.ts @@ -260,7 +260,6 @@ async function queryConversationsAndContacts( query ); - // Split into two groups - active conversations and items just from address book let conversations: Array = []; let contacts: Array = []; diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index 1311557a8..c42866156 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -10,8 +10,7 @@ import { MessageTypeInConvo, } from '../ducks/conversations'; -import { getIntl, getRegionCode, getOurNumber } from './user'; -import { ConversationListItemProps } from '../../components/ConversationListItem'; +import { getIntl, getOurNumber, getRegionCode } from './user'; import { BlockedNumberController } from '../../util'; export const getConversations = (state: StateType): ConversationsStateType => diff --git a/ts/state/smart/LeftPane.tsx b/ts/state/smart/LeftPane.tsx index c0a58ad25..13fc86d26 100644 --- a/ts/state/smart/LeftPane.tsx +++ b/ts/state/smart/LeftPane.tsx @@ -3,11 +3,7 @@ import { LeftPane } from '../../components/LeftPane'; import { StateType } from '../reducer'; import { getQuery, getSearchResults, isSearching } from '../selectors/search'; -import { - getIntl, - getRegionCode, - getOurNumber, -} from '../selectors/user'; +import { getIntl, getOurNumber, getRegionCode } from '../selectors/user'; import { getLeftPaneLists, getOurPrimaryConversation, @@ -17,7 +13,7 @@ import { getFocusedSection } from '../selectors/section'; import { getTheme } from '../selectors/theme'; // Workaround: A react component's required properties are filtering up through connect() -// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31363 +// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/3136k3 const mapStateToProps = (state: StateType) => { const showSearch = isSearching(state); diff --git a/ts/test/session/integration/common.ts b/ts/test/session/integration/common.ts index d0ce5d7c2..0772ddfe8 100644 --- a/ts/test/session/integration/common.ts +++ b/ts/test/session/integration/common.ts @@ -326,9 +326,7 @@ export class Common { return [app1, app2]; } - public static async addFriendToNewClosedGroup( - members: Array, - ) { + public static async addFriendToNewClosedGroup(members: Array) { const [app, ...others] = members; await app.client diff --git a/ts/test/session/integration/sender_keys_itest.ts b/ts/test/session/integration/sender_keys_itest.ts index 33d0ee7df..3dfbe068b 100644 --- a/ts/test/session/integration/sender_keys_itest.ts +++ b/ts/test/session/integration/sender_keys_itest.ts @@ -55,7 +55,6 @@ async function makeFriendsPlusMessage( async function testTwoMembers() { const [app, app2] = await Common.startAppsAsFriends(); - // create group and add new friend await Common.addFriendToNewClosedGroup([app, app2]); diff --git a/ts/test/session/unit/crypto/MessageEncrypter_test.ts b/ts/test/session/unit/crypto/MessageEncrypter_test.ts index ccbf06bd7..5da1fab33 100644 --- a/ts/test/session/unit/crypto/MessageEncrypter_test.ts +++ b/ts/test/session/unit/crypto/MessageEncrypter_test.ts @@ -8,10 +8,9 @@ import { } from '../../../../session/crypto'; import { EncryptionType } from '../../../../session/types/EncryptionType'; import { Stubs, TestUtils } from '../../../test-utils'; -import { UserUtil } from '../../../../util'; import { SignalService } from '../../../../protobuf'; -import { StringUtils } from '../../../../session/utils'; +import { StringUtils, UserUtils } from '../../../../session/utils'; import chaiBytes from 'chai-bytes'; import { PubKey } from '../../../../session/types'; @@ -118,9 +117,9 @@ describe('MessageEncrypter', () => { } as any, }); - sandbox.stub(UserUtil, 'getCurrentDevicePubKey').resolves(ourNumber); + sandbox.stub(UserUtils, 'getCurrentDevicePubKey').resolves(ourNumber); sandbox - .stub(UserUtil, 'getUserED25519KeyPair') + .stub(UserUtils, 'getUserED25519KeyPair') .resolves(ourUserEd25516Keypair); }); @@ -187,7 +186,7 @@ describe('MessageEncrypter', () => { sandboxSessionProtocol = sinon.createSandbox(); sandboxSessionProtocol - .stub(UserUtil, 'getIdentityKeyPair') + .stub(UserUtils, 'getIdentityKeyPair') .resolves(ourIdentityKeypair); }); @@ -211,7 +210,7 @@ describe('MessageEncrypter', () => { }); it('should pass the correct data for sodium crypto_sign', async () => { - const keypair = await UserUtil.getUserED25519KeyPair(); + const keypair = await UserUtils.getUserED25519KeyPair(); const recipient = TestUtils.generateFakePubKey(); const sodium = await getSodium(); const cryptoSignDetachedSpy = sandboxSessionProtocol.spy( @@ -266,8 +265,8 @@ describe('MessageEncrypter', () => { it('should return valid decodable ciphertext', async () => { // for testing, we encode a message to ourself - const userX25519KeyPair = await UserUtil.getIdentityKeyPair(); - const userEd25519KeyPair = await UserUtil.getUserED25519KeyPair(); + const userX25519KeyPair = await UserUtils.getIdentityKeyPair(); + const userEd25519KeyPair = await UserUtils.getUserED25519KeyPair(); const plainTextBytes = new Uint8Array( StringUtils.encode('123456789', 'utf8') diff --git a/ts/test/session/unit/messages/ChatMessage_test.ts b/ts/test/session/unit/messages/ChatMessage_test.ts index a4a365ac9..dafe352b1 100644 --- a/ts/test/session/unit/messages/ChatMessage_test.ts +++ b/ts/test/session/unit/messages/ChatMessage_test.ts @@ -63,7 +63,7 @@ describe('ChatMessage', () => { .to.have.deep.property('displayName', 'displayName'); expect(decoded.dataMessage) .to.have.property('profile') - .to.have.deep.property('avatar', 'avatarPointer'); + .to.have.deep.property('profilePicture', 'avatarPointer'); expect(decoded.dataMessage).to.have.deep.property('profileKey', profileKey); }); diff --git a/ts/test/session/unit/sending/MessageQueue_test.ts b/ts/test/session/unit/sending/MessageQueue_test.ts index 4c9cfecc1..94e89e5f0 100644 --- a/ts/test/session/unit/sending/MessageQueue_test.ts +++ b/ts/test/session/unit/sending/MessageQueue_test.ts @@ -3,18 +3,17 @@ import * as sinon from 'sinon'; import _ from 'lodash'; import { describe } from 'mocha'; -import { GroupUtils, PromiseUtils } from '../../../../session/utils'; -import { TestUtils } from '../../../../test/test-utils'; +import { GroupUtils, PromiseUtils, UserUtils } from '../../../../session/utils'; +import { TestUtils } from '../../../../test/test-utils'; import { MessageQueue } from '../../../../session/sending/MessageQueue'; import { ContentMessage, OpenGroupMessage, } from '../../../../session/messages/outgoing'; -import {PubKey, RawMessage } from '../../../../session/types'; -import { UserUtil } from '../../../../util'; +import { PubKey, RawMessage } from '../../../../session/types'; import { MessageSender } from '../../../../session/sending'; import { PendingMessageCacheStub } from '../../../test-utils/stubs'; -import { ClosedGroupV2Message } from '../../../../session/messages/outgoing/content/data/groupv2'; +import { ClosedGroupV2Message } from '../../../../session/messages/outgoing/content/data/groupv2/ClosedGroupV2Message'; // tslint:disable-next-line: no-require-imports no-var-requires const chaiAsPromised = require('chai-as-promised'); @@ -38,7 +37,7 @@ describe('MessageQueue', () => { beforeEach(async () => { // Utils Stubs - sandbox.stub(UserUtil, 'getCurrentDevicePubKey').resolves(ourNumber); + sandbox.stub(UserUtils, 'getCurrentDevicePubKey').resolves(ourNumber); TestUtils.stubWindow('libsignal', { SignalProtocolAddress: sandbox.stub(), @@ -213,7 +212,10 @@ describe('MessageQueue', () => { }); it('should emit a success event when send was successful', async () => { - sendToOpenGroupStub.resolves({ serverId: 5125, serverTimestamp: 5125 }); + sendToOpenGroupStub.resolves({ + serverId: 5125, + serverTimestamp: 5125, + }); const message = TestUtils.generateOpenGroupMessage(); const eventPromise = PromiseUtils.waitForTask(complete => { @@ -237,4 +239,4 @@ describe('MessageQueue', () => { }); }); }); -}); \ No newline at end of file +}); diff --git a/ts/test/session/unit/sending/MessageSender_test.ts b/ts/test/session/unit/sending/MessageSender_test.ts index f260c8cd3..19d1d358e 100644 --- a/ts/test/session/unit/sending/MessageSender_test.ts +++ b/ts/test/session/unit/sending/MessageSender_test.ts @@ -5,12 +5,12 @@ import { toNumber } from 'lodash'; import { MessageSender } from '../../../../session/sending'; import LokiMessageAPI from '../../../../../js/modules/loki_message_api'; import { TestUtils } from '../../../test-utils'; -import { UserUtil } from '../../../../util'; import { MessageEncrypter } from '../../../../session/crypto'; import { SignalService } from '../../../../protobuf'; import { OpenGroupMessage } from '../../../../session/messages/outgoing'; import { EncryptionType } from '../../../../session/types/EncryptionType'; import { PubKey } from '../../../../session/types'; +import { UserUtils } from '../../../../session/utils'; describe('MessageSender', () => { const sandbox = sinon.createSandbox(); @@ -35,6 +35,7 @@ describe('MessageSender', () => { }); }); + // tslint:disable-next-line: max-func-body-length describe('send', () => { const ourNumber = '0123456789abcdef'; let lokiMessageAPISendStub: sinon.SinonStub< @@ -58,7 +59,7 @@ describe('MessageSender', () => { cipherText: crypto.randomBytes(10), }); - sandbox.stub(UserUtil, 'getCurrentDevicePubKey').resolves(ourNumber); + sandbox.stub(UserUtils, 'getCurrentDevicePubKey').resolves(ourNumber); }); describe('retry', () => { @@ -161,8 +162,10 @@ describe('MessageSender', () => { const envelope = SignalService.Envelope.decode( webSocketMessage.request?.body as Uint8Array ); - expect(envelope.type).to.equal(SignalService.Envelope.Type.UNIDENTIFIED_SENDER); - expect(envelope.source).to.equal(ourNumber); + expect(envelope.type).to.equal( + SignalService.Envelope.Type.UNIDENTIFIED_SENDER + ); + expect(envelope.source).to.equal(''); expect(toNumber(envelope.timestamp)).to.equal(timestamp); expect(envelope.content).to.deep.equal(plainTextBuffer); }); diff --git a/ts/test/test-utils/utils/pubkey.ts b/ts/test/test-utils/utils/pubkey.ts index e3bc38650..04f17bfc6 100644 --- a/ts/test/test-utils/utils/pubkey.ts +++ b/ts/test/test-utils/utils/pubkey.ts @@ -1,7 +1,6 @@ import * as crypto from 'crypto'; -import { ECKeyPair } from '../../../receiver/closedGroupsV2'; +import { ECKeyPair } from '../../../receiver/keypairs'; import { PubKey } from '../../../session/types'; -import { fromHexToArray } from '../../../session/utils/String'; export function generateFakePubKey(): PubKey { // Generates a mock pubkey for testing diff --git a/ts/test/util/blockedNumberController_test.ts b/ts/test/util/blockedNumberController_test.ts index 3a116c6bd..b9901882c 100644 --- a/ts/test/util/blockedNumberController_test.ts +++ b/ts/test/util/blockedNumberController_test.ts @@ -3,8 +3,9 @@ import * as sinon from 'sinon'; import { BlockedNumberController } from '../../util/blockedNumberController'; import { TestUtils } from '../test-utils'; import { PubKey } from '../../session/types'; -import { UserUtil } from '../../util'; +import { UserUtils } from '../../session/utils'; +// tslint:disable-next-line: max-func-body-length describe('BlockedNumberController', () => { const sandbox = sinon.createSandbox(); let memoryDB: { [key: string]: any }; @@ -78,10 +79,9 @@ describe('BlockedNumberController', () => { describe('unblock', async () => { it('should unblock the user', async () => { const primary = TestUtils.generateFakePubKey(); - const secondary = TestUtils.generateFakePubKey(); memoryDB.blocked = [primary.key]; - await BlockedNumberController.unblock(secondary); + await BlockedNumberController.unblock(primary); const blockedNumbers = BlockedNumberController.getBlockedNumbers(); expect(blockedNumbers).to.be.empty; @@ -166,14 +166,11 @@ describe('BlockedNumberController', () => { let ourDevice: PubKey; beforeEach(() => { ourDevice = TestUtils.generateFakePubKey(); - sandbox.stub(UserUtil, 'getCurrentDevicePubKey').resolves(ourDevice.key); + sandbox.stub(UserUtils, 'getCurrentDevicePubKey').resolves(ourDevice.key); }); it('should return false for our device', async () => { const isBlocked = await BlockedNumberController.isBlockedAsync(ourDevice); - expect(isBlocked).to.equal( - false, - 'Expected our device to return false' - ); + expect(isBlocked).to.equal(false, 'Expected our device to return false'); }); it('should return true if the device is blocked', async () => { diff --git a/ts/util/blockedNumberController.ts b/ts/util/blockedNumberController.ts index 3a377ffbe..a192070f1 100644 --- a/ts/util/blockedNumberController.ts +++ b/ts/util/blockedNumberController.ts @@ -1,6 +1,6 @@ -import { UserUtil } from '.'; import { createOrUpdateItem, getItemById } from '../../js/modules/data'; import { PubKey } from '../session/types'; +import { UserUtils } from '../session/utils'; const BLOCKED_NUMBERS_ID = 'blocked'; const BLOCKED_GROUPS_ID = 'blocked-groups'; @@ -18,7 +18,7 @@ export class BlockedNumberController { */ public static async isBlockedAsync(user: string | PubKey): Promise { await this.load(); - const isOurDevice = await UserUtil.isUs(user); + const isOurDevice = await UserUtils.isUs(user); if (isOurDevice) { return false; } diff --git a/ts/util/index.ts b/ts/util/index.ts index 9a4376c9e..214a13908 100644 --- a/ts/util/index.ts +++ b/ts/util/index.ts @@ -5,7 +5,6 @@ import { missingCaseError } from './missingCaseError'; import { migrateColor } from './migrateColor'; import { makeLookup } from './makeLookup'; import { FindMember } from './findMember'; -import * as UserUtil from './user'; import * as PasswordUtil from './passwordUtils'; import * as AttachmentUtil from './attachmentsUtil'; import * as LinkPreviewUtil from './linkPreviewFetch'; @@ -19,7 +18,6 @@ export { makeLookup, migrateColor, missingCaseError, - UserUtil, PasswordUtil, FindMember, AttachmentUtil,