Bug fixes.

- Change environment variables.
- Refactor http getter.
- Add custom error state matcher.
- Hide create account component.
This commit is contained in:
Spencer Ofwiti
2021-02-12 09:32:08 +03:00
parent 8dc0eb24d8
commit 0be8bcd51a
14 changed files with 2391 additions and 631 deletions

38
src/assets/js/cic-meta/sync.d.ts vendored Normal file
View File

@@ -0,0 +1,38 @@
import { JSONSerializable } from './format';
import { Authoritative, Signer } from './auth';
import { VersionedSpec } from './constants';
declare class Envelope {
o: VersionedSpec;
constructor(payload: Object);
set(payload: Object): void;
get(): string;
toJSON(): string;
static fromJSON(s: string): Envelope;
unwrap(): Syncable;
}
declare class ArgPair {
k: string;
v: any;
constructor(k: string, v: any);
}
declare class Syncable implements JSONSerializable, Authoritative {
id: string;
timestamp: number;
m: any;
e: Envelope;
signer: Signer;
onwrap: (string: any) => void;
onauthenticate: (boolean: any) => void;
constructor(id: string, v: Object);
setSigner(signer: Signer): void;
digest(): string;
private wrap;
authenticate(full?: boolean): void;
sign(): void;
update(changes: Array<ArgPair>, changesDescription: string): void;
replace(o: Object, changesDescription: string): void;
merge(s: Syncable): void;
toJSON(): string;
static fromJSON(s: string): Syncable;
}
export { JSONSerializable, Syncable, ArgPair, Envelope };

View File

@@ -0,0 +1,246 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Envelope = exports.ArgPair = exports.Syncable = void 0;
var Automerge = __importStar(require("automerge"));
var constants_1 = require("./constants");
var fullSpec = {
name: 'cic',
version: '1',
ext: {
network: constants_1.cryptoSpec,
engine: constants_1.engineSpec,
},
};
var Envelope = /** @class */ (function () {
function Envelope(payload) {
this.o = fullSpec;
this.set(payload);
}
Envelope.prototype.set = function (payload) {
this.o['payload'] = payload;
};
Envelope.prototype.get = function () {
return this.o['payload'];
};
Envelope.prototype.toJSON = function () {
return JSON.stringify(this.o);
};
Envelope.fromJSON = function (s) {
var e = new Envelope(undefined);
e.o = JSON.parse(s);
return e;
};
Envelope.prototype.unwrap = function () {
return Syncable.fromJSON(this.o['payload']);
};
return Envelope;
}());
exports.Envelope = Envelope;
var ArgPair = /** @class */ (function () {
function ArgPair(k, v) {
this.k = k;
this.v = v;
}
return ArgPair;
}());
exports.ArgPair = ArgPair;
var SignablePart = /** @class */ (function () {
function SignablePart(s) {
this.s = s;
}
SignablePart.prototype.digest = function () {
return this.s;
};
return SignablePart;
}());
function orderDict(src) {
var dst;
if (Array.isArray(src)) {
dst = [];
src.forEach(function (v) {
if (typeof (v) == 'object') {
v = orderDict(v);
}
dst.push(v);
});
}
else {
dst = {};
Object.keys(src).sort().forEach(function (k) {
var v = src[k];
if (typeof (v) == 'object') {
v = orderDict(v);
}
dst[k] = v;
});
}
return dst;
}
var Syncable = /** @class */ (function () {
// TODO: Move data to sub-object so timestamp, id, signature don't collide
function Syncable(id, v) {
this.id = id;
var o = {
'id': id,
'timestamp': Math.floor(Date.now() / 1000),
'data': v,
};
//this.m = Automerge.from(v)
this.m = Automerge.from(o);
}
Syncable.prototype.setSigner = function (signer) {
var _this = this;
this.signer = signer;
this.signer.onsign = function (s) {
_this.wrap(s);
};
};
// TODO: To keep integrity, the non-link key/value pairs for each step also need to be hashed
Syncable.prototype.digest = function () {
var links = [];
Automerge.getAllChanges(this.m).forEach(function (ch) {
var op = ch['ops'];
ch['ops'].forEach(function (op) {
if (op['action'] == 'link') {
//console.log('op link', op);
links.push([op['obj'], op['value']]);
}
});
});
//return JSON.stringify(links);
var j = JSON.stringify(links);
return Buffer.from(j).toString('base64');
};
Syncable.prototype.wrap = function (s) {
this.m = Automerge.change(this.m, 'sign', function (doc) {
doc['signature'] = s;
});
this.e = new Envelope(this.toJSON());
if (this.onwrap !== undefined) {
this.onwrap(this.e);
}
};
// private _verifyLoop(i:number, history:Array<any>, signable:Signable, result:boolean) {
// if (!result) {
// this.onauthenticate(false);
// return;
// } else if (history.length == 0) {
// this.onauthenticate(true);
// return;
// }
// const h = history.shift()
// if (i % 2 == 0) {
// i++;
// signable = {
// digest: () => {
// return Automerge.save(h.snapshot)
// },
// };
// this._verifyLoop(i, history, signable, true);
// } else {
// i++;
// const signature = h.snapshot['signature'];
// console.debug('signature', signature, signable.digest());
// this.signer.onverify = (v) => {
// this._verifyLoop(i, history, signable, v)
// }
// this.signer.verify(signable, signature);
// }
// }
//
// // TODO: This should replay the graph and check signatures on each step
// public _authenticate(full:boolean=false) {
// let h = Automerge.getHistory(this.m);
// h.forEach((m) => {
// //console.debug(m.snapshot);
// });
// const signable = {
// digest: () => { return '' },
// }
// if (!full) {
// h = h.slice(h.length-2);
// }
// this._verifyLoop(0, h, signable, true);
// }
Syncable.prototype.authenticate = function (full) {
var _this = this;
if (full === void 0) { full = false; }
if (full) {
console.warn('only doing shallow authentication for now, sorry');
}
//console.log('authenticating', signable.digest());
//console.log('signature', this.m.signature);
this.signer.onverify = function (v) {
//this._verifyLoop(i, history, signable, v)
_this.onauthenticate(v);
};
this.signer.verify(this.m.signature.digest, this.m.signature);
};
Syncable.prototype.sign = function () {
//this.signer.prepare(this);
this.signer.sign(this.digest());
};
Syncable.prototype.update = function (changes, changesDescription) {
this.m = Automerge.change(this.m, changesDescription, function (m) {
changes.forEach(function (c) {
var path = c.k.split('.');
var target = m['data'];
while (path.length > 1) {
var part = path.shift();
target = target[part];
}
target[path[0]] = c.v;
});
m['timestamp'] = Math.floor(Date.now() / 1000);
});
};
Syncable.prototype.replace = function (o, changesDescription) {
this.m = Automerge.change(this.m, changesDescription, function (m) {
Object.keys(o).forEach(function (k) {
m['data'][k] = o[k];
});
Object.keys(m).forEach(function (k) {
if (o[k] == undefined) {
delete m['data'][k];
}
});
m['timestamp'] = Math.floor(Date.now() / 1000);
});
};
Syncable.prototype.merge = function (s) {
this.m = Automerge.merge(s.m, this.m);
};
Syncable.prototype.toJSON = function () {
var s = Automerge.save(this.m);
var o = JSON.parse(s);
var oo = orderDict(o);
return JSON.stringify(oo);
};
Syncable.fromJSON = function (s) {
var doc = Automerge.load(s);
var y = new Syncable(doc['id'], {});
y.m = doc;
return y;
};
return Syncable;
}());
exports.Syncable = Syncable;

View File

@@ -0,0 +1,264 @@
import * as Automerge from 'automerge';
import { JSONSerializable } from './format';
import { Authoritative, Signer, PGPSigner, Signable, Signature } from './auth';
import { engineSpec, cryptoSpec, networkSpec, VersionedSpec } from './constants';
const fullSpec: VersionedSpec = {
name: 'cic',
version: '1',
ext: {
network: cryptoSpec,
engine: engineSpec,
},
};
class Envelope {
o = fullSpec;
constructor(payload: Object) {
this.set(payload);
}
public set(payload: Object) {
this.o['payload'] = payload;
}
public get(): string {
return this.o['payload'];
}
public toJSON() {
return JSON.stringify(this.o);
}
public static fromJSON(s: string): Envelope {
const e = new Envelope(undefined);
e.o = JSON.parse(s);
return e;
}
public unwrap(): Syncable {
return Syncable.fromJSON(this.o['payload']);
}
}
class ArgPair {
k: string;
v: any;
constructor(k: string, v: any) {
this.k = k;
this.v = v;
}
}
class SignablePart implements Signable {
s: string;
constructor(s: string) {
this.s = s;
}
public digest(): string {
return this.s;
}
}
function orderDict(src) {
let dst;
if (Array.isArray(src)) {
dst = [];
src.forEach((v) => {
if (typeof (v) == 'object') {
v = orderDict(v);
}
dst.push(v);
});
} else {
dst = {};
Object.keys(src).sort().forEach((k) => {
let v = src[k];
if (typeof (v) == 'object') {
v = orderDict(v);
}
dst[k] = v;
});
}
return dst;
}
class Syncable implements JSONSerializable, Authoritative {
// TODO: Move data to sub-object so timestamp, id, signature don't collide
constructor(id: string, v: Object) {
this.id = id;
const o = {
id: id,
timestamp: Math.floor(Date.now() / 1000),
data: v,
};
// this.m = Automerge.from(v)
this.m = Automerge.from(o);
}
id: string;
timestamp: number;
m: any; // automerge object
e: Envelope;
signer: Signer;
onwrap: (string) => void;
onauthenticate: (boolean) => void;
public static fromJSON(s: string): Syncable {
const doc = Automerge.load(s);
let y = new Syncable(doc['id'], {});
y.m = doc;
return y;
}
public setSigner(signer: Signer) {
this.signer = signer;
this.signer.onsign = (s) => {
this.wrap(s);
};
}
// TODO: To keep integrity, the non-link key/value pairs for each step also need to be hashed
public digest(): string {
const links = [];
Automerge.getAllChanges(this.m).forEach((ch: Object) => {
const op: Array<any> = ch['ops'];
ch['ops'].forEach((op: Array<Object>) => {
if (op['action'] == 'link') {
// console.log('op link', op);
links.push([op['obj'], op['value']]);
}
});
});
// return JSON.stringify(links);
const j = JSON.stringify(links);
return Buffer.from(j).toString('base64');
}
private wrap(s: string) {
this.m = Automerge.change(this.m, 'sign', (doc) => {
doc['signature'] = s;
});
this.e = new Envelope(this.toJSON());
if (this.onwrap !== undefined) {
this.onwrap(this.e);
}
}
// private _verifyLoop(i:number, history:Array<any>, signable:Signable, result:boolean) {
// if (!result) {
// this.onauthenticate(false);
// return;
// } else if (history.length == 0) {
// this.onauthenticate(true);
// return;
// }
// const h = history.shift()
// if (i % 2 == 0) {
// i++;
// signable = {
// digest: () => {
// return Automerge.save(h.snapshot)
// },
// };
// this._verifyLoop(i, history, signable, true);
// } else {
// i++;
// const signature = h.snapshot['signature'];
// console.debug('signature', signature, signable.digest());
// this.signer.onverify = (v) => {
// this._verifyLoop(i, history, signable, v)
// }
// this.signer.verify(signable, signature);
// }
// }
//
// // TODO: This should replay the graph and check signatures on each step
// public _authenticate(full:boolean=false) {
// let h = Automerge.getHistory(this.m);
// h.forEach((m) => {
// //console.debug(m.snapshot);
// });
// const signable = {
// digest: () => { return '' },
// }
// if (!full) {
// h = h.slice(h.length-2);
// }
// this._verifyLoop(0, h, signable, true);
// }
public authenticate(full: boolean = false) {
if (full) {
console.warn('only doing shallow authentication for now, sorry');
}
// console.log('authenticating', signable.digest());
// console.log('signature', this.m.signature);
this.signer.onverify = (v) => {
// this._verifyLoop(i, history, signable, v)
this.onauthenticate(v);
};
this.signer.verify(this.m.signature.digest, this.m.signature);
}
public sign() {
// this.signer.prepare(this);
this.signer.sign(this.digest());
}
public update(changes: Array<ArgPair>, changesDescription: string) {
this.m = Automerge.change(this.m, changesDescription, (m) => {
changes.forEach((c) => {
let path = c.k.split('.');
let target = m['data'];
while (path.length > 1) {
const part = path.shift();
target = target[part];
}
target[path[0]] = c.v;
});
m['timestamp'] = Math.floor(Date.now() / 1000);
});
}
public replace(o: Object, changesDescription: string) {
this.m = Automerge.change(this.m, changesDescription, (m) => {
Object.keys(o).forEach((k) => {
m['data'][k] = o[k];
});
Object.keys(m).forEach((k) => {
if (o[k] == undefined) {
delete m['data'][k];
}
});
m['timestamp'] = Math.floor(Date.now() / 1000);
});
}
public merge(s: Syncable) {
this.m = Automerge.merge(s.m, this.m);
}
public toJSON(): string {
const s = Automerge.save(this.m);
const o = JSON.parse(s);
const oo = orderDict(o);
return JSON.stringify(oo);
}
}
export { JSONSerializable, Syncable, ArgPair, Envelope };