From 700eb32f5a8852a8004782b199e5fcca4c847116 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 18 Oct 2016 01:36:47 +0200 Subject: be even more safe in db --- lib/wallet/query.ts | 68 ++++++++++++++++++++++++++++++++-------------------- lib/wallet/wallet.ts | 42 ++++++++++++++++++++++++-------- 2 files changed, 74 insertions(+), 36 deletions(-) (limited to 'lib/wallet') diff --git a/lib/wallet/query.ts b/lib/wallet/query.ts index ce0308ed3..03b443a6e 100644 --- a/lib/wallet/query.ts +++ b/lib/wallet/query.ts @@ -34,14 +34,23 @@ export class Store { } } +export class Index { + indexName: string; + storeName: string; + + constructor(s: Store, indexName: string) { + this.storeName = s.name; + this.indexName = indexName; + } +} + /** * Stream that can be filtered, reduced or joined * with indices. */ export interface QueryStream { - indexJoin(storeName: string, - indexName: string, - keyFn: (obj: any) => any): QueryStream<[T, S]>; + indexJoin(index: Index, + keyFn: (obj: T) => I): QueryStream<[T, S]>; filter(f: (x: any) => boolean): QueryStream; reduce(f: (v: T, acc: S) => S, start?: S): Promise; flatMap(f: (x: T) => T[]): QueryStream; @@ -64,14 +73,14 @@ function openPromise() { // Never happens, unless JS implementation is broken throw Error(); } - return { resolve, reject, promise }; + return {resolve, reject, promise}; } abstract class QueryStreamBase implements QueryStream { abstract subscribe(f: (isDone: boolean, - value: any, - tx: IDBTransaction) => void): void; + value: any, + tx: IDBTransaction) => void): void; root: QueryRoot; @@ -83,11 +92,10 @@ abstract class QueryStreamBase implements QueryStream { return new QueryStreamFlatMap(this, f); } - indexJoin(storeName: string, - indexName: string, - key: any): QueryStream<[T, S]> { - this.root.addStoreAccess(storeName, false); - return new QueryStreamIndexJoin(this, storeName, indexName, key); + indexJoin(index: Index, + keyFn: (obj: T) => I): QueryStream<[T, S]> { + this.root.addStoreAccess(index.storeName, false); + return new QueryStreamIndexJoin(this, index.storeName, index.indexName, keyFn); } filter(f: (x: any) => boolean): QueryStream { @@ -107,8 +115,8 @@ abstract class QueryStreamBase implements QueryStream { }); return Promise.resolve() - .then(() => this.root.finish()) - .then(() => promise); + .then(() => this.root.finish()) + .then(() => promise); } reduce(f: (x: any, acc?: A) => A, init?: A): Promise { @@ -124,8 +132,8 @@ abstract class QueryStreamBase implements QueryStream { }); return Promise.resolve() - .then(() => this.root.finish()) - .then(() => promise); + .then(() => this.root.finish()) + .then(() => promise); } } @@ -191,7 +199,8 @@ class QueryStreamIndexJoin extends QueryStreamBase<[T, S]> { key: any; indexName: string; - constructor(s: QueryStreamBase, storeName: string, indexName: string, key: any) { + constructor(s: QueryStreamBase, storeName: string, indexName: string, + key: any) { super(s.root); this.s = s; this.storeName = storeName; @@ -238,7 +247,7 @@ class IterQueryStream extends QueryStreamBase { let s: any; if (indexName !== void 0) { s = tx.objectStore(this.storeName) - .index(this.options.indexName); + .index(this.options.indexName); } else { s = tx.objectStore(this.storeName); } @@ -287,10 +296,17 @@ export class QueryRoot { this.db = db; } - iter(store: Store, - {only = undefined, indexName = undefined} = {}): QueryStream { + iter(store: Store): QueryStream { this.stores.add(store.name); - return new IterQueryStream(this, store.name, { only, indexName }); + return new IterQueryStream(this, store.name, {}); + } + + iterIndex(index: Index, only?: S): QueryStream { + this.stores.add(index.storeName); + return new IterQueryStream(this, index.storeName, { + only, + indexName: index.indexName + }); } /** @@ -354,8 +370,8 @@ export class QueryRoot { this.addWork(doGet, store.name, false); return Promise.resolve() - .then(() => this.finish()) - .then(() => promise); + .then(() => this.finish()) + .then(() => promise); } /** @@ -377,8 +393,8 @@ export class QueryRoot { this.addWork(doGetIndexed, storeName, false); return Promise.resolve() - .then(() => this.finish()) - .then(() => promise); + .then(() => this.finish()) + .then(() => promise); } /** @@ -420,8 +436,8 @@ export class QueryRoot { * Low-level function to add a task to the internal work queue. */ addWork(workFn: (t: IDBTransaction) => void, - storeName?: string, - isWrite?: boolean) { + storeName?: string, + isWrite?: boolean) { this.work.push(workFn); if (storeName) { this.addStoreAccess(storeName, isWrite); diff --git a/lib/wallet/wallet.ts b/lib/wallet/wallet.ts index 6ab777801..54c979919 100644 --- a/lib/wallet/wallet.ts +++ b/lib/wallet/wallet.ts @@ -30,7 +30,7 @@ import { WireInfo, RefreshSession, ReserveRecord, CoinPaySig } from "./types"; import {HttpResponse, RequestException} from "./http"; -import {QueryRoot, Store} from "./query"; +import {QueryRoot, Store, Index} from "./query"; import {Checkable} from "./checkable"; import {canonicalizeBaseUrl} from "./helpers"; import {ReserveCreationInfo, Amounts} from "./types"; @@ -306,12 +306,36 @@ function getWithdrawDenomList(amountAvailable: AmountJson, namespace Stores { - export let exchanges: Store = new Store("exchanges"); + class ExchangeStore extends Store { + constructor() { + super("exchanges"); + } + pubKeyIndex = new Index(this, "pubKey"); + } + + class CoinsStore extends Store { + constructor() { + super("coins"); + } + + exchangeBaseUrlIndex = new Index(this, "exchangeBaseUrl"); + } + + class HistoryStore extends Store { + constructor() { + super("history"); + } + + timestampIndex = new Index(this, "timestamp"); + } + + + export let exchanges: ExchangeStore = new ExchangeStore(); export let transactions: Store = new Store("transactions"); export let reserves: Store = new Store("reserves"); - export let coins: Store = new Store("coins"); + export let coins: CoinsStore = new CoinsStore(); export let refresh: Store = new Store("refresh"); - export let history: Store = new Store("history"); + export let history: HistoryStore = new HistoryStore(); export let precoins: Store = new Store("precoins"); } @@ -463,9 +487,8 @@ export class Wallet { console.log("Checking for merchant's exchange", JSON.stringify(info)); return [ this.q() - .iter(Stores.exchanges, {indexName: "pubKey", only: info.master_pub}) - .indexJoin("coins", - "exchangeBaseUrl", + .iterIndex(Stores.exchanges.pubKeyIndex, info.master_pub) + .indexJoin(Stores.coins.exchangeBaseUrlIndex, (exchange) => exchange.baseUrl) .reduce((x) => storeExchangeCoin(x, info.url)) ]; @@ -997,8 +1020,7 @@ export class Wallet { private async suspendCoins(exchangeInfo: IExchangeInfo): Promise { let suspendedCoins = await ( this.q() - .iter(Stores.coins, - {indexName: "exchangeBaseUrl", only: exchangeInfo.baseUrl}) + .iterIndex(Stores.coins.exchangeBaseUrlIndex, exchangeInfo.baseUrl) .reduce((coin: Coin, suspendedCoins: Coin[]) => { if (!exchangeInfo.active_denoms.find((c) => c.denom_pub == coin.denomPub)) { return Array.prototype.concat(suspendedCoins, [coin]); @@ -1375,7 +1397,7 @@ export class Wallet { let history = await ( this.q() - .iter(Stores.history, {indexName: "timestamp"}) + .iterIndex(Stores.history.timestampIndex) .reduce(collect, [])); return {history}; -- cgit v1.2.3