feat: add dependency to our libsession wrapper for nodejs

also add a basic test to make sure it works
pull/2620/head
Audric Ackermann 1 year ago
parent 2a8d764bfb
commit 9749529e25

@ -150,6 +150,7 @@
"rimraf": "2.6.2",
"sanitize.css": "^12.0.1",
"semver": "5.4.1",
"session_util_wrapper": "https://github.com/oxen-io/libsession-util-nodejs",
"styled-components": "5.1.1",
"uuid": "8.3.2"
},

@ -0,0 +1,222 @@
import { expect } from 'chai';
import * as SessionUtilWrapper from 'session_util_wrapper';
import { stringToUint8Array } from '../../../../session/utils/String';
import { from_hex, to_hex } from 'libsodium-wrappers-sumo';
import { concatUInt8Array } from '../../../../session/crypto';
describe('libsession_wrapper', () => {
it.skip('[config][user_profile][c]', () => {
// 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
// yarn configure && yarn build
const edSecretKey = from_hex(
'0123456789abcdef0123456789abcdef000000000000000000000000000000004cb76fdc6d32278e3f83dbf608360ecc6b65727934b85d2fb86862ff98c46ab7'
);
// Initialize a brand new, empty config because we have no dump data to deal with.
const conf = new SessionUtilWrapper.UserConfigWrapper(edSecretKey, null);
// We don't need to push anything, since this is an empty config
expect(conf.needsPush()).to.be.eql(false);
expect(conf.needsDump()).to.be.eql(false);
// Since it's empty there shouldn't be a name.
expect(conf.getName()).to.be.null;
let pushResult = conf.push();
expect(pushResult.seqno).to.be.eq(0);
expect(pushResult.data.length).to.be.eq(256);
expect(conf.encryptionDomain()).to.be.eq('UserProfile');
expect(conf.storageNamespace()).to.be.eq(2);
expect(to_hex(pushResult.data)).to.be.deep.eq(
'9ffb5347e061ac40d937ae4f1a890031475bdc11653f94c8ae1d516ffda71d9ee9cdaf9fbaeb15d835cdc7b3b6ecc120361f004ff172dd5e757c80ede10e88945536e6841255a7bca73664ab8a0607fcfe2579c05bb3d9d4b34ac1de2921e703783ce39e317a512cb9d4e3b59176cbde47b5ba24a03065bf8fefe3e8ca2609e0ad10c7c9c3f81dc6d3a399bda0c190e8a228d0acb22863ab84c2d0c411be74dac4de1f8bc18539635db01ea1ef7f28e505703d67786cb419690edd4bd8c92926fc1d6449eaccc31d7d9639e1b36222e5672b87d1e34b7860308c3f40b3997f39fecf6ceb889323826fa69e001816307799fc9fed302a90faa1e43f7cd7367c3c'
);
// This should also be unset:
const picResult = conf.getProfilePic();
expect(picResult.url).to.be.null;
expect(picResult.key).to.be.null;
// Now let's go set a profile name and picture:
conf.setProfilePic('http://example.org/omg-pic-123.bmp', stringToUint8Array('secret'));
conf.setName('Kallie');
// Retrieve them just to make sure they set properly:
const name = conf.getName();
expect(name).to.be.not.null;
expect(name).to.be.eq('Kallie');
const picture = conf.getProfilePic();
expect(picture.url).to.be.eq('http://example.org/omg-pic-123.bmp');
expect(picture.key).to.be.deep.eq(stringToUint8Array('secret'));
// Since we've made changes, we should need to push new config to the swarm, *and* should need
// to dump the updated state:
expect(conf.needsDump()).to.be.true;
expect(conf.needsPush()).to.be.true;
// incremented since we made changes (this only increments once between
// dumps; even though we changed two fields here).
pushResult = conf.push();
expect(pushResult.seqno).to.be.eq(1);
const exp_hash0 = from_hex('ea173b57beca8af18c3519a7bbf69c3e7a05d1c049fa9558341d8ebb48b0c965');
// prettier-ignore
const exp_push1_start = "d" +
"1:#" +"i1e"+
"1:&" +"d"+
"1:n" +"6:Kallie"+
"1:p" +"34:http://example.org/omg-pic-123.bmp"+
"1:q" +"6:secret"+
"e"+
"1:<"+ "l"+
"l" +"i0e" +"32:" ;
// prettier-ignore
const exp_push1_end = "de"+ "e"+
"e"+
"1:="+ "d"+
"1:n" +"0:"+
"1:p" +"0:"+
"1:q" +"0:"+
"e"+
"e";
// The data to be actually pushed, expanded like this to make it somewhat human-readable:
const exp_push1_decrypted = concatUInt8Array(
stringToUint8Array(exp_push1_start),
exp_hash0,
stringToUint8Array(exp_push1_end)
);
const exp_push1_encrypted = from_hex(
'a2952190dcb9797bc48e48f6dc7b3254d004bde9091cfc9ec3433cbc5939a3726deb04f58a546d7d79e6f80ea185d43bf93278398556304998ae882304075c77f15c67f9914c4d10005a661f29ff7a79e0a9de7f21725ba3b5a6c19eaa3797671b8fa4008d62e9af2744629cbb46664c4d8048e2867f66ed9254120371bdb24e95b2d92341fa3b1f695046113a768ceb7522269f937ead5591bfa8a5eeee3010474002f2db9de043f0f0d1cfb1066a03e7b5d6cfb70a8f84a20cd2df5a510cd3d175708015a52dd4a105886d916db0005dbea5706e5a5dc37ffd0a0ca2824b524da2e2ad181a48bb38e21ed9abe136014a4ee1e472cb2f53102db2a46afa9d68'
);
expect(to_hex(pushResult.data)).to.be.deep.eq(to_hex(exp_push1_encrypted));
// We haven't dumped, so still need to dump:
expect(conf.needsDump()).to.be.true;
// We did call push, but we haven't confirmed it as stored yet, so this will still return true:
expect(conf.needsPush()).to.be.true;
let dumped = conf.dump();
// (in a real client we'd now store this to disk)
expect(conf.needsDump()).to.be.false;
// prettier-ignore
const expected_dump = concatUInt8Array(stringToUint8Array("d" +
"1:!" +"i2e"+
"1:$" + `${exp_push1_decrypted.length}` + ':'), exp_push1_decrypted, stringToUint8Array("e"));
expect(to_hex(dumped)).to.be.deep.eq(to_hex(expected_dump));
// So now imagine we got back confirmation from the swarm that the push has been stored:
conf.confirmPushed(pushResult.seqno);
expect(conf.needsPush()).to.be.false;
expect(conf.needsDump()).to.be.true;
conf.dump();
expect(conf.needsDump()).to.be.false;
// Now we're going to set up a second, competing config object (in the real world this would be
// another Session client somewhere).
// Start with an empty config, as above:
const conf2 = new SessionUtilWrapper.UserConfigWrapper(edSecretKey, null);
expect(conf2.needsDump()).to.be.false;
// Now imagine we just pulled down the encrypted string from the swarm; we merge it into conf2:
const accepted = conf2.merge([exp_push1_encrypted]);
expect(accepted).to.be.eq(1);
// Our state has changed, so we need to dump:
expect(conf2.needsDump()).to.be.true;
conf2.dump();
// (store in db)
expect(conf2.needsDump()).to.be.false;
// We *don't* need to push: even though we updated, all we did is update to the merged data (and
// didn't have any sort of merge conflict needed):
expect(conf2.needsPush()).to.be.false;
// Now let's create a conflicting update:
// Change the name on both clients:
conf.setName('Nibbler');
conf2.setName('Raz');
// And, on conf2, we're also going to change the profile pic:
conf2.setProfilePic('http://new.example.com/pic', stringToUint8Array('qwert\0yuio'));
// Both have changes, so push need a push
expect(conf.needsPush()).to.be.true;
expect(conf2.needsPush()).to.be.true;
pushResult = conf.push();
expect(pushResult.seqno).to.be.eq(2); // incremented, since we made a field change
let pushResult2 = conf2.push();
expect(pushResult2.seqno).to.be.eq(2); // incremented, since we made a field change
// (store in db)
conf.dump();
conf2.dump();
// Since we set different things, we're going to get back different serialized data to be
// pushed:
expect(to_hex(pushResult.data)).to.not.be.deep.eq(to_hex(pushResult2.data));
// Now imagine that each client pushed its `seqno=2` config to the swarm, but then each client
// also fetches new messages and pulls down the other client's `seqno=2` value.
// Feed the new config into each other. (This array could hold multiple configs if we pulled
// down more than one).
conf2.merge([pushResult.data]);
conf.merge([pushResult2.data]);
// Now after the merge we *will* want to push from both client, since both will have generated a
// merge conflict update (with seqno = 3).
expect(conf.needsPush()).to.be.true;
expect(conf2.needsPush()).to.be.true;
pushResult = conf.push();
pushResult2 = conf2.push();
expect(pushResult.seqno).to.be.eq(3);
expect(pushResult2.seqno).to.be.eq(3);
// They should have resolved the conflict to the same thing:
expect(conf.getName()).to.be.eq('Nibbler');
expect(conf2.getName()).to.be.eq('Nibbler');
// (Note that they could have also both resolved to "Raz" here, but the hash of the serialized
// message just happens to have a higher hash -- and thus gets priority -- for this particular
// test).
// Since only one of them set a profile pic there should be no conflict there:
const pic = conf.getProfilePic();
const pic2 = conf2.getProfilePic();
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'));
conf.confirmPushed(pushResult.seqno);
conf2.confirmPushed(pushResult2.seqno);
conf.dump();
conf2.dump();
// (store in db)
expect(conf.needsPush()).to.be.false;
expect(conf.needsDump()).to.be.false;
expect(conf2.needsPush()).to.be.false;
expect(conf2.needsDump()).to.be.false;
});
});

@ -2180,7 +2180,7 @@ abab@^2.0.5, abab@^2.0.6:
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==
abbrev@1:
abbrev@1, abbrev@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
@ -6569,6 +6569,11 @@ nan@^2.14.0, nan@^2.14.2:
resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee"
integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==
nan@^2.17.0:
version "2.17.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb"
integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==
nano-css@^5.3.1:
version "5.3.5"
resolved "https://registry.yarnpkg.com/nano-css/-/nano-css-5.3.5.tgz#3075ea29ffdeb0c7cb6d25edb21d8f7fa8e8fe8e"
@ -6657,6 +6662,22 @@ node-gyp@9.0.0:
tar "^6.1.2"
which "^2.0.2"
node-gyp@^9.3.0:
version "9.3.0"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.3.0.tgz#f8eefe77f0ad8edb3b3b898409b53e697642b319"
integrity sha512-A6rJWfXFz7TQNjpldJ915WFb1LnhO4lIve3ANPbWreuEoLoKlFT3sxIepPBkLhM27crW8YmN+pjlgbasH6cH/Q==
dependencies:
env-paths "^2.2.0"
glob "^7.1.4"
graceful-fs "^4.2.6"
make-fetch-happen "^10.0.3"
nopt "^6.0.0"
npmlog "^6.0.0"
rimraf "^3.0.2"
semver "^7.3.5"
tar "^6.1.2"
which "^2.0.2"
node-loader@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/node-loader/-/node-loader-2.0.0.tgz#9109a6d828703fd3e0aa03c1baec12a798071562"
@ -6683,6 +6704,13 @@ nopt@^5.0.0:
dependencies:
abbrev "1"
nopt@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-6.0.0.tgz#245801d8ebf409c6df22ab9d95b65e1309cdb16d"
integrity sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==
dependencies:
abbrev "^1.0.0"
nopt@~3.0.6:
version "3.0.6"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
@ -8175,6 +8203,14 @@ serialize-javascript@6.0.0:
dependencies:
randombytes "^2.1.0"
"session_util_wrapper@https://github.com/oxen-io/libsession-util-nodejs":
version "0.1.0"
resolved "https://github.com/oxen-io/libsession-util-nodejs#08bebd19042dee4d53f617bf93d51ab8fe9d8282"
dependencies:
bindings "^1.5.0"
nan "^2.17.0"
node-gyp "^9.3.0"
set-blocking@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"

Loading…
Cancel
Save