Commit f86525df authored by Anastasios Kalogeropoulos's avatar Anastasios Kalogeropoulos
Browse files

Project added

parents
node_modules
/smartcontract/test/
/backend/src/identity/
\ No newline at end of file
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}"
}
]
}
\ No newline at end of file
Christian Ziegler (christian.ziegler@tum.de)
Jonas Ebel
Benedikt Schleibinger
Kevin Huestis
\ No newline at end of file
# DLT4PI_Frontend
This Project contains Backend and Drontend of ibo-tracing
- Frontend is deployed to: ibo-tracing.herokuapp.com
- Backend is deployed to: ibo-tracing-backend.herokuapp.com (no IPFS!)
## Run
```
cd backend
npm start
cd frontend
npm start
```
## Deploy
Since there are two projects in this repository we need to work with subtree (Heroku):
- heroku git:remote -a ibo-tracing-backend
- git subtree push --prefix=backend heroku master
frontend works the same
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
# editorconfig-tools is unable to ignore long strings or urls
max_line_length = null
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
UNUSED/*
{
"extends": "airbnb",
"parserOptions": {
"ecmaVersion": 2019
},
"rules": {
"prefer-destructuring": "off",
"max-len": "off",
"no-await-in-loop": "off",
"no-continue": "off",
"arrow-parens": "off",
"no-async-promise-executor": "warn",
"arrow-body-style": "warn"
}
}
# Auto detect text files and perform LF normalization
* text=auto
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# DLT4PI - IBO Backend
## Install
### Application
- cd backend
- npm install
### Postgresql
- sudo apt install postgresql
- sudo -u postgres -i
- psql
- ALTER USER postgres WITH PASSWORD 'postgres';
- exit
### IPFS
1. Download binary https://dist.ipfs.io/#go-ipfs
1. Untar with tar -xzf <file>
1. cd go-ipfs
1. sudo ./install
1. ipfs init
1. ipfs daemon
## Run
```npm i && npm start```
## Routes
/api/v1/
```
GET "/getShippingData",
GET "/getShippedItems",
GET "/getVerificationData",
GET "/getOutboundData",
GET "/getDecomissionedData",
POST "/login",
POST "/register",
POST "/createProduct",
POST "/createProcessedItem",
POST "/addDoc",
POST "/move"
```
```
GET example: localhost:3005/api/v1/getShippingData
```
```
POST example: localhost:3005/api/v1/createProduct
body: {
productInfo: {
serialNumber: '000000123a',
label: 'Screws',
},
documents: ['hash1', 'hash2', 'hash3'],
}
POST example: localhost:3005/api/v1/createProcessedItem
body: {
productInfo: {
serialNumber: '000000123a',
label: 'Screws',
},
documents: ['hash1', 'hash2', 'hash3'],
subParts: ['000000123a'],
}
```
module.exports = {
port: process.env.PORT || 3005,
dbConnectionString: process.env.DATABASE_URL || 'postgres://postgres:postgres@localhost:5432/ibo',
saltRounds: 2,
jwtSecret: 'ibosecretjwttoken',
tokenExpireTime: '30d',
};
const Sequelize = require('sequelize');
const config = require('./config');
const sequelize = new Sequelize(config.dbConnectionString);
module.exports = sequelize;
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const api = require('./src/api/api');
const CONFIG = require('./config');
const app = express();
app.use(bodyParser.json({ limit: '50mb' }));
app.use(cors());
app.use('/api/v1', api);
app.get('/', (req, res) => {
res.json({
routes: '/api/v1',
});
});
app.get('/api', (req, res) => {
res.json({
routes: '/v1',
});
});
app.listen(CONFIG.port, () => console.log(`Backend is running and listening at http://localhost:${CONFIG.port}`));
This diff is collapsed.
{
"name": "backend",
"version": "1.0.0",
"description": "This is the nodejs backend for DLT4PI-IBO project",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "eslint ."
},
"author": "jonny3576",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.0.0",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"crypto": "^1.0.1",
"express": "^4.17.1",
"fabric-ca-client": "^2.1.0",
"fabric-network": "^2.1.0",
"ipfs-http-client": "^41.0.1",
"js-yaml": "^3.14.0",
"jsonwebtoken": "^8.5.1",
"pg": "^8.2.1",
"sequelize": "^5.21.13"
},
"engines": {
"node": "12.8.1"
},
"devDependencies": {
"eslint": "^6.8.0",
"eslint-config-airbnb": "^18.0.1",
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-react": "^7.18.3"
}
}
const express = require('express');
const queries = require('./queries');
const transactions = require('./transactions');
const authController = require('../controllers/auth');
const testUser = require('../mocks/testUser');
const authMiddleware = require('../middlewares/auth');
const api = express();
api.use((req, res, next) => {
if (!req.user) {
req.user = testUser;
}
next();
});
api.get('/', (req, res) => {
res.send({routes: [
// Peer Getter
'/getShippingData',
// Data Getter
'/getShippedItems',
'/getVerificationData',
'/getOutboundData',
'/getDecomissionedData',
// Auth
'/login',
'/register',
// Create Operations
'/createProduct',
'/createProcessedItem',
// Transfers
'/addDoc',
'/getDoc',
'/move',
// State changes
'/approveShipment',
'/decomissionProduct',
'/acceptProduct'
]});
});
// Product
api.get('/getProduct', authMiddleware.injectUser, queries.getProduct);
// Peer Getter
api.get('/getShippingData', authMiddleware.injectUser, queries.getShippingData);
// Data Getter
api.get('/getShippedItems', authMiddleware.injectUser, queries.getShippedItemsData);
api.get('/getVerificationData', authMiddleware.injectUser, queries.getVerificationData);
api.get('/getOutboundData', authMiddleware.injectUser, queries.getOutboundData);
api.get('/getDecomissionedData', authMiddleware.injectUser, queries.getDecomissionedData);
api.get('/getWorldData', authMiddleware.injectUser, queries.getWorldData);
api.post('/login', authMiddleware.injectUser, authController.login);
api.post('/register', authMiddleware.injectUser, authController.register);
api.post('/createProduct', authMiddleware.injectUser, transactions.createProduct);
api.post('/createProcessedItem', authMiddleware.injectUser, transactions.createProcessedItem);
// State changes
api.post('/approveShipment', authMiddleware.injectUser, transactions.approveShipment);
api.post('/decomissionProduct', authMiddleware.injectUser, transactions.decomissionProduct);
api.post('/acceptProduct', authMiddleware.injectUser, transactions.acceptProduct);
api.post('/addDoc', authMiddleware.injectUser, transactions.addDoc);
api.get('/getDoc', authMiddleware.injectUser, queries.getDocument);
api.post('/move', authMiddleware.injectUser, transactions.move);
module.exports = api;
const sca = require('../services/smartContractAdapter');
const ipfs = require('../services/ipfs');
const dbService = require('../services/user');
const helper = {
resolveItem: async (serial, user) => {
/* Performance problems; Re-implement for production */
const product = await sca.getProduct(user, serial);
if (!product) {
return undefined;
}
const items = [];
for (let i = 0; i < product.subParts.length; i += 1) {
const resolvedItem = await helper.resolveItem(product.subParts[i], user);
items.push(resolvedItem);
}
return {
serial: product.serial,
producer: product.producer,
currentOwner: product.currentOwner,
description: product.label,
qaDocuments: product.qaDocuments,
status: product.status,
oldOwners: product.oldOwners,
items,
}
},
getWorldSateInFrontendStructure: async (user) => {
const worldState = await sca.getWorldState(user);
const flatWorldState = Object.entries(worldState);
const frontendStyleWorldState = [];
for (let i = 0; i < flatWorldState.length; i += 1) {
const resolvedItem = await helper.resolveItem(flatWorldState[i][0], user);
frontendStyleWorldState.push(resolvedItem);
}
return frontendStyleWorldState;
},
};
const queries = {
getShippingData: async (req, res) => {
const otherUsers = await dbService.getOtherUser(req.user.login);
const returnValues = otherUsers.map((user) => { return {name: user.dataValues.login, cert: user.dataValues.cert } } );
res.send(returnValues);
},
getShippedItemsData: async (req, res) => {
const worldStateFrontendStructure = await helper.getWorldSateInFrontendStructure(req.user);
const filteredState = worldStateFrontendStructure.filter((item) => item.status.status === 'SHIPPING');
res.send(filteredState);
},
getOutboundData: async (req, res) => {
const worldStateFrontendStructure = await helper.getWorldSateInFrontendStructure(req.user);
const filteredState = worldStateFrontendStructure.filter((item) => item.status.status === 'IN_WAREHOUSE_VERIFIED');
res.send(filteredState);
},
getVerificationData: async (req, res) => {
const worldStateFrontendStructure = await helper.getWorldSateInFrontendStructure(req.user);
const filteredState = worldStateFrontendStructure.filter((item) => item.status.status === 'IN_WAREHOUSE');
res.send(filteredState);
},
getDecomissionedData: async (req, res) => {
const worldStateFrontendStructure = await helper.getWorldSateInFrontendStructure(req.user);
const filteredState = worldStateFrontendStructure.filter((item) => item.status.status === 'DECOMISSIONED');
res.send(filteredState);
},
getProduct: async (req, res) => {
const frontendItem = await helper.resolveItem(req.params.serialnumber || req.query.serialnumber, req.user);
res.send(frontendItem);
},
getWorldData: async (req, res) => {
const frontendWorldState = await helper.getWorldSateInFrontendStructure(req.user);
res.send(frontendWorldState);
},
getDocument: async (req, res) => {
// const documentKeys = await sca.readDocumentKeys(req.user, req.query.filehash);
//console.log(req.user, req.query.filehash, documentKeys);
//console.log(documentKeys);
const file = await ipfs.getDoc(req.query.filehash, {});
// console.log(file);
res.send({
file,
});
},
};
module.exports = queries;
[{
"serial": "IBO-0041231",
"producer": "IBO",
"currentOwner": "IBO",
"description": "Bearing",
"qadocuments": ["somehash", "examplehash", "thirdhash"],
"status": {
"status": "IN_WAREHOUSE_VERIFIED",
"timestamp": 1579091115
},
"oldOwners": [],
"items": [{
"serial": "ZF-0000005",
"producer": "ZF",
"currentOwner": "IBO",
"description": "Aluminum Sphere",
"qadocuments": ["somehash", "examplehash", "thirdhash"],
"status": {
"status": "IN_WAREHOUSE_VERIFIED",
"timestamp": 1579091115
},
"oldOwners": [{
"owner": "ZF",
"becameOwner": 1578091115
}],
"items": []
}, {
"serial": "ZF-0000006",
"producer": "ZF",
"currentOwner": "IBO",
"description": "Aluminum Rings",
"qadocuments": ["somehash", "examplehash", "thirdhash"],
"status": {
"status": "IN_WAREHOUSE_VERIFIED",
"timestamp": 1579091115
},
"oldOwners": [{
"owner": "ZF",
"becameOwner": 1578091115
}],
"items": []
}]
}, {
"serial": "ZF-0000005",
"producer": "ZF",
"currentOwner": "IBO",
"description": "Aluminum Sphere",
"qadocuments": ["somehash", "examplehash", "thirdhash"],
"status": {
"status": "IN_WAREHOUSE_VERIFIED",
"timestamp": 1579091115
},
"oldOwners": [{
"owner": "ZF",
"becameOwner": 1578091115
}],
"items": []
}, {
"serial": "ZF-0000006",
"producer": "ZF",
"currentOwner": "IBO",
"description": "Aluminum Rings",
"qadocuments": ["somehash", "examplehash", "thirdhash"],
"status": {
"status": "IN_WAREHOUSE_VERIFIED",
"timestamp": 1579091115
},
"oldOwners": [{
"owner": "ZF",
"becameOwner": 1578091115
}],
"items": []
}]
const sca = require('../services/smartContractAdapter');
const ipfs = require('../services/ipfs');
const helper = {
resolveItem: async (serial, user) => {
/* Performance problems; Re-implement for production */
const worldState = await sca.getWorldState(user);
const product = worldState[serial];
//console.log(product);
if (!product) {
return undefined;
}
const items = [];
for (let i = 0; i < product.subParts.length; i += 1) {
const resolvedItem = await helper.resolveItem(product.subParts[i], user);
items.push(resolvedItem);
}
return {
serial: product.serial,
producer: product.producer,
currentOwner: product.currentOwner,
description: product.label,