feat: insert all contacts into wrapper before syncing it

pull/2620/head
Audric Ackermann 3 years ago
parent 22329bc745
commit b2237efe51

@ -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<Incomin
if (!result.needsDump) {
return result;
}
const us = UserUtils.getOurPubKeyStrFromCache();
const allContacts = await ContactsWrapperActions.getAll();
for (let index = 0; index < allContacts.length; index++) {
const wrapperConvo = allContacts[index];
if (wrapperConvo.id && getConversationController().get(wrapperConvo.id)) {
const existingConvo = getConversationController().get(wrapperConvo.id);
if (wrapperConvo.id === us) {
// our profile update comes from our userProfile, not from the contacts wrapper.
continue;
}
const existingConvo = await getConversationController().getOrCreateAndWait(
wrapperConvo.id,
ConversationTypeEnum.PRIVATE
);
if (wrapperConvo.id && existingConvo) {
let changes = false;
// Note: the isApproved and didApproveMe flags are irreversible so they should only be updated when getting set to true
if (
existingConvo.get('isApproved') !== undefined &&
wrapperConvo.approved !== undefined &&
!isNil(existingConvo.get('isApproved')) &&
!isNil(wrapperConvo.approved) &&
existingConvo.get('isApproved') !== wrapperConvo.approved
) {
await existingConvo.setIsApproved(wrapperConvo.approved, false);
@ -94,8 +106,8 @@ async function handleContactsUpdate(result: IncomingConfResult): Promise<Incomin
}
if (
existingConvo.get('didApproveMe') !== undefined &&
wrapperConvo.approvedMe !== undefined &&
!isNil(existingConvo.get('didApproveMe')) &&
!isNil(wrapperConvo.approvedMe) &&
existingConvo.get('didApproveMe') !== wrapperConvo.approvedMe
) {
await existingConvo.setDidApproveMe(wrapperConvo.approvedMe, false);
@ -201,7 +213,6 @@ async function processMergingResults(
return;
}
await removeFromCache(envelope);
// Now that the local state has been updated, trigger a config sync (this will push any
// pending updates and properly update the state)
if (result.result.needsPush) {
@ -233,7 +244,7 @@ async function handleConfigMessageViaLibSession(
await processMergingResults(envelope, incomingMergeResult);
}
async function handleOurProfileUpdate(
async function handleOurProfileUpdateLegacy(
sentAt: number | Long,
configMessage: SignalService.ConfigurationMessage
) {
@ -260,10 +271,13 @@ async function handleOurProfileUpdate(
}
}
async function handleGroupsAndContactsFromConfigMessage(
async function handleGroupsAndContactsFromConfigMessageLegacy(
envelope: EnvelopePlus,
configMessage: SignalService.ConfigurationMessage
) {
if (window.sessionFeatureFlags.useSharedUtilForUserConfig) {
return;
}
const envelopeTimestamp = _.toNumber(envelope.timestamp);
const lastConfigUpdate = await Data.getItemById(hasSyncedInitialConfigurationItem);
const lastConfigTimestamp = lastConfigUpdate?.timestamp;
@ -284,13 +298,15 @@ async function handleGroupsAndContactsFromConfigMessage(
// we only want to apply changes to closed groups if we never got them
// new opengroups get added when we get a new closed group message from someone, or a sync'ed message from outself creating the group
if (!lastConfigTimestamp) {
await handleClosedGroupsFromConfig(configMessage.closedGroups, envelope);
await handleClosedGroupsFromConfigLegacy(configMessage.closedGroups, envelope);
}
handleOpenGroupsFromConfig(configMessage.openGroups);
if (configMessage.contacts?.length) {
await Promise.all(configMessage.contacts.map(async c => 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<string>) => {
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<string>) => {
* 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<SignalService.ConfigurationMessage.IClosedGroup>,
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<void> {
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,
};

@ -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
);

@ -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<ConversationModel> {
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;

@ -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} `
// );
}
}

@ -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<ConfigurationSyncPersistedData>
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();

@ -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<ConfigWrapperObjectTypes> = ['UserConfig', 'ContactsConfig']; // 'conversations'
@ -32,29 +32,6 @@ export type OutgoingConfResult = {
oldMessageHashes: Array<string>;
};
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,
};

@ -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<void> {
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,
};

@ -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,
};

@ -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);
});
});
});

@ -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:<lli0e32:';
'd1:#i1e1:&d1:n6:Kallie1:p34:http://example.org/omg-pic-123.bmp1:q32:secret78901234567890123456789012e1:<lli0e32:';
const expPush1End = 'deee1:=d1:n0:1:p0:1:q0:ee';
// The data to be actually pushed, expanded like this to make it somewhat human-readable:
@ -93,7 +88,7 @@ describe('libsession_wrapper', () => {
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);

@ -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;

@ -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);
// });
});

@ -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;
});

@ -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}`)
);

Loading…
Cancel
Save