Skip to content
This repository has been archived by the owner on Feb 8, 2019. It is now read-only.

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Maurice Dalderup authored and Maurice Dalderup committed Feb 7, 2019
0 parents commit 1e701fa
Show file tree
Hide file tree
Showing 23 changed files with 1,379 additions and 0 deletions.
27 changes: 27 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"parser": "babel-eslint",
"plugins": ["prettier"],
"parserOptions": {
"ecmaVersion": 2017,
"sourceType": "module"
},
"env": {
"es6": true,
"node": true,
"mocha": true,
"jest": true
},
"extends": ["eslint:recommended", "airbnb-base", "prettier"],
"rules": {
"prettier/prettier": "error",
"import/no-unresolved": "false",
"import/no-dynamic-require": ["off"],
"import/prefer-default-export": "false",
"import/no-extraneous-dependencies": ["error", { "devDependencies": true }],
"consistent-return": ["off"],
"no-restricted-syntax": "off",
"array-callback-return": "off",
"no-underscore-dangle": "off",
"no-await-in-loop": "off"
}
}
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
.hfc-key-store
.DS_Store
.env
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM trase/mu-javascript-template
LABEL maintainer="Wouter Van Hecke <[email protected]>"
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## Setup

```
# Install Deps & Rebuild gRPC for docker
npm install --target=8.12.0 --target_platform=linux --target_arch=x64 --target_libc=musl .
npm rebuild --target=8.12.0 --target_platform=linux --target_arch=x64 --target_libc=musl .
```
83 changes: 83 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { app, errorHandler } from "mu";
import mongoose from "mongoose";
import util from "util";
import https from "https";
import fs from "fs";

import routes from "./app.routes";
import logger from "./config/Log";
import network from "./services/network.service";
import config from "./config/config";

const init = async () => {
logger.info("=========== STARTING UP DECISION SERVER ===========");
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});

app.use(routes);
app.use(errorHandler);

try {
await network.initFabric();
} catch (e) {
logger.info(`Please restart the resource server. ${e}`);
process.exit(1);
}

const mongoUri =
config.env === "production"
? "mongodb://mongodb:27017/abb-lblod"
: "mongodb://mongodb:27017/abb-lblod-dev";

// connect to mongo db
await mongoose
.connect(
mongoUri,
{
useCreateIndex: true,
useNewUrlParser: true,
poolSize: 2
}
)
.catch(
e => new Error(`unable to connect to database: ${config.mongoUri}`, e)
);

if (config.env === "production") {
const httpsOptions = {
key: fs.readFileSync("certs/localhost-key.pem"),
cert: fs.readFileSync("certs/localhost.pem")
};
https.createServer(httpsOptions, app).listen(443, () => {
logger.info(
`Started decision server on port 443 in ${app.get("env")} mode`
);
});
} else {
// start server
app.listen(80, () =>
logger.info(
`Started decision server on port 80 in ${app.get("env")} mode`
)
);
}

// print mongoose logs in dev env
if (app.get("env") === "development") {
mongoose.set("debug", (collectionName, method, query, doc) => {
logger.info(
`${collectionName}.${method}`,
util.inspect(query, false, 20),
doc
);
});
}
};

init();
10 changes: 10 additions & 0 deletions app.routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Router } from "express";

import decisionRoutes from "./endpoints/decision/decision.route";

export default Router()
/** GET /health-check - Check service health */
.get("/health-check", (req, res) =>
res.send("LBLOD Blockchain decision service up and running!")
)
.use("/decision", decisionRoutes);
38 changes: 38 additions & 0 deletions config/Log.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import expressWinston from "express-winston";
import { transports, format, createLogger } from "winston";

const { combine, prettyPrint, colorize, printf } = format;

const myFormat = printf(
({ level, timestamp, label = "FABRIC", message }) =>
`\n${level}: [${label} - ${timestamp}] - ${message} \n`
);

const defaultTransports = [
new transports.Console({
format: format.combine(format.prettyPrint(), format.colorize())
})
];

const Logger = createLogger({
format: combine(format.timestamp(), prettyPrint(), colorize(), myFormat),
transports: [
new transports.Console(),
new transports.File({ filename: "combined.log" })
],
handleExceptions: true,
exitOnError: false
});

export const expressLogger = expressWinston.logger({
meta: false,
transports: defaultTransports
});

export const expressErrorLogger = expressWinston.errorLogger({
meta: false,
blacklistedMetaFields: ["process", "trace", "os", "req"],
transports: defaultTransports
});

export default Logger;
45 changes: 45 additions & 0 deletions config/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import Joi from "joi";

// require and configure dotenv, will load vars in .env in PROCESS.ENV
import dotenv from "dotenv";

dotenv.config();

// define validation for all the env vars
const envVarsSchema = Joi.object({
PORT: Joi.number().default(3000),
MONGO_PORT: Joi.number().default(27017),
USE_DB: Joi.boolean().default(false),
NODE_ENV: Joi.string()
.allow(["development", "production", "test", "provision"])
.default("development"),
MONGOOSE_DEBUG: Joi.boolean().when("NODE_ENV", {
is: Joi.string().equal("development"),
then: Joi.boolean().default(true),
otherwise: Joi.boolean().default(false)
}),
ADMIN_PW: Joi.string()
.required()
.description("Admin password required")
})
.unknown()
.required();

const { error, value: envVars } = Joi.validate(process.env, envVarsSchema);

if (error) {
throw new Error(
`Check your '.env' file (located at the root of this project),
validation error: ${error.message}`
);
}

const config = {
env: envVars.NODE_ENV,
port: envVars.PORT,
mongooseDebug: envVars.MONGOOSE_DEBUG,
useDb: envVars.USE_DB,
ADMIN_PW: envVars.ADMIN_PW
};

export default config;
7 changes: 7 additions & 0 deletions deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#! /bin/sh

DOCKER_ID_USER="trase"

rm -rf .hfc-key-store
docker build -t $DOCKER_ID_USER/decision-service:0.1.1 .
docker push $DOCKER_ID_USER/decision-service:0.1.1
97 changes: 97 additions & 0 deletions endpoints/decision/decision.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import httpStatus from "http-status";

import logger from "../../config/Log";
import decisionService from "../../services/decision.service";

let counter = 0;

const publish = async (req, res, next) => {
try {
counter++;
console.log("Decison counter", counter);
logger.info("Publishing resources..");
const resource = req.body;
const result = await decisionService.Publish(resource);
res.status(httpStatus.OK).json({ result });
} catch (e) {
next(e);
}
};

const sign = async (req, res, next) => {
try {
logger.info("Signing resources..");
const resource = req.body;
const result = await decisionService.Sign(resource);
res.status(httpStatus.OK).json({ result });
} catch (e) {
next(e);
}
};

const getAll = async (req, res, next) => {
try {
const result = await decisionService.GetAll();
res.status(httpStatus.OK).json({ result });
} catch (e) {
next(e);
}
};

const validate = async (req, res, next) => {
try {
const { id, hash } = req.body;
const { result, blockchainHash } = await decisionService.Validate(id, hash);
res.status(httpStatus.OK).json({
id,
hash,
result,
blockchainHash
});
} catch (e) {
next(e);
}
};

const queryById = async (req, res, next) => {
try {
const { id } = req.body;
const result = await decisionService.GetResourceById(id);
res.status(httpStatus.OK).json({ result });
} catch (e) {
next(e);
}
};

const queryHistory = async (req, res, next) => {
try {
const { id } = req.body;
const result = await decisionService.GetResourceHistory(id);
res.status(httpStatus.OK).json({ result });
} catch (e) {
next(e);
}
};

const queryHistoryByVersion = async (req, res, next) => {
try {
const { id, version } = req.body;
const result = await decisionService.GetResourceHistoryByVersion(
id,
version
);
res.status(httpStatus.OK).json({ result });
} catch (e) {
next(e);
}
};

export default {
publish,
getAll,
sign,
validate,
queryById,
queryHistory,
queryHistoryByVersion
};
37 changes: 37 additions & 0 deletions endpoints/decision/decision.param.validation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Joi from "joi";

export const resourceScheme = {
body: {
id: Joi.string().required(),
content: Joi.string().required(),
oit: {
identifier: Joi.string().required(),
roles: Joi.array().required(),
secret: Joi.string().required(),
fullIdentifier: Joi.string().required()
},
resourceId: Joi.string().required(),
subject: Joi.string().required(),
timestamp: Joi.string().required()
}
};

export const validationScheme = {
body: {
id: Joi.string().required(),
hash: Joi.string().required()
}
};

export const queryHistoryScheme = {
body: {
id: Joi.string().required()
}
};

export const queryHistoryByVersionScheme = {
body: {
id: Joi.string().required(),
version: Joi.string().required()
}
};
Loading

0 comments on commit 1e701fa

Please sign in to comment.