diff --git a/ts/receiver/configMessage.ts b/ts/receiver/configMessage.ts index 59547d623..71ba0ce89 100644 --- a/ts/receiver/configMessage.ts +++ b/ts/receiver/configMessage.ts @@ -1,4 +1,4 @@ -import _, { isEmpty, isEqual } from 'lodash'; +import _, { isEmpty, isEqual, isNil } from 'lodash'; import { ConfigDumpData } from '../data/configDump/configDump'; import { Data, hasSyncedInitialConfigurationItem } from '../data/data'; import { ConversationInteraction } from '../interactions'; @@ -39,7 +39,10 @@ async function mergeConfigsWithIncomingUpdates( await GenericWrapperActions.merge(wrapperId, toMerge); const needsPush = await GenericWrapperActions.needsPush(wrapperId); + console.warn(`${wrapperId} needsPush? `, needsPush); const needsDump = await GenericWrapperActions.needsDump(wrapperId); + console.warn(`${wrapperId} needsDump? `, needsDump); + const messageHashes = [incomingConfig.messageHash]; const latestSentTimestamp = incomingConfig.envelopeTimestamp; @@ -73,20 +76,29 @@ async function handleContactsUpdate(result: IncomingConfResult): Promise handleContactFromConfig(c, envelope))); + await Promise.all( + configMessage.contacts.map(async c => handleContactFromConfigLegacy(c, envelope)) + ); } } @@ -299,6 +315,9 @@ async function handleGroupsAndContactsFromConfigMessage( * @param openGroups string array of open group urls */ const handleOpenGroupsFromConfig = (openGroups: Array) => { + if (window.sessionFeatureFlags.useSharedUtilForUserConfig) { + return; + } const numberOpenGroup = openGroups?.length || 0; for (let i = 0; i < numberOpenGroup; i++) { const currentOpenGroupUrl = openGroups[i]; @@ -320,10 +339,13 @@ const handleOpenGroupsFromConfig = (openGroups: Array) => { * Trigger a join for all closed groups which doesn't exist yet * @param openGroups string array of open group urls */ -const handleClosedGroupsFromConfig = async ( +const handleClosedGroupsFromConfigLegacy = async ( closedGroups: Array, envelope: EnvelopePlus ) => { + if (window.sessionFeatureFlags.useSharedUtilForUserConfig) { + return; + } const numberClosedGroup = closedGroups?.length || 0; window?.log?.info( @@ -354,10 +376,13 @@ const handleClosedGroupsFromConfig = async ( * Handles adding of a contact and setting approval/block status * @param contactReceived Contact to sync */ -const handleContactFromConfig = async ( +const handleContactFromConfigLegacy = async ( contactReceived: SignalService.ConfigurationMessage.IContact, envelope: EnvelopePlus ) => { + if (window.sessionFeatureFlags.useSharedUtilForUserConfig) { + return; + } try { if (!contactReceived.publicKey?.length) { return; @@ -415,13 +440,13 @@ const handleContactFromConfig = async ( * This is the legacy way of handling incoming configuration message. * Should not be used at all soon. */ -async function handleConfigurationMessage( +async function handleConfigurationMessageLegacy( envelope: EnvelopePlus, configurationMessage: SignalService.ConfigurationMessage ): Promise { if (window.sessionFeatureFlags.useSharedUtilForUserConfig) { window?.log?.info( - 'useSharedUtilForUserConfig is set, not handling config messages with "handleConfigurationMessage()"' + 'useSharedUtilForUserConfig is set, not handling config messages with "handleConfigurationMessageLegacy()"' ); await removeFromCache(envelope); return; @@ -438,14 +463,14 @@ async function handleConfigurationMessage( return removeFromCache(envelope); } - await handleOurProfileUpdate(envelope.timestamp, configurationMessage); + await handleOurProfileUpdateLegacy(envelope.timestamp, configurationMessage); - await handleGroupsAndContactsFromConfigMessage(envelope, configurationMessage); + await handleGroupsAndContactsFromConfigMessageLegacy(envelope, configurationMessage); await removeFromCache(envelope); } export const ConfigMessageHandler = { - handleConfigurationMessage, + handleConfigurationMessageLegacy, handleConfigMessageViaLibSession, }; diff --git a/ts/receiver/contentMessage.ts b/ts/receiver/contentMessage.ts index 876890d5b..0e2d4fffa 100644 --- a/ts/receiver/contentMessage.ts +++ b/ts/receiver/contentMessage.ts @@ -428,7 +428,7 @@ export async function innerHandleSwarmContentMessage( if (content.configurationMessage) { // this one can be quite long (downloads profilePictures and everything), // so do not await it - void ConfigMessageHandler.handleConfigurationMessage( + void ConfigMessageHandler.handleConfigurationMessageLegacy( envelope, content.configurationMessage as SignalService.ConfigurationMessage ); diff --git a/ts/session/conversations/ConversationController.ts b/ts/session/conversations/ConversationController.ts index 279922655..060d9d410 100644 --- a/ts/session/conversations/ConversationController.ts +++ b/ts/session/conversations/ConversationController.ts @@ -264,8 +264,14 @@ export class ConversationController { } } + /** + * + * @returns the reference of the list of conversations stored. + * Warning: You should not not edit things directly from that list. This must only be used for reading things. + * If you need to make change, do the usual getConversationControler().get('the id you want to edit') + */ public getConversations(): Array { - return Array.from(this.conversations.models); + return this.conversations.models; } public unsafeDelete(convo: ConversationModel) { @@ -315,6 +321,7 @@ export class ConversationController { public loadPromise() { return this._initialPromise; } + public reset() { this._initialPromise = Promise.resolve(); this._initialFetchComplete = false; diff --git a/ts/session/utils/job_runners/jobs/AvatarDownloadJob.ts b/ts/session/utils/job_runners/jobs/AvatarDownloadJob.ts index b6f7c9d06..f67da9557 100644 --- a/ts/session/utils/job_runners/jobs/AvatarDownloadJob.ts +++ b/ts/session/utils/job_runners/jobs/AvatarDownloadJob.ts @@ -71,9 +71,9 @@ async function addAvatarDownloadJobIfNeeded({ ); await runners.avatarDownloadRunner.addJob(avatarDownloadJob); } else { - window.log.debug( - `addAvatarDownloadJobIfNeeded: no download required for ${pubkey}:${profileUrl}:${profileKeyHex} ` - ); + // window.log.debug( + // `addAvatarDownloadJobIfNeeded: no download required for ${pubkey}:${profileUrl}:${profileKeyHex} ` + // ); } } diff --git a/ts/session/utils/job_runners/jobs/ConfigurationSyncJob.ts b/ts/session/utils/job_runners/jobs/ConfigurationSyncJob.ts index b85295c70..401ad71ab 100644 --- a/ts/session/utils/job_runners/jobs/ConfigurationSyncJob.ts +++ b/ts/session/utils/job_runners/jobs/ConfigurationSyncJob.ts @@ -2,16 +2,12 @@ import { compact, groupBy, isArray, isEmpty, isNumber, isString, uniq } from 'lo import { v4 } from 'uuid'; import { UserUtils } from '../..'; import { ConfigDumpData } from '../../../../data/configDump/configDump'; -import { - GenericWrapperActions, - UserConfigWrapperActions, -} from '../../../../webworker/workers/browser/libsession_worker_interface'; +import { GenericWrapperActions } from '../../../../webworker/workers/browser/libsession_worker_interface'; import { NotEmptyArrayOfBatchResults } from '../../../apis/snode_api/SnodeRequestTypes'; import { getConversationController } from '../../../conversations'; import { SharedConfigMessage } from '../../../messages/outgoing/controlMessage/SharedConfigMessage'; import { MessageSender } from '../../../sending/MessageSender'; import { LibSessionUtil, OutgoingConfResult } from '../../libsession/libsession_utils'; -import { fromHexToArray } from '../../String'; import { runners } from '../JobRunner'; import { AddJobCheckReturn, @@ -200,17 +196,8 @@ class ConfigurationSyncJob extends PersistedJob window.log.warn('did not find our own conversation'); return RunJobResult.PermanentFailure; } - const name = conversation.get('displayNameInProfile'); - const pointer = conversation.get('avatarPointer'); - const profileKey = conversation.get('profileKey'); - await UserConfigWrapperActions.setName(name || ''); - - if (profileKey && pointer) { - const profileKeyArray = fromHexToArray(profileKey); - await UserConfigWrapperActions.setProfilePicture(pointer, profileKeyArray); - } else { - await UserConfigWrapperActions.setProfilePicture('', new Uint8Array()); - } + await LibSessionUtil.insertUserProfileIntoWrapper(); + await LibSessionUtil.insertAllContactsIntoContactsWrapper(); const singleDestChanges = await retrieveSingleDestinationChanges(); diff --git a/ts/session/utils/libsession/libsession_utils.ts b/ts/session/utils/libsession/libsession_utils.ts index 3bdb039e0..df8706839 100644 --- a/ts/session/utils/libsession/libsession_utils.ts +++ b/ts/session/utils/libsession/libsession_utils.ts @@ -1,5 +1,4 @@ -import { from_hex } from 'libsodium-wrappers-sumo'; -import { difference, isEqual, omit } from 'lodash'; +import { difference, omit } from 'lodash'; import Long from 'long'; import { UserUtils } from '..'; import { ConfigDumpData } from '../../../data/configDump/configDump'; @@ -11,9 +10,10 @@ import { } from '../../../webworker/workers/browser/libsession_worker_interface'; import { GetNetworkTime } from '../../apis/snode_api/getNetworkTime'; import { SnodeNamespaces } from '../../apis/snode_api/namespaces'; -import { getConversationController } from '../../conversations'; import { SharedConfigMessage } from '../../messages/outgoing/controlMessage/SharedConfigMessage'; import { ConfigurationSync } from '../job_runners/jobs/ConfigurationSyncJob'; +import { SessionUtilContact } from './libsession_utils_contacts'; +import { SessionUtilUserProfile } from './libsession_utils_user_profile'; // TODO complete this list const requiredUserDumpVariants: Array = ['UserConfig', 'ContactsConfig']; // 'conversations' @@ -32,29 +32,6 @@ export type OutgoingConfResult = { oldMessageHashes: Array; }; -async function insertUserProfileIntoWrapperIfChanged() { - const us = UserUtils.getOurPubKeyStrFromCache(); - const ourConvo = getConversationController().get(us); - - if (!ourConvo) { - throw new Error('insertUserProfileIntoWrapper needs a ourConvo to exist'); - } - const wrapperName = await UserConfigWrapperActions.getName(); - const wrapperProfilePicture = await UserConfigWrapperActions.getProfilePicture(); - const wrapperProfileUrl = wrapperProfilePicture.url || ''; - const wrapperProfileKey = wrapperProfilePicture.key || ''; - - const dbName = ourConvo.get('displayNameInProfile') || ''; - const dbProfileUrl = ourConvo.get('avatarPointer') || ''; - const dbProfileKey = from_hex(ourConvo.get('profileKey') || ''); - if (!isEqual(dbName, wrapperName)) { - await UserConfigWrapperActions.setName(dbName); - } - if (!isEqual(dbProfileUrl, wrapperProfileUrl) || !isEqual(dbProfileKey, wrapperProfileKey)) { - await UserConfigWrapperActions.setProfilePicture(wrapperProfileUrl, dbProfileKey); - } -} - /** * Right after we migrated, we won't have any dumps in DB. We must create them from our database state, */ @@ -67,7 +44,7 @@ async function createConfigDumpsFromDbFirstStart( // build the userconfig await UserConfigWrapperActions.init(privateKeyEd25519, null); - await insertUserProfileIntoWrapperIfChanged(); + await SessionUtilUserProfile.insertUserProfileIntoWrapper(); const data = await UserConfigWrapperActions.dump(); // save it to the DB await ConfigDumpData.saveConfigDump({ @@ -224,6 +201,8 @@ export const LibSessionUtil = { initializeLibSessionUtilWrappers, requiredUserDumpVariants, pendingChangesForPubkey, + insertUserProfileIntoWrapper: SessionUtilUserProfile.insertUserProfileIntoWrapper, + insertAllContactsIntoContactsWrapper: SessionUtilContact.insertAllContactsIntoContactsWrapper, kindToVariant, markAsPushed, }; diff --git a/ts/session/utils/libsession/libsession_utils_contacts.ts b/ts/session/utils/libsession/libsession_utils_contacts.ts new file mode 100644 index 000000000..a6f0389e6 --- /dev/null +++ b/ts/session/utils/libsession/libsession_utils_contacts.ts @@ -0,0 +1,97 @@ +import { isEmpty, isEqual } from 'lodash'; +import { UserUtils } from '..'; +import { ConversationModel } from '../../../models/conversation'; +import { BlockedNumberController } from '../../../util'; +import { ContactsWrapperActions } from '../../../webworker/workers/browser/libsession_worker_interface'; +import { getConversationController } from '../../conversations'; +import { PubKey } from '../../types'; +import { fromHexToArray } from '../String'; + +/** + * Update the ContactWrapper with all the data is cares about from the database. + */ +async function insertAllContactsIntoContactsWrapper() { + console.error( + 'we need to find a way to keep track of what was changed as ids and only insert those in the wrapper' + ); + const idsToInsert = getConversationController() + .getConversations() + .filter(filterContactsToStoreInContactsWrapper) + .map(m => m.id); + + window.log.debug(`ContactsWrapper keep tracks of ${idsToInsert.length} contacts`); + + for (let index = 0; index < idsToInsert.length; index++) { + const id = idsToInsert[index]; + console.warn(`inserting into wrapper ${id}`); + await insertContactFromDBIntoWrapper(id); + } +} + +/** + * Returns true if that conversation is not us, is private, is not blinded and has either the + * `isApproved` or `didApproveMe` field set. + * So that would be all the private conversations we either sent or receive a message from, not blinded + */ +function filterContactsToStoreInContactsWrapper(convo: ConversationModel): boolean { + return ( + !convo.isMe() && + convo.isPrivate() && + !PubKey.hasBlindedPrefix(convo.id) && + (convo.isApproved() || convo.didApproveMe()) + ); +} + +/** + * Fetches the specified convo and updates the required field in the wrapper. + * If that contact does not exist in the wrapper, it is created before being updated. + */ +async function insertContactFromDBIntoWrapper(id: string): Promise { + const us = UserUtils.getOurPubKeyStrFromCache(); + if (id === us) { + window.log.info( + "The contact config wrapper does not handle the current user config, just his contacts'" + ); + return; + } + + const foundConvo = getConversationController().get(id); + if (!foundConvo) { + return; + } + + const dbName = foundConvo.get('displayNameInProfile') || undefined; + const dbNickname = foundConvo.get('nickname') || undefined; + const dbProfileUrl = foundConvo.get('avatarPointer') || undefined; + const dbProfileKey = foundConvo.get('profileKey') || undefined; + const dbApproved = foundConvo.get('isApproved') || false; + const dbApprovedMe = foundConvo.get('didApproveMe') || false; + const dbBlocked = BlockedNumberController.isBlocked(id) || false; + + const wrapperContact = await ContactsWrapperActions.getOrCreate(id); + + // override the values with what we have in the DB. the library will do the diff + wrapperContact.approved = dbApproved; + wrapperContact.approvedMe = dbApprovedMe; + wrapperContact.blocked = dbBlocked; + wrapperContact.name = dbName; + wrapperContact.nickname = dbNickname; + + if ( + wrapperContact.profilePicture?.url !== dbProfileUrl || + !isEqual(wrapperContact.profilePicture?.key, dbProfileKey) + ) { + wrapperContact.profilePicture = { + url: dbProfileUrl || null, + key: dbProfileKey && !isEmpty(dbProfileKey) ? fromHexToArray(dbProfileKey) : null, + }; + } + console.time('ContactsWrapperActions.set'); + await ContactsWrapperActions.set(wrapperContact); + console.timeEnd('ContactsWrapperActions.set'); +} + +export const SessionUtilContact = { + filterContactsToStoreInContactsWrapper, + insertAllContactsIntoContactsWrapper, +}; diff --git a/ts/session/utils/libsession/libsession_utils_user_profile.ts b/ts/session/utils/libsession/libsession_utils_user_profile.ts new file mode 100644 index 000000000..d24e7ffea --- /dev/null +++ b/ts/session/utils/libsession/libsession_utils_user_profile.ts @@ -0,0 +1,29 @@ +import { isEmpty } from 'lodash'; +import { UserUtils } from '..'; +import { UserConfigWrapperActions } from '../../../webworker/workers/browser/libsession_worker_interface'; +import { getConversationController } from '../../conversations'; +import { fromHexToArray } from '../String'; + +async function insertUserProfileIntoWrapper() { + const us = UserUtils.getOurPubKeyStrFromCache(); + const ourConvo = getConversationController().get(us); + + if (!ourConvo) { + throw new Error('insertUserProfileIntoWrapper needs a ourConvo to exist'); + } + + const dbName = ourConvo.get('displayNameInProfile') || ''; + const dbProfileUrl = ourConvo.get('avatarPointer') || ''; + const dbProfileKey = fromHexToArray(ourConvo.get('profileKey') || ''); + await UserConfigWrapperActions.setName(dbName); + + if (dbProfileUrl && !isEmpty(dbProfileKey)) { + await UserConfigWrapperActions.setProfilePicture(dbProfileUrl, dbProfileKey); + } else { + await UserConfigWrapperActions.setProfilePicture('', new Uint8Array()); + } +} + +export const SessionUtilUserProfile = { + insertUserProfileIntoWrapper, +}; diff --git a/ts/test/session/unit/libsession_wrapper/libsession_wrapper_contacts_test.ts b/ts/test/session/unit/libsession_wrapper/libsession_wrapper_contacts_test.ts index 34449d954..04dcae4cb 100644 --- a/ts/test/session/unit/libsession_wrapper/libsession_wrapper_contacts_test.ts +++ b/ts/test/session/unit/libsession_wrapper/libsession_wrapper_contacts_test.ts @@ -1,10 +1,16 @@ import { expect } from 'chai'; import { from_hex, from_string } from 'libsodium-wrappers-sumo'; +import Sinon from 'sinon'; +import { ConversationModel } from '../../../../models/conversation'; +import { ConversationTypeEnum } from '../../../../models/conversationAttributes'; +import { UserUtils } from '../../../../session/utils'; +import { SessionUtilContact } from '../../../../session/utils/libsession/libsession_utils_contacts'; // tslint:disable: chai-vague-errors no-unused-expression no-http-string no-octal-literal whitespace no-require-imports variable-name // import * as SessionUtilWrapper from 'session_util_wrapper'; +// tslint:disable-next-line: max-func-body-length describe('libsession_contacts', () => { // Note: To run this test, you need to compile the libsession wrapper for node (and not for electron). // To do this, you can cd to the node_module/libsession_wrapper folder and do @@ -13,7 +19,7 @@ describe('libsession_contacts', () => { // We have to disable it by filename as nodejs tries to load the module during the import step above, and fails as it is not compiled for nodejs but for electron. - it('libsession_contacts', () => { + it('libsession_contacts1', () => { const edSecretKey = from_hex( '0123456789abcdef0123456789abcdef000000000000000000000000000000004cb76fdc6d32278e3f83dbf608360ecc6b65727934b85d2fb86862ff98c46ab7' ); @@ -68,12 +74,13 @@ describe('libsession_contacts', () => { expect(updated?.profilePicture).to.be.undefined; - created.profilePicture = { key: new Uint8Array([1, 2, 3]), url: 'fakeUrl' }; + const plop = new Uint8Array(32).fill(6); + created.profilePicture = { key: plop, url: 'fakeUrl' }; contacts.set(created); const updated2 = contacts.get(real_id); expect(updated2?.profilePicture?.url).to.be.deep.eq('fakeUrl'); - expect(updated2?.profilePicture?.key).to.be.deep.eq(new Uint8Array([1, 2, 3])); + expect(updated2?.profilePicture?.key).to.be.deep.eq(plop); expect(contacts.needsPush()).to.be.eql(true); expect(contacts.needsDump()).to.be.eql(true); @@ -144,7 +151,11 @@ describe('libsession_contacts', () => { contacts2.setNickname(third_id, 'Nickname 3'); contacts2.setApproved(third_id, true); contacts2.setBlocked(third_id, true); - contacts2.setProfilePicture(third_id, 'http://example.com/huge.bmp', from_string('qwerty')); + contacts2.setProfilePicture( + third_id, + 'http://example.com/huge.bmp', + from_string('qwert\0yuio1234567890123456789012') + ); expect(contacts.needsPush()).to.be.true; expect(contacts2.needsPush()).to.be.true; @@ -186,7 +197,7 @@ describe('libsession_contacts', () => { expect(nicknames2).to.be.deep.eq(['(N/A)', 'Nickname 3']); }); - it('libsession_contacts_c', () => { + it('libsession_contacts2_c', () => { const edSecretKey = from_hex( '0123456789abcdef0123456789abcdef000000000000000000000000000000004cb76fdc6d32278e3f83dbf608360ecc6b65727934b85d2fb86862ff98c46ab7' ); @@ -291,4 +302,91 @@ describe('libsession_contacts', () => { expect(contacts.get(realId)).to.exist; expect(contacts.get(another_id)).to.be.null; }); + + describe('filter contacts for wrapper', () => { + const ourNumber = '051234567890acbdef'; + const validArgs = { + id: '051111567890acbdef', + type: ConversationTypeEnum.PRIVATE, + isApproved: true, + didApproveMe: true, + }; + beforeEach(() => { + Sinon.stub(UserUtils, 'getOurPubKeyStrFromCache').returns(ourNumber); + }); + afterEach(() => { + Sinon.restore(); + }); + + it('excludes ourselves', () => { + expect( + SessionUtilContact.filterContactsToStoreInContactsWrapper( + new ConversationModel({ ...validArgs, id: ourNumber } as any) + ) + ).to.be.eq(false); + }); + + it('excludes non private', () => { + expect( + SessionUtilContact.filterContactsToStoreInContactsWrapper( + new ConversationModel({ ...validArgs, type: ConversationTypeEnum.GROUP } as any) + ) + ).to.be.eq(false); + }); + + it('includes private', () => { + expect( + SessionUtilContact.filterContactsToStoreInContactsWrapper( + new ConversationModel({ ...validArgs, type: ConversationTypeEnum.PRIVATE } as any) + ) + ).to.be.eq(true); + }); + + it('excludes blinded', () => { + expect( + SessionUtilContact.filterContactsToStoreInContactsWrapper( + new ConversationModel({ + ...validArgs, + type: ConversationTypeEnum.PRIVATE, + id: '1511111111111', + } as any) + ) + ).to.be.eq(false); + }); + + it('excludes non approved by us nor did approveme', () => { + expect( + SessionUtilContact.filterContactsToStoreInContactsWrapper( + new ConversationModel({ + ...validArgs, + didApproveMe: false, + isApproved: false, + } as any) + ) + ).to.be.eq(false); + }); + + it('includes approved only by us ', () => { + expect( + SessionUtilContact.filterContactsToStoreInContactsWrapper( + new ConversationModel({ + ...validArgs, + didApproveMe: false, + isApproved: true, + } as any) + ) + ).to.be.eq(true); + }); + it('includes approved only by them ', () => { + expect( + SessionUtilContact.filterContactsToStoreInContactsWrapper( + new ConversationModel({ + ...validArgs, + didApproveMe: true, + isApproved: false, + } as any) + ) + ).to.be.eq(true); + }); + }); }); diff --git a/ts/test/session/unit/libsession_wrapper/libsession_wrapper_test.ts b/ts/test/session/unit/libsession_wrapper/libsession_wrapper_test.ts index 54f7d4760..a43d2317a 100644 --- a/ts/test/session/unit/libsession_wrapper/libsession_wrapper_test.ts +++ b/ts/test/session/unit/libsession_wrapper/libsession_wrapper_test.ts @@ -1,11 +1,13 @@ import { expect } from 'chai'; import { stringToUint8Array } from '../../../../session/utils/String'; -import { from_hex, to_hex } from 'libsodium-wrappers-sumo'; +import { from_hex, from_string, to_hex } from 'libsodium-wrappers-sumo'; import { concatUInt8Array } from '../../../../session/crypto'; // tslint:disable: chai-vague-errors no-unused-expression no-http-string no-octal-literal whitespace no-require-imports variable-name +const fakeKey32 = from_string('secret78901234567890123456789012'); + describe('libsession_wrapper', () => { it('libsession_user', () => { // Note: To run this test, you need to compile the libsession wrapper for node (and not for electron). @@ -46,13 +48,8 @@ describe('libsession_wrapper', () => { expect(picResult.key).to.be.null; // Now let's go set a profile name and picture: - conf.setProfilePicture( - 'http://example.org/omg-pic-123.bmp', - new Uint8Array([115, 101, 99, 114, 101, 116]) // 'secret' in ascii - ); - expect(conf.getProfilePicture().key).to.be.deep.eq( - new Uint8Array([115, 101, 99, 114, 101, 116]) // 'secret' in ascii - ); + conf.setProfilePicture('http://example.org/omg-pic-123.bmp', new Uint8Array(fakeKey32)); + expect(conf.getProfilePicture().key).to.be.deep.eq(new Uint8Array(fakeKey32)); conf.setName('Kallie'); @@ -65,9 +62,7 @@ describe('libsession_wrapper', () => { const picture = conf.getProfilePicture(); expect(picture.url).to.be.eq('http://example.org/omg-pic-123.bmp'); - expect(picture.key).to.be.deep.eq( - new Uint8Array([115, 101, 99, 114, 101, 116]) // 'secret' in ascii - ); + expect(picture.key).to.be.deep.eq(new Uint8Array(fakeKey32)); // Since we've made changes, we should need to push new config to the swarm, *and* should need // to dump the updated state: @@ -83,7 +78,7 @@ describe('libsession_wrapper', () => { const expHash0 = from_hex('ea173b57beca8af18c3519a7bbf69c3e7a05d1c049fa9558341d8ebb48b0c965'); const expPush1Start = - 'd1:#i1e1:&d1:n6:Kallie1:p34:http://example.org/omg-pic-123.bmp1:q6:secrete1: { stringToUint8Array(expPush1End) ); const expPush1Encrypted = from_hex( - 'a2952190dcb9797bc48e48f6dc7b3254d004bde9091cfc9ec3433cbc5939a3726deb04f58a546d7d79e6f80ea185d43bf93278398556304998ae882304075c77f15c67f9914c4d10005a661f29ff7a79e0a9de7f21725ba3b5a6c19eaa3797671b8fa4008d62e9af2744629cbb46664c4d8048e2867f66ed9254120371bdb24e95b2d92341fa3b1f695046113a768ceb7522269f937ead5591bfa8a5eeee3010474002f2db9de043f0f0d1cfb1066a03e7b5d6cfb70a8f84a20cd2df5a510cd3d175708015a52dd4a105886d916db0005dbea5706e5a5dc37ffd0a0ca2824b524da2e2ad181a48bb38e21ed9abe136014a4ee1e472cb2f53102db2a46afa9d68' + '877c8e0f5d33f5fffa5a4e162785a9a89918e95de1c4b925201f1f5c29d9ee4f8c36e2b278fce1e6b9d999689dd86ff8e79e0a04004fa54d24da89bc2604cb1df8c1356da8f14710543ecec44f2d57fc56ea8b7e73d119c69d755f4d513d5d069f02396b8ec0cbed894169836f57ca4b782ce705895c593b4230d50c175d44a08045388d3f4160bacb617b9ae8de3ebc8d9024245cd09ce102627cab2acf1b9126159211359606611ca5814de320d1a7099a65c99b0eebbefb92a115f5efa6b9132809300ac010c6857cfbd62af71b0fa97eccec75cb95e67edf40b35fdb9cad125a6976693ab085c6bba96a2e51826e81e16b9ec1232af5680f2ced55310486' ); expect(to_hex(pushResult.data)).to.be.deep.eq(to_hex(expPush1Encrypted)); @@ -150,7 +145,10 @@ describe('libsession_wrapper', () => { conf2.setName('Raz'); // And, on conf2, we're also going to change the profile pic: - conf2.setProfilePicture('http://new.example.com/pic', stringToUint8Array('qwert\0yuio')); + conf2.setProfilePicture( + 'http://new.example.com/pic', + stringToUint8Array('qwert\0yuio1234567890123456789012') + ); // Both have changes, so push need a push expect(conf.needsPush()).to.be.true; @@ -201,8 +199,8 @@ describe('libsession_wrapper', () => { expect(pic.url).to.be.eq('http://new.example.com/pic'); expect(pic2.url).to.be.eq('http://new.example.com/pic'); - expect(pic.key).to.be.deep.eq(stringToUint8Array('qwert\0yuio')); - expect(pic2.key).to.be.deep.eq(stringToUint8Array('qwert\0yuio')); + expect(pic.key).to.be.deep.eq(stringToUint8Array('qwert\0yuio1234567890123456789012')); + expect(pic2.key).to.be.deep.eq(stringToUint8Array('qwert\0yuio1234567890123456789012')); conf.confirmPushed(pushResult.seqno); conf2.confirmPushed(pushResult2.seqno); diff --git a/ts/test/session/unit/receiving/ClosedGroupUpdates_test.ts b/ts/test/session/unit/receiving/ClosedGroupUpdates_test.ts index efc96bcd5..26140e9d4 100644 --- a/ts/test/session/unit/receiving/ClosedGroupUpdates_test.ts +++ b/ts/test/session/unit/receiving/ClosedGroupUpdates_test.ts @@ -8,7 +8,6 @@ chai.use(chaiAsPromised as any); // tslint:disable-next-line: max-func-body-length describe('ClosedGroupUpdates', () => { - //FIXME AUDRIC TODO // const ourDevice = TestUtils.generateFakePubKey(); // const ourNumber = ourDevice.key; // const groupId = TestUtils.generateFakePubKey().key; diff --git a/ts/test/session/unit/receiving/ConfigurationMessage_test.ts b/ts/test/session/unit/receiving/ConfigurationMessage_test.ts index ee4669f34..95cdb25b6 100644 --- a/ts/test/session/unit/receiving/ConfigurationMessage_test.ts +++ b/ts/test/session/unit/receiving/ConfigurationMessage_test.ts @@ -51,7 +51,7 @@ describe('ConfigurationMessage_receiving', () => { const proto = config.contentProto(); createOrUpdateStub = stubData('createOrUpdateItem').resolves(); getItemByIdStub = stubData('getItemById').resolves(); - await ConfigMessageHandler.handleConfigurationMessage( + await ConfigMessageHandler.handleConfigurationMessageLegacy( envelope, proto.configurationMessage as SignalService.ConfigurationMessage ); @@ -73,7 +73,7 @@ describe('ConfigurationMessage_receiving', () => { createOrUpdateStub = stubData('createOrUpdateItem').resolves(); getItemByIdStub = stubData('getItemById').resolves(); - await ConfigMessageHandler.handleConfigurationMessage( + await ConfigMessageHandler.handleConfigurationMessageLegacy( envelope, proto.configurationMessage as SignalService.ConfigurationMessage ); @@ -87,7 +87,7 @@ describe('ConfigurationMessage_receiving', () => { // createOrUpdateStub = sandbox.stub(data, 'createOrUpdateItem').resolves(); // getItemByIdStub = sandbox.stub(data, 'getItemById').resolves(); - // await handleConfigurationMessage(envelope, proto.configurationMessage as SignalService.ConfigurationMessage); + // await handleConfigurationMessageLegacy(envelope, proto.configurationMessage as SignalService.ConfigurationMessage); // expect(getItemByIdStub.callCount).to.equal(1); // }); }); diff --git a/ts/types/attachments/VisualAttachment.ts b/ts/types/attachments/VisualAttachment.ts index 65d8cc6ca..9a940b589 100644 --- a/ts/types/attachments/VisualAttachment.ts +++ b/ts/types/attachments/VisualAttachment.ts @@ -37,7 +37,7 @@ export const getImageDimensions = async ({ window.log.error('getImageDimensions error', toLogFormat(error)); reject(error); }); - // TODO image/jpeg is hard coded, but it does not look to cause any issues + // TODO image/jpg is hard coded, but it does not look to cause any issues const decryptedUrl = await getDecryptedMediaUrl(objectUrl, 'image/jpg', false); image.src = decryptedUrl; }); diff --git a/ts/webworker/worker_interface.ts b/ts/webworker/worker_interface.ts index c5989ef1b..935e53e8d 100644 --- a/ts/webworker/worker_interface.ts +++ b/ts/webworker/worker_interface.ts @@ -43,6 +43,7 @@ export class WorkerInterface { const { resolve, reject, fnName } = job; if (errorForDisplay) { + console.error(`Error received from worker job ${jobId} (${fnName}):`, errorForDisplay); return reject( new Error(`Error received from worker job ${jobId} (${fnName}): ${errorForDisplay}`) );