|
|
@@ -1,5 +1,5 @@
|
|
|
import 'dotenv/config'
|
|
|
-import grpc from "grpc"
|
|
|
+import grpc from "grpc"
|
|
|
import express from "express"
|
|
|
import bodyParser from "body-parser"
|
|
|
import basicAuth from "express-basic-auth"
|
|
|
@@ -10,7 +10,9 @@ import {
|
|
|
import { queries } from 'iroha-helpers'
|
|
|
import util from 'util'
|
|
|
import { exec } from 'child_process'
|
|
|
-import cors from 'cors'
|
|
|
+import cors from 'cors'
|
|
|
+import * as sql from 'sqlite3'
|
|
|
+import fs from 'fs'
|
|
|
|
|
|
const app = express();
|
|
|
app.use(bodyParser.json());
|
|
|
@@ -18,7 +20,7 @@ app.use(bodyParser.json());
|
|
|
//TODO is cors package necesary? basic middleware could suffice
|
|
|
app.use(cors()); //TODO: set only safe origins
|
|
|
app.use(basicAuth({
|
|
|
- users: { admin: 'superPasswd' }
|
|
|
+ users: { admin: 'superPasswd' }
|
|
|
}));
|
|
|
|
|
|
|
|
|
@@ -35,10 +37,75 @@ const CHAIN4ALL_RASTER_CLIP_SCRIPT_PATH = process.env.CHAIN4ALL_RASTER_CLIP_SCRI
|
|
|
const CHAIN4ALL_SERVICE_PORT = process.env.CHAIN4ALL_SERVICE_PORT || 3000;
|
|
|
const PRICE_MODIFIER: number = parseFloat(process.env.PRICE_MODIFIER || "0.5");
|
|
|
|
|
|
+const DB_FILE_NAME: string = "data/transfers.db";
|
|
|
+
|
|
|
app.get("/", (req, res) => {
|
|
|
res.send("Chain4All Blockchain service");
|
|
|
});
|
|
|
|
|
|
+app.get("/transfers/:userId", async (req, res, next) => {
|
|
|
+ let db = await getDbConnection();
|
|
|
+
|
|
|
+ db.all(
|
|
|
+ "SELECT hash " +
|
|
|
+ "FROM transfers " +
|
|
|
+ "WHERE user=? " +
|
|
|
+ "ORDER BY id DESC " +
|
|
|
+ "LIMIT 10;",
|
|
|
+ [req.params.userId],
|
|
|
+ (err, rows) => {
|
|
|
+ if (err) {
|
|
|
+ next(err);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ res.send(rows);
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ db.close();
|
|
|
+});
|
|
|
+
|
|
|
+app.post("/transfer", async (req, res, next) => {
|
|
|
+ try {
|
|
|
+ if (!req.body) {
|
|
|
+ res.status(400);
|
|
|
+ throw Error(JSON.stringify({ error: { name: "Error, request has no body!" } }));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!req.body.txHash) {
|
|
|
+ res.status(400);
|
|
|
+ throw Error(JSON.stringify({ error: { name: "Error, request body has no \"txHash\" property!" } }));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!req.body.user) {
|
|
|
+ res.status(400);
|
|
|
+ throw Error(JSON.stringify({ error: { name: "Error, request body has no \"user\" property!" } }));
|
|
|
+ }
|
|
|
+
|
|
|
+ let db = await getDbConnection();
|
|
|
+
|
|
|
+ db.run(
|
|
|
+ "INSERT INTO transfers (hash, user)" +
|
|
|
+ "VALUES (?, ?);",
|
|
|
+ [req.body.txHash, req.body.user],
|
|
|
+ (err) => {
|
|
|
+ if (err) {
|
|
|
+ next(err);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ res.status(201);
|
|
|
+ res.send();
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ db.close();
|
|
|
+ }
|
|
|
+ catch (err) {
|
|
|
+ next(err);
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
app.post("/price", (req, res) => { //add caching of same requests
|
|
|
if (req.body && req.body.area) {
|
|
|
res.send({ price: getPrice(req.body.area) });
|
|
|
@@ -73,25 +140,56 @@ app.post("/buy", async (req, res, next) => {
|
|
|
|
|
|
let extent: number[] = JSON.parse(txDetail.description).extent as number[];
|
|
|
let dataFileId: string = Date.now().toString();
|
|
|
-
|
|
|
+
|
|
|
let dataCommand = CHAIN4ALL_RASTER_CLIP_SCRIPT_PATH + ' ' + extent[0] + ' ' + extent[1] + ' ' + extent[2] + ' ' + extent[3] + ' ' + dataFileId;
|
|
|
console.debug(dataCommand);
|
|
|
|
|
|
const { stdout, stderr } = await asyncExec(dataCommand);
|
|
|
-
|
|
|
+
|
|
|
console.debug(stdout);
|
|
|
|
|
|
- if(stderr){
|
|
|
+ if (stderr) {
|
|
|
console.warn(stderr);
|
|
|
}
|
|
|
|
|
|
- res.send({dataUrl: "https://gis.lesprojekt.cz/chain4all/raster_" + dataFileId + ".tif"});
|
|
|
+ res.send({ dataUrl: "https://gis.lesprojekt.cz/chain4all/raster_" + dataFileId + ".tif" });
|
|
|
}
|
|
|
catch (err) {
|
|
|
next(err);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
+function getDbConnection(): sql.Database {
|
|
|
+
|
|
|
+ return new sql.Database(DB_FILE_NAME);
|
|
|
+}
|
|
|
+
|
|
|
+function initDatabase(): Promise<void>{
|
|
|
+ return new Promise<void>((resolve, reject) => {
|
|
|
+ if(!fs.existsSync("./data")){
|
|
|
+ fs.mkdirSync("data");
|
|
|
+ };
|
|
|
+
|
|
|
+ let db = getDbConnection();
|
|
|
+
|
|
|
+ db.run(
|
|
|
+ "CREATE TABLE IF NOT EXISTS transfers( " +
|
|
|
+ "id INTEGER PRIMARY KEY, " +
|
|
|
+ "hash TEXT NOT NULL, " +
|
|
|
+ "user TEXT NOT NULL " +
|
|
|
+ ");",
|
|
|
+ (err) => {
|
|
|
+ if (err) {
|
|
|
+ reject(err);
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ resolve();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
async function getTransactionDetail(txHash: string, user: string) {
|
|
|
let quer: any = await queries.getAccountTransactions({
|
|
|
privateKey: IROHA_ADMIN_PRIV,
|
|
|
@@ -116,7 +214,7 @@ async function getTransactionDetail(txHash: string, user: string) {
|
|
|
return quer.transactionsList[0].payload.reducedPayload.commandsList[0].transferAsset;
|
|
|
}
|
|
|
|
|
|
-function getPrice(area: number) : number {
|
|
|
+function getPrice(area: number): number {
|
|
|
return area * PRICE_MODIFIER;
|
|
|
}
|
|
|
|
|
|
@@ -128,6 +226,12 @@ function errorMiddleware(err: any, req: any, res: any, next: any): void { //TODO
|
|
|
|
|
|
app.use(errorMiddleware);
|
|
|
|
|
|
-app.listen(CHAIN4ALL_SERVICE_PORT, () => {
|
|
|
- console.log(`Listening at http://localhost:${CHAIN4ALL_SERVICE_PORT}`)
|
|
|
+app.listen(CHAIN4ALL_SERVICE_PORT,async () => {
|
|
|
+ try{
|
|
|
+ await initDatabase();
|
|
|
+ console.log(`Listening at http://localhost:${CHAIN4ALL_SERVICE_PORT}`);
|
|
|
+ }catch(err){
|
|
|
+ console.error("Cannot start service!");
|
|
|
+ console.error(err);
|
|
|
+ }
|
|
|
});
|