Add connection to cic-meta.
This commit is contained in:
parent
0be8bcd51a
commit
9d2fdd687b
@ -1,9 +1,9 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import {BehaviorSubject, Observable} from 'rxjs';
|
import {BehaviorSubject, Observable, of} from 'rxjs';
|
||||||
import {HttpClient, HttpParams} from '@angular/common/http';
|
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
|
||||||
import {environment} from '../../environments/environment';
|
import {environment} from '../../environments/environment';
|
||||||
import {first, map} from 'rxjs/operators';
|
import {first, map} from 'rxjs/operators';
|
||||||
import {} from '../../assets/js/cic-meta/sync';
|
import { Envelope, Syncable } from '../../assets/js/cic-meta/sync.js';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -48,10 +48,37 @@ export class UserService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
changeAccountInfo(status: string, name: string, phoneNumber: string, type: string, token: string, failedPinAttempts: string, bio: string,
|
changeAccountInfo(address: string, status: string, name: string, phoneNumber: string, type: string, token: string,
|
||||||
gender: string, businessCategory: string, userLocation: string, location: string, referrer: string): Observable<any> {
|
failedPinAttempts: string, bio: string, gender: string, businessCategory: string, userLocation: string,
|
||||||
console.log(status);
|
location: string, referrer: string): Observable<any> {
|
||||||
return ;
|
const accountDetails = {
|
||||||
|
status,
|
||||||
|
name,
|
||||||
|
phoneNumber,
|
||||||
|
type,
|
||||||
|
token,
|
||||||
|
failedPinAttempts,
|
||||||
|
bio,
|
||||||
|
gender,
|
||||||
|
businessCategory,
|
||||||
|
userLocation,
|
||||||
|
location,
|
||||||
|
referrer
|
||||||
|
};
|
||||||
|
const addressStub = address.slice(2);
|
||||||
|
const headers = new HttpHeaders().append('x-cic-automerge', 'client');
|
||||||
|
this.http.get(`${environment.cicMetaUrl}/${addressStub}`, { headers }).pipe(first()).subscribe(res => {
|
||||||
|
console.log(res);
|
||||||
|
const response = Envelope.fromJSON(res);
|
||||||
|
response.unwrap();
|
||||||
|
console.log(response);
|
||||||
|
}, error => {
|
||||||
|
console.error('There is an error!', error);
|
||||||
|
});
|
||||||
|
this.http.put(`${environment.cicMetaUrl}/${addressStub}`, { data: accountDetails }, { headers }).pipe(first()).subscribe(res => {
|
||||||
|
console.log(res);
|
||||||
|
});
|
||||||
|
return of(addressStub);
|
||||||
}
|
}
|
||||||
|
|
||||||
getAccounts(): void {
|
getAccounts(): void {
|
||||||
@ -109,8 +136,4 @@ export class UserService {
|
|||||||
return response;
|
return response;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
changeUserCredentials(): void {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import {Component, OnInit, ViewChild} from '@angular/core';
|
import {Component, OnInit, ViewChild} from '@angular/core';
|
||||||
import {MatTableDataSource} from '@angular/material/table';
|
import {MatTableDataSource} from '@angular/material/table';
|
||||||
import {Transaction, User} from '../../../_models';
|
|
||||||
import {SelectionModel} from '@angular/cdk/collections';
|
import {SelectionModel} from '@angular/cdk/collections';
|
||||||
import {MatPaginator} from '@angular/material/paginator';
|
import {MatPaginator} from '@angular/material/paginator';
|
||||||
import {MatSort} from '@angular/material/sort';
|
import {MatSort} from '@angular/material/sort';
|
||||||
@ -158,9 +157,9 @@ export class AccountDetailsComponent implements OnInit {
|
|||||||
|
|
||||||
saveInfo(): void {
|
saveInfo(): void {
|
||||||
this.submitted = true;
|
this.submitted = true;
|
||||||
console.log(this.accountInfoFormStub.userLocation.value);
|
|
||||||
if (this.accountInfoForm.invalid) { return; }
|
if (this.accountInfoForm.invalid) { return; }
|
||||||
this.userService.changeAccountInfo(
|
this.userService.changeAccountInfo(
|
||||||
|
this.account.address,
|
||||||
this.accountInfoFormStub.status.value,
|
this.accountInfoFormStub.status.value,
|
||||||
this.accountInfoFormStub.name.value,
|
this.accountInfoFormStub.name.value,
|
||||||
this.accountInfoFormStub.phoneNumber.value,
|
this.accountInfoFormStub.phoneNumber.value,
|
||||||
|
24
src/assets/js/cic-meta/constants.js
Normal file
24
src/assets/js/cic-meta/constants.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.networkSpec = exports.cryptoSpec = exports.engineSpec = void 0;
|
||||||
|
var ENGINE_NAME = 'automerge';
|
||||||
|
var ENGINE_VERSION = '0.14.1';
|
||||||
|
var NETWORK_NAME = 'cic';
|
||||||
|
var NETWORK_VERSION = '1';
|
||||||
|
var CRYPTO_NAME = 'pgp';
|
||||||
|
var CRYPTO_VERSION = '2';
|
||||||
|
var engineSpec = {
|
||||||
|
name: ENGINE_NAME,
|
||||||
|
version: ENGINE_VERSION,
|
||||||
|
};
|
||||||
|
exports.engineSpec = engineSpec;
|
||||||
|
var cryptoSpec = {
|
||||||
|
name: CRYPTO_NAME,
|
||||||
|
version: CRYPTO_VERSION,
|
||||||
|
};
|
||||||
|
exports.cryptoSpec = cryptoSpec;
|
||||||
|
var networkSpec = {
|
||||||
|
name: NETWORK_NAME,
|
||||||
|
version: NETWORK_VERSION,
|
||||||
|
};
|
||||||
|
exports.networkSpec = networkSpec;
|
38
src/assets/js/cic-meta/sync.d.ts
vendored
38
src/assets/js/cic-meta/sync.d.ts
vendored
@ -1,38 +0,0 @@
|
|||||||
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 };
|
|
@ -1,264 +0,0 @@
|
|||||||
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 };
|
|
@ -2,6 +2,7 @@ export const environment = {
|
|||||||
production: true,
|
production: true,
|
||||||
cicCacheUrl: 'http://localhost:63313',
|
cicCacheUrl: 'http://localhost:63313',
|
||||||
cicScriptsUrl: 'http://localhost:9999',
|
cicScriptsUrl: 'http://localhost:9999',
|
||||||
|
cicMetaUrl: 'http://localhost:63380',
|
||||||
web3Provider: 'ws://localhost:8546',
|
web3Provider: 'ws://localhost:8546',
|
||||||
cicUssdUrl: 'http://localhost:63315',
|
cicUssdUrl: 'http://localhost:63315',
|
||||||
cicEthUrl: 'http://localhost:63314',
|
cicEthUrl: 'http://localhost:63314',
|
||||||
|
@ -6,6 +6,7 @@ export const environment = {
|
|||||||
production: false,
|
production: false,
|
||||||
cicCacheUrl: 'http://localhost:63313',
|
cicCacheUrl: 'http://localhost:63313',
|
||||||
cicScriptsUrl: 'http://localhost:9999',
|
cicScriptsUrl: 'http://localhost:9999',
|
||||||
|
cicMetaUrl: 'http://localhost:63380',
|
||||||
web3Provider: 'ws://localhost:8546',
|
web3Provider: 'ws://localhost:8546',
|
||||||
cicUssdUrl: 'http://localhost:63315',
|
cicUssdUrl: 'http://localhost:63315',
|
||||||
cicEthUrl: 'http://localhost:63314',
|
cicEthUrl: 'http://localhost:63314',
|
||||||
|
Loading…
Reference in New Issue
Block a user