api: import updated version from the ios repo.

Improves types and adds functionality to getting crypto managers.
master
Tom Hacohen 5 years ago
parent 53930292ee
commit f5df8cb4e1

@ -3,6 +3,9 @@ import { USER, PASSWORD, keyBase64 } from './TestConstants';
import { stringToByteArray } from './Helpers'; import { stringToByteArray } from './Helpers';
import * as sjcl from 'sjcl';
sjcl.random.addEntropy('seedForTheTests', 1024, 'FakeSeed');
it('Derive key', () => { it('Derive key', () => {
const derived = deriveKey(USER, PASSWORD); const derived = deriveKey(USER, PASSWORD);
expect(derived).toBe(keyBase64); expect(derived).toBe(keyBase64);

@ -6,6 +6,9 @@ const testApiBase = 'http://localhost:8000';
import { USER, PASSWORD, keyBase64 } from './TestConstants'; import { USER, PASSWORD, keyBase64 } from './TestConstants';
sjcl.random.addEntropy('seedForTheTests', 1024, 'FakeSeed');
let credentials: EteSync.Credentials; let credentials: EteSync.Credentials;
beforeEach(async () => { beforeEach(async () => {

@ -4,7 +4,7 @@ import URI from 'urijs';
import * as Constants from './Constants'; import * as Constants from './Constants';
import { byte, base64, stringToByteArray } from './Helpers'; import { byte, base64, stringToByteArray } from './Helpers';
import { CryptoManager, AsymmetricKeyPair, HMAC_SIZE_BYTES } from './Crypto'; import { CryptoManager, AsymmetricCryptoManager, AsymmetricKeyPair, HMAC_SIZE_BYTES } from './Crypto';
export { CryptoManager, AsymmetricCryptoManager, AsymmetricKeyPair, deriveKey, genUid } from './Crypto'; export { CryptoManager, AsymmetricCryptoManager, AsymmetricKeyPair, deriveKey, genUid } from './Crypto';
type URI = typeof URI; type URI = typeof URI;
@ -83,7 +83,7 @@ class BaseItem<T extends BaseItemJson> {
protected _content?: object; protected _content?: object;
constructor() { constructor() {
this._json = {} as any; this._json = {} as T;
} }
public deserialize(json: T) { public deserialize(json: T) {
@ -131,9 +131,13 @@ export interface JournalJson extends BaseJson {
} }
export class Journal extends BaseJournal<JournalJson> { export class Journal extends BaseJournal<JournalJson> {
constructor(version: number = Constants.CURRENT_VERSION) { constructor(initial?: Partial<JournalJson>, version: number = Constants.CURRENT_VERSION) {
super(); super();
this._json.version = version; this._json = {
...this._json,
version,
...initial,
};
} }
get key(): byte[] | undefined { get key(): byte[] | undefined {
@ -152,6 +156,16 @@ export class Journal extends BaseJournal<JournalJson> {
return this._json.version; return this._json.version;
} }
public getCryptoManager(derived: string, keyPair: AsymmetricKeyPair) {
if (this.key) {
const asymmetricCryptoManager = new AsymmetricCryptoManager(keyPair);
const derivedJournalKey = asymmetricCryptoManager.decryptBytes(this.key);
return CryptoManager.fromDerivedKey(derivedJournalKey, this.version);
} else {
return new CryptoManager(derived, this.uid, this.version);
}
}
public setInfo(cryptoManager: CryptoManager, info: CollectionInfo) { public setInfo(cryptoManager: CryptoManager, info: CollectionInfo) {
this._json.uid = info.uid; this._json.uid = info.uid;
this._content = info; this._content = info;
@ -270,6 +284,10 @@ export class UserInfo extends BaseItem<UserInfoJson> {
return ret; return ret;
} }
public getCryptoManager(derived: string) {
return new CryptoManager(derived, 'userInfo', this.version);
}
public setKeyPair(cryptoManager: CryptoManager, keyPair: AsymmetricKeyPair) { public setKeyPair(cryptoManager: CryptoManager, keyPair: AsymmetricKeyPair) {
this._json.pubkey = sjcl.codec.base64.fromBits(sjcl.codec.bytes.toBits(keyPair.publicKey)); this._json.pubkey = sjcl.codec.base64.fromBits(sjcl.codec.bytes.toBits(keyPair.publicKey));
this._content = keyPair.privateKey; this._content = keyPair.privateKey;
@ -323,14 +341,16 @@ class BaseNetwork {
this.apiBase = URI(apiBase).normalize(); this.apiBase = URI(apiBase).normalize();
} }
// FIXME: Get the correct type for extra public newCall<T = any>(segments: string[] = [], extra: RequestInit = {}, _apiBase: URI = this.apiBase): Promise<T> {
public newCall(segments: string[] = [], extra: any = {}, _apiBase: URI = this.apiBase): Promise<any> {
const apiBase = BaseNetwork.urlExtend(_apiBase, segments); const apiBase = BaseNetwork.urlExtend(_apiBase, segments);
extra = Object.assign({}, extra); extra = {
extra.headers = Object.assign( ...extra,
{ Accept: 'application/json' }, headers: {
extra.headers); Accept: 'application/json',
...extra.headers,
},
};
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
fetch(apiBase.toString(), extra).then((response) => { fetch(apiBase.toString(), extra).then((response) => {
@ -382,7 +402,7 @@ export class Authenticator extends BaseNetwork {
body: form, body: form,
}; };
this.newCall([], extra).then((json: {token: string}) => { this.newCall<{token: string}>([], extra).then((json) => {
resolve(json.token); resolve(json.token);
}).catch((error: Error) => { }).catch((error: Error) => {
reject(error); reject(error);
@ -400,15 +420,15 @@ export class BaseManager extends BaseNetwork {
this.apiBase = BaseNetwork.urlExtend(this.apiBase, ['api', 'v1'].concat(segments)); this.apiBase = BaseNetwork.urlExtend(this.apiBase, ['api', 'v1'].concat(segments));
} }
// FIXME: Get the correct type for extra public newCall<T = any>(segments: string[] = [], extra: RequestInit = {}, apiBase: any = this.apiBase): Promise<T> {
public newCall(segments: string[] = [], extra: any = {}, apiBase: any = this.apiBase): Promise<any> { extra = {
extra = Object.assign({}, extra); ...extra,
extra.headers = Object.assign( headers: {
{
'Content-Type': 'application/json;charset=UTF-8', 'Content-Type': 'application/json;charset=UTF-8',
'Authorization': 'Token ' + this.credentials.authToken, 'Authorization': 'Token ' + this.credentials.authToken,
...extra.headers,
}, },
extra.headers); };
return super.newCall(segments, extra, apiBase); return super.newCall(segments, extra, apiBase);
} }
@ -421,8 +441,8 @@ export class JournalManager extends BaseManager {
public fetch(journalUid: string): Promise<Journal> { public fetch(journalUid: string): Promise<Journal> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.newCall([journalUid, '']).then((json: JournalJson) => { this.newCall<JournalJson>([journalUid, '']).then((json) => {
const journal = new Journal(json.version); const journal = new Journal({ uid: json.uid }, json.version);
journal.deserialize(json); journal.deserialize(json);
resolve(journal); resolve(journal);
}).catch((error: Error) => { }).catch((error: Error) => {
@ -433,9 +453,9 @@ export class JournalManager extends BaseManager {
public list(): Promise<Journal[]> { public list(): Promise<Journal[]> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.newCall().then((json: JournalJson[]) => { this.newCall<JournalJson[]>().then((json) => {
resolve(json.map((val: JournalJson) => { resolve(json.map((val: JournalJson) => {
const journal = new Journal(val.version); const journal = new Journal({ uid: val.uid }, val.version);
journal.deserialize(val); journal.deserialize(val);
return journal; return journal;
})); }));
@ -451,7 +471,7 @@ export class JournalManager extends BaseManager {
body: JSON.stringify(journal.serialize()), body: JSON.stringify(journal.serialize()),
}; };
return this.newCall([], extra); return this.newCall<Journal>([], extra);
} }
public update(journal: Journal): Promise<{}> { public update(journal: Journal): Promise<{}> {
@ -460,7 +480,7 @@ export class JournalManager extends BaseManager {
body: JSON.stringify(journal.serialize()), body: JSON.stringify(journal.serialize()),
}; };
return this.newCall([journal.uid, ''], extra); return this.newCall<Journal>([journal.uid, ''], extra);
} }
public delete(journal: Journal): Promise<{}> { public delete(journal: Journal): Promise<{}> {
@ -485,8 +505,8 @@ export class EntryManager extends BaseManager {
}); });
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.newCall(undefined, undefined, apiBase).then((json: Array<{}>) => { this.newCall<EntryJson[]>(undefined, undefined, apiBase).then((json) => {
resolve(json.map((val: any) => { resolve(json.map((val) => {
const entry = new Entry(); const entry = new Entry();
entry.deserialize(val); entry.deserialize(val);
return entry; return entry;
@ -524,8 +544,8 @@ export class JournalMembersManager extends BaseManager {
public list(): Promise<JournalMemberJson[]> { public list(): Promise<JournalMemberJson[]> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.newCall().then((json: JournalMemberJson[]) => { this.newCall<JournalMemberJson[]>().then((json) => {
resolve(json.map((val: JournalMemberJson) => { resolve(json.map((val) => {
return val; return val;
})); }));
}).catch((error: Error) => { }).catch((error: Error) => {
@ -559,7 +579,7 @@ export class UserInfoManager extends BaseManager {
public fetch(owner: string): Promise<UserInfo> { public fetch(owner: string): Promise<UserInfo> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.newCall([owner, '']).then((json: UserInfoJson) => { this.newCall<UserInfoJson>([owner, '']).then((json) => {
const userInfo = new UserInfo(owner, json.version); const userInfo = new UserInfo(owner, json.version);
userInfo.deserialize(json); userInfo.deserialize(json);
resolve(userInfo); resolve(userInfo);

@ -56,7 +56,7 @@ const journalsDeserialize = (state: {}) => {
const newState = new Map<string, EteSync.Journal>(); const newState = new Map<string, EteSync.Journal>();
Object.keys(state).forEach((uid) => { Object.keys(state).forEach((uid) => {
const x = state[uid]; const x = state[uid];
const ret = new EteSync.Journal(x.version); const ret = new EteSync.Journal(uid, x.version);
ret.deserialize(x); ret.deserialize(x);
newState.set(uid, ret); newState.set(uid, ret);
}); });

Loading…
Cancel
Save