be even more safe in db

This commit is contained in:
Florian Dold 2016-10-18 01:36:47 +02:00
parent 89c3c2d58d
commit 700eb32f5a
2 changed files with 74 additions and 36 deletions

View File

@ -34,14 +34,23 @@ export class Store<T> {
}
}
export class Index<S,T> {
indexName: string;
storeName: string;
constructor(s: Store<T>, indexName: string) {
this.storeName = s.name;
this.indexName = indexName;
}
}
/**
* Stream that can be filtered, reduced or joined
* with indices.
*/
export interface QueryStream<T> {
indexJoin<S>(storeName: string,
indexName: string,
keyFn: (obj: any) => any): QueryStream<[T, S]>;
indexJoin<S,I>(index: Index<I,S>,
keyFn: (obj: T) => I): QueryStream<[T, S]>;
filter(f: (x: any) => boolean): QueryStream<T>;
reduce<S>(f: (v: T, acc: S) => S, start?: S): Promise<S>;
flatMap(f: (x: T) => T[]): QueryStream<T>;
@ -83,11 +92,10 @@ abstract class QueryStreamBase<T> implements QueryStream<T> {
return new QueryStreamFlatMap(this, f);
}
indexJoin<S>(storeName: string,
indexName: string,
key: any): QueryStream<[T, S]> {
this.root.addStoreAccess(storeName, false);
return new QueryStreamIndexJoin(this, storeName, indexName, key);
indexJoin<S,I>(index: Index<I,S>,
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<T> {
@ -191,7 +199,8 @@ class QueryStreamIndexJoin<T, S> extends QueryStreamBase<[T, S]> {
key: any;
indexName: string;
constructor(s: QueryStreamBase<T>, storeName: string, indexName: string, key: any) {
constructor(s: QueryStreamBase<T>, storeName: string, indexName: string,
key: any) {
super(s.root);
this.s = s;
this.storeName = storeName;
@ -287,10 +296,17 @@ export class QueryRoot {
this.db = db;
}
iter<T>(store: Store<T>,
{only = <string | undefined>undefined, indexName = <string | undefined>undefined} = {}): QueryStream<T> {
iter<T>(store: Store<T>): QueryStream<T> {
this.stores.add(store.name);
return new IterQueryStream(this, store.name, { only, indexName });
return new IterQueryStream(this, store.name, {});
}
iterIndex<S,T>(index: Index<S,T>, only?: S): QueryStream<T> {
this.stores.add(index.storeName);
return new IterQueryStream(this, index.storeName, {
only,
indexName: index.indexName
});
}
/**

View File

@ -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<IExchangeInfo> = new Store<IExchangeInfo>("exchanges");
class ExchangeStore extends Store<IExchangeInfo> {
constructor() {
super("exchanges");
}
pubKeyIndex = new Index<string,IExchangeInfo>(this, "pubKey");
}
class CoinsStore extends Store<Coin> {
constructor() {
super("coins");
}
exchangeBaseUrlIndex = new Index<string,Coin>(this, "exchangeBaseUrl");
}
class HistoryStore extends Store<HistoryRecord> {
constructor() {
super("history");
}
timestampIndex = new Index<number,HistoryRecord>(this, "timestamp");
}
export let exchanges: ExchangeStore = new ExchangeStore();
export let transactions: Store<Transaction> = new Store<Transaction>("transactions");
export let reserves: Store<ReserveRecord> = new Store<ReserveRecord>("reserves");
export let coins: Store<Coin> = new Store<Coin>("coins");
export let coins: CoinsStore = new CoinsStore();
export let refresh: Store<RefreshSession> = new Store<RefreshSession>("refresh");
export let history: Store<HistoryRecord> = new Store<HistoryRecord>("history");
export let history: HistoryStore = new HistoryStore();
export let precoins: Store<PreCoin> = new Store<PreCoin>("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<void> {
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};