cic-stack/apps/cic-meta/tests/server.ts

363 lines
8.9 KiB
TypeScript
Raw Permalink Normal View History

2021-02-08 18:31:29 +01:00
import assert = require('assert');
import fs = require('fs');
import pgp = require('openpgp');
import sqlite = require('sqlite3');
import * as handlers from '../scripts/server/handlers';
2021-05-21 11:42:08 +02:00
import { Envelope, Syncable, ArgPair, PGPKeyStore, PGPSigner, KeyStore, Signer } from '@cicnet/crdt-meta';
import { SqliteAdapter } from '../src/db';
2021-02-08 18:31:29 +01:00
2021-10-25 20:51:08 +02:00
const hashOfFoo = '2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae';
2021-02-08 18:31:29 +01:00
function createKeystore() {
const pksa = fs.readFileSync(__dirname + '/privatekeys.asc', 'utf-8');
const pubksa = fs.readFileSync(__dirname + '/publickeys.asc', 'utf-8');
return new Promise<PGPKeyStore>((whohoo, doh) => {
let keystore = undefined;
try {
keystore = new PGPKeyStore('merman', pksa, pubksa, pubksa, pubksa, () => {
whohoo(keystore);
});
} catch(e) {
doh(e);
}
if (keystore === undefined) {
doh();
}
});
}
function createDatabase(sqlite_file:string):Promise<any> {
try {
fs.unlinkSync(sqlite_file);
} catch {
}
return new Promise((whohoo, doh) => {
//const db = new sqlite.Database(sqlite_file, (e) => {
const dbconf = {
name: sqlite_file,
port: undefined,
host: undefined,
user: undefined,
password: undefined,
}
const db = new SqliteAdapter(dbconf);//, (e) => {
// if (e) {
// doh(e);
// return;
// }
2021-10-25 20:51:08 +02:00
// get this from real sql files sources
2021-02-08 18:31:29 +01:00
const sql = `CREATE TABLE store (
id integer primary key autoincrement,
2021-10-25 20:51:08 +02:00
owner_fingerprint text default null,
2021-02-08 18:31:29 +01:00
hash char(64) not null unique,
2021-10-25 20:51:08 +02:00
content text not null,
mime_type text default null
2021-02-08 18:31:29 +01:00
);
`
console.log(sql);
db.query(sql, (e) => {
if (e) {
doh(e);
return;
}
whohoo(db);
});
// });
});
}
function wrap(s:Syncable, signer:Signer) {
return new Promise<Envelope>((whohoo, doh) => {
s.setSigner(signer);
s.onwrap = async (env) => {
if (env === undefined) {
doh();
return;
}
whohoo(env);
}
s.sign();
});
}
async function signData(d:string, keyStore:KeyStore) {
const digest = await pgp.message.fromText(d);
const opts = {
message: digest,
privateKeys: [keyStore.getPrivateKey()],
detached: true,
};
const signature = await pgp.sign(opts);
return {
data: signature.signature,
engine: 'pgp',
algo: 'sha256',
digest: d,
};
}
describe('server', async () => {
await it('put_client_then_retrieve', async () => {
const keystore = await createKeystore();
const signer = new PGPSigner(keystore);
const digest = 'deadbeef';
const s = new Syncable(digest, {
bar: 'baz',
});
const db = await createDatabase(__dirname + '/db.one.sqlite');
let env = await wrap(s, signer);
let j = env.toJSON();
const content = await handlers.handleClientMergePut(j, db, digest, keystore, signer);
assert(content); // true-ish
2021-10-25 20:51:08 +02:00
console.debug('content', content);
2021-02-08 18:31:29 +01:00
let v = await handlers.handleNoMergeGet(db, digest, keystore);
2021-10-25 20:51:08 +02:00
if (v === false) {
2021-02-08 18:31:29 +01:00
db.close();
assert.fail('');
}
2021-10-25 20:51:08 +02:00
db.close();
return;
2021-02-08 18:31:29 +01:00
v = await handlers.handleClientMergeGet(db, digest, keystore);
2021-10-25 20:51:08 +02:00
if (v === false) {
2021-02-08 18:31:29 +01:00
db.close();
assert.fail('');
}
db.close();
});
await it('client_merge', async () => {
const keystore = await createKeystore();
const signer = new PGPSigner(keystore);
const db = await createDatabase(__dirname + '/db.two.sqlite');
// create new, sign, wrap
const digest = 'deadbeef';
let s = new Syncable(digest, {
bar: 'baz',
});
await wrap(s, signer)
// create client branch, sign, wrap, and serialize
let update = new ArgPair('baz', 666)
s.update([update], 'client branch');
let env = await wrap(s, signer)
const j_client = env.toJSON();
// create server branch, sign, wrap, and serialize
update = new ArgPair('baz', [1,2,3]);
s.update([update], 'client branch');
env = await wrap(s, signer)
const j_server = env.toJSON();
assert.notDeepEqual(j_client, j_server);
let v = await handlers.handleClientMergePut(j_server, db, digest, keystore, signer);
assert(v); // true-ish
v = await handlers.handleClientMergePut(j_client, db, digest, keystore, signer);
assert(v); // true-ish
const j = await handlers.handleClientMergeGet(db, digest, keystore);
env = Envelope.fromJSON(j);
s = env.unwrap();
db.close();
});
await it('server_merge', async () => {
const keystore = await createKeystore();
const signer = new PGPSigner(keystore);
const db = await createDatabase(__dirname + '/db.three.sqlite');
const digest = 'deadbeef';
let s = new Syncable(digest, {
bar: 'baz',
});
let env = await wrap(s, signer)
let j:any = env.toJSON();
let v = await handlers.handleClientMergePut(j, db, digest, keystore, signer);
assert(v); // true-ish
j = await handlers.handleNoMergeGet(db, digest, keystore);
assert(v); // true-ish
2021-10-25 20:51:08 +02:00
let o = JSON.parse(j[0]);
2021-02-08 18:31:29 +01:00
o.bar = 'xyzzy';
j = JSON.stringify(o);
let signMaterial = await handlers.handleServerMergePost(j, db, digest, keystore, signer);
assert(signMaterial)
env = Envelope.fromJSON(signMaterial);
const w = env.unwrap();
console.log('jjjj', w, env);
const signedData = await signData(w.m.signature.digest, keystore);
o = {
'm': env,
's': signedData,
}
j = JSON.stringify(o);
v = await handlers.handleServerMergePut(j, db, digest, keystore, signer);
assert(v);
j = await handlers.handleNoMergeGet(db, digest, keystore);
assert(j); // true-ish
2021-10-25 20:51:08 +02:00
o = JSON.parse(j[0]);
2021-02-08 18:31:29 +01:00
console.log(o);
db.close();
});
2021-10-25 20:51:08 +02:00
// await it('server_merge', async () => {
// const keystore = await createKeystore();
// const signer = new PGPSigner(keystore);
//
// const db = await createDatabase(__dirname + '/db.three.sqlite');
//
// const digest = 'deadbeef';
// let s = new Syncable(digest, {
// bar: 'baz',
// });
// let env = await wrap(s, signer)
// let j:any = env.toJSON();
//
// let v = await handlers.handleClientMergePut(j, db, digest, keystore, signer);
// assert(v); // true-ish
//
// j = await handlers.handleNoMergeGet(db, digest, keystore);
// assert(v); // true-ish
//
// let o = JSON.parse(j);
// o.bar = 'xyzzy';
// j = JSON.stringify(o);
//
// let signMaterial = await handlers.handleServerMergePost(j, db, digest, keystore, signer);
// assert(signMaterial)
//
// env = Envelope.fromJSON(signMaterial);
//
// console.log('envvvv', env);
//
// const signedData = await signData(env.o['digest'], keystore);
// console.log('signed', signedData);
//
// o = {
// 'm': env,
// 's': signedData,
// }
// j = JSON.stringify(o);
// console.log(j);
//
// v = await handlers.handleServerMergePut(j, db, digest, keystore, signer);
// assert(v);
//
// j = await handlers.handleNoMergeGet(db, digest, keystore);
// assert(j); // true-ish
// o = JSON.parse(j);
// console.log(o);
//
// db.close();
// });
//
await it('server_merge_empty', async () => {
2021-02-08 18:31:29 +01:00
const keystore = await createKeystore();
const signer = new PGPSigner(keystore);
const db = await createDatabase(__dirname + '/db.three.sqlite');
2021-10-25 20:51:08 +02:00
const digest = '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef';
let o:any = {
foo: 'bar',
xyzzy: 42,
}
let j:any = JSON.stringify(o);
2021-02-08 18:31:29 +01:00
let signMaterial = await handlers.handleServerMergePost(j, db, digest, keystore, signer);
assert(signMaterial)
2021-10-25 20:51:08 +02:00
const env = Envelope.fromJSON(signMaterial);
2021-02-08 18:31:29 +01:00
console.log('envvvv', env);
const signedData = await signData(env.o['digest'], keystore);
console.log('signed', signedData);
o = {
'm': env,
's': signedData,
}
j = JSON.stringify(o);
console.log(j);
2021-10-25 20:51:08 +02:00
let v = await handlers.handleServerMergePut(j, db, digest, keystore, signer);
2021-02-08 18:31:29 +01:00
assert(v);
j = await handlers.handleNoMergeGet(db, digest, keystore);
assert(j); // true-ish
2021-10-25 20:51:08 +02:00
o = JSON.parse(j[0]);
2021-02-08 18:31:29 +01:00
console.log(o);
db.close();
});
2021-10-25 20:51:08 +02:00
await it('immutable_nodigest', async() => {
const keystore = await createKeystore();
const db = await createDatabase(__dirname + '/db.three.sqlite');
2021-02-08 18:31:29 +01:00
2021-10-25 20:51:08 +02:00
const s:string = 'foo';
let r;
r = await handlers.handleImmutablePost(s, db, undefined, keystore, 'text/plain');
assert(r[0]);
assert(hashOfFoo == r[1]);
2021-02-08 18:31:29 +01:00
2021-10-25 20:51:08 +02:00
r = await handlers.handleImmutablePost(s, db, undefined, keystore, 'text/plain');
assert(!r[0]);
assert(hashOfFoo == r[1]);
const b:Uint8Array = new TextEncoder().encode(s);
r = await handlers.handleImmutablePost(b, db, undefined, keystore, 'text/plain');
assert(!r[0]);
assert(hashOfFoo == r[1]);
});
await it('immutable_digest', async() => {
const keystore = await createKeystore();
const db = await createDatabase(__dirname + '/db.three.sqlite');
const s:string = 'foo';
const b:Uint8Array = new TextEncoder().encode(s);
let r;
r = await handlers.handleImmutablePost(b, db, hashOfFoo, keystore, 'application/octet-stream');
assert(r[0]);
assert(hashOfFoo == r[1]);
r = await handlers.handleImmutablePost(b, db, hashOfFoo, keystore, 'application/octet-stream');
assert(!r[0]);
assert(hashOfFoo == r[1]);
r = await handlers.handleImmutablePost(s, db, hashOfFoo, keystore, 'text/plain');
assert(!r[0]);
assert(hashOfFoo == r[1]);
});
2021-02-08 18:31:29 +01:00
});