API: Add API to handle UserInfo.

master
Tom Hacohen 7 years ago
parent ac31f7093f
commit fb738622fe

@ -127,3 +127,31 @@ it('Journal Entry sync', async () => {
}
}).toThrowError();
});
it('User info sync', async () => {
const userInfoManager = new EteSync.UserInfoManager(credentials, testApiBase);
// Get when there's nothing
await expect(userInfoManager.fetch(USER)).rejects.toBeInstanceOf(EteSync.HTTPError);
// Create
let userInfo = new EteSync.UserInfo();
userInfo.deserialize({pubkey: 'dGVzdAo=', content: 'dGVzdAo=', owner: USER});
await expect(userInfoManager.create(userInfo)).resolves.not.toBeNull();
// Get
let userInfo2 = await userInfoManager.fetch(USER);
expect(userInfo2).not.toBeNull();
expect(userInfo.serialize().content).toEqual(userInfo2!.serialize().content);
// Update
userInfo.deserialize({pubkey: 'dGVzdDIK', content: 'dGVzdDIK', owner: USER});
await userInfoManager.update(userInfo);
userInfo2 = await userInfoManager.fetch(USER);
expect(userInfo2).not.toBeNull();
expect(userInfo.serialize().content).toEqual(userInfo2!.serialize().content);
// Delete
await userInfoManager.delete(userInfo);
await expect(userInfoManager.fetch(USER)).rejects.toBeInstanceOf(EteSync.HTTPError);
});

@ -65,12 +65,11 @@ export class CollectionInfo {
}
}
interface BaseJson {
uid: string;
interface BaseItemJson {
content: base64;
}
class BaseJournal<T extends BaseJson> {
class BaseItem<T extends BaseItemJson> {
protected _json: T;
protected _encrypted: byte[];
protected _content?: object;
@ -85,10 +84,6 @@ class BaseJournal<T extends BaseJson> {
this._content = undefined;
}
get uid(): string {
return this._json.uid;
}
serialize(): T {
return Object.assign(
{},
@ -109,6 +104,16 @@ class BaseJournal<T extends BaseJson> {
}
}
interface BaseJson extends BaseItemJson {
uid: string;
}
class BaseJournal<T extends BaseJson> extends BaseItem<T> {
get uid(): string {
return this._json.uid;
}
}
export interface JournalJson extends BaseJson {
version: number;
owner: string;
@ -219,6 +224,43 @@ export class Entry extends BaseJournal<EntryJson> {
}
}
export interface UserInfoJson extends BaseItemJson {
version?: number;
owner: string;
pubkey: base64;
}
export class UserInfo extends BaseItem<UserInfoJson> {
constructor(version: number = Constants.CURRENT_VERSION) {
super();
this._json.version = version;
}
get version(): number {
return this._json.version!;
}
get owner() {
return this._json.owner;
}
calculateHmac(cryptoManager: CryptoManager, encrypted: byte[]): byte[] {
let postfix = stringToByteArray(this._json.pubkey);
return cryptoManager.hmac(encrypted.concat(postfix));
}
verify(cryptoManager: CryptoManager) {
let calculated = this.calculateHmac(cryptoManager, this.encryptedContent());
let hmac = this._encrypted.slice(0, HMAC_SIZE_BYTES);
super.verifyBase(hmac, calculated);
}
private encryptedContent(): byte[] {
return this._encrypted.slice(HMAC_SIZE_BYTES);
}
}
// FIXME: baseUrl and apiBase should be the right type all around.
class BaseNetwork {
@ -421,3 +463,47 @@ export class EntryManager extends BaseManager {
return this.newCall(undefined, extra, apiBase);
}
}
export class UserInfoManager extends BaseManager {
constructor(credentials: Credentials, apiBase: string) {
super(credentials, apiBase, ['user', '']);
}
fetch(owner: string): Promise<UserInfo> {
return new Promise((resolve, reject) => {
this.newCall([owner, '']).then((json: UserInfoJson) => {
let userInfo = new UserInfo(json.version);
userInfo.deserialize(json);
resolve(userInfo);
}).catch((error: Error) => {
reject(error);
});
});
}
create(userInfo: UserInfo): Promise<{}> {
const extra = {
method: 'post',
body: JSON.stringify(userInfo.serialize()),
};
return this.newCall([], extra);
}
update(userInfo: UserInfo): Promise<{}> {
const extra = {
method: 'put',
body: JSON.stringify(userInfo.serialize()),
};
return this.newCall([userInfo.owner, ''], extra);
}
delete(userInfo: UserInfo): Promise<{}> {
const extra = {
method: 'delete',
};
return this.newCall([userInfo.owner, ''], extra);
}
}

Loading…
Cancel
Save