mirror of https://gitlab.com/ecentrics/concordia
Apostolos Fanakis
4 years ago
12 changed files with 274 additions and 1 deletions
@ -1,3 +1,5 @@ |
|||||
export const FORUM_CONTRACT = 'Forum'; |
export const FORUM_CONTRACT = 'Forum'; |
||||
export const POST_VOTING_CONTRACT = 'PostVoting'; |
export const POST_VOTING_CONTRACT = 'PostVoting'; |
||||
export const VOTING_CONTRACT = 'Voting'; |
export const VOTING_CONTRACT = 'Voting'; |
||||
|
export const NUMBER_OF_CONTRACTS = 4; |
||||
|
export const NUMBER_OF_CONTRACTS = 4; |
||||
|
@ -0,0 +1,47 @@ |
|||||
|
// const downloadContractArtifacts = async () => {
|
||||
|
import { NUMBER_OF_CONTRACTS } from '../constants/contracts/ContractNames'; |
||||
|
|
||||
|
export const downloadContractArtifacts = async () => { |
||||
|
const headers = new Headers(); |
||||
|
headers.append('Access-Control-Allow-Origin', 'http://localhost:7000'); |
||||
|
headers.append('Access-Control-Allow-Credentials', 'true'); |
||||
|
|
||||
|
const requestOptions = { |
||||
|
method: 'GET', |
||||
|
redirect: 'follow', |
||||
|
headers, |
||||
|
}; |
||||
|
|
||||
|
const remoteContracts = await fetch('http://127.0.0.1:8400/contracts/asdf', requestOptions) |
||||
|
.then((response) => response.text()) |
||||
|
.then((contractsRawData) => JSON.parse(contractsRawData)); |
||||
|
|
||||
|
if (remoteContracts.length !== NUMBER_OF_CONTRACTS) { |
||||
|
throw new Error(`Version mismatch detected. Artifacts brought ${remoteContracts.length} contracts but app
|
||||
|
expected ${NUMBER_OF_CONTRACTS}`);
|
||||
|
} |
||||
|
|
||||
|
return remoteContracts; |
||||
|
}; |
||||
|
|
||||
|
export const downloadContractArtifactsSync = () => { |
||||
|
const xhrRequest = new XMLHttpRequest(); |
||||
|
// xhrRequest.withCredentials = true;
|
||||
|
xhrRequest.open('GET', 'http://127.0.0.1:8400/contracts/asdf', false); |
||||
|
xhrRequest.setRequestHeader('Access-Control-Allow-Origin', 'http://localhost:7000'); |
||||
|
xhrRequest.setRequestHeader('Access-Control-Allow-Credentials', 'true'); |
||||
|
xhrRequest.send(null); |
||||
|
|
||||
|
if (xhrRequest.status === 200) { |
||||
|
const contractsRawData = xhrRequest.responseText; |
||||
|
const remoteContracts = JSON.parse(contractsRawData); |
||||
|
|
||||
|
if (remoteContracts.length !== NUMBER_OF_CONTRACTS) { |
||||
|
throw new Error(`Version mismatch detected. Artifacts brought ${remoteContracts.length} contracts but app
|
||||
|
expected ${NUMBER_OF_CONTRACTS}`);
|
||||
|
} |
||||
|
|
||||
|
return remoteContracts; |
||||
|
} |
||||
|
throw new Error(`Remote contract artifacts download request failed!\n${xhrRequest.responseText}`); |
||||
|
}; |
@ -0,0 +1,60 @@ |
|||||
|
module.exports = { |
||||
|
env: { |
||||
|
browser: true, |
||||
|
es6: true, |
||||
|
jest: true, |
||||
|
}, |
||||
|
extends: [ |
||||
|
'plugin:react/recommended', |
||||
|
'airbnb', |
||||
|
], |
||||
|
globals: { |
||||
|
Atomics: 'readonly', |
||||
|
SharedArrayBuffer: 'readonly', |
||||
|
}, |
||||
|
parser: 'babel-eslint', |
||||
|
parserOptions: { |
||||
|
ecmaFeatures: { |
||||
|
jsx: true, |
||||
|
}, |
||||
|
ecmaVersion: 2018, |
||||
|
sourceType: 'module', |
||||
|
}, |
||||
|
plugins: [ |
||||
|
'react', |
||||
|
'react-hooks', |
||||
|
], |
||||
|
rules: { |
||||
|
'react/jsx-props-no-spreading': 'off', |
||||
|
'import/extensions': 'off', |
||||
|
'react/jsx-indent': [ |
||||
|
'error', |
||||
|
4, |
||||
|
{ |
||||
|
checkAttributes: true, |
||||
|
indentLogicalExpressions: true, |
||||
|
}, |
||||
|
], |
||||
|
'react/require-default-props': 'off', |
||||
|
'react/prop-types': 'off', |
||||
|
'react-hooks/rules-of-hooks': 'error', |
||||
|
'react-hooks/exhaustive-deps': 'error', |
||||
|
'max-len': ['warn', { code: 120, tabWidth: 4 }], |
||||
|
'no-unused-vars': 'warn', |
||||
|
'no-console': 'warn', |
||||
|
'no-shadow': 'warn', |
||||
|
'no-multi-str': 'warn', |
||||
|
'jsx-a11y/label-has-associated-control': [2, { |
||||
|
labelAttributes: ['label'], |
||||
|
controlComponents: ['Input'], |
||||
|
depth: 3, |
||||
|
}], |
||||
|
}, |
||||
|
settings: { |
||||
|
'import/resolver': { |
||||
|
node: { |
||||
|
extensions: ['.js', '.jsx'], |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}; |
@ -0,0 +1,22 @@ |
|||||
|
# Node |
||||
|
/node_modules |
||||
|
|
||||
|
# IDE |
||||
|
.DS_Store |
||||
|
.idea |
||||
|
|
||||
|
# Build Directories |
||||
|
/build |
||||
|
/src/build |
||||
|
|
||||
|
# Logs |
||||
|
/log |
||||
|
npm-debug.log* |
||||
|
yarn-debug.log* |
||||
|
yarn-error.log* |
||||
|
|
||||
|
# Misc |
||||
|
.env.local |
||||
|
.env.development.local |
||||
|
.env.test.local |
||||
|
.env.production.local |
@ -0,0 +1,26 @@ |
|||||
|
{ |
||||
|
"name": "concordia-contracts-provider", |
||||
|
"description": "A server that provides built contracts for Concordia.", |
||||
|
"version": "0.1.0", |
||||
|
"private": true, |
||||
|
"main": "src/index.js", |
||||
|
"scripts": { |
||||
|
"start": "node -r esm src/index.js" |
||||
|
}, |
||||
|
"license": "MIT", |
||||
|
"dependencies": { |
||||
|
"cors": "^2.8.5", |
||||
|
"esm": "~3.2.25", |
||||
|
"express": "^4.17.1", |
||||
|
"lodash": "^4.17.20", |
||||
|
"multer": "^1.4.2", |
||||
|
"multiparty": "^4.2.2" |
||||
|
}, |
||||
|
"devDependencies": { |
||||
|
"eslint": "^7.19.0", |
||||
|
"eslint-config-airbnb": "^18.2.1", |
||||
|
"eslint-plugin-jsx-a11y": "^6.4.1", |
||||
|
"eslint-plugin-react": "^7.22.0", |
||||
|
"eslint-plugin-react-hooks": "^4.2.0" |
||||
|
} |
||||
|
} |
@ -0,0 +1,3 @@ |
|||||
|
export const API_HOST = '127.0.0.1'; |
||||
|
export const API_PORT = '8400'; |
||||
|
export const UPLOADED_CONTRACTS_DIR = './contracts-uploads/'; |
@ -0,0 +1,19 @@ |
|||||
|
import * as fs from 'fs'; |
||||
|
import path from 'path'; |
||||
|
import { UPLOADED_CONTRACTS_DIR } from '../constants'; |
||||
|
|
||||
|
const downloadContracts = async (req, res) => { |
||||
|
const { params: { hash } } = req; |
||||
|
const directoryPath = path.join(`${__dirname}/../../${UPLOADED_CONTRACTS_DIR}/${hash}`); |
||||
|
const contracts = []; |
||||
|
|
||||
|
fs.readdirSync(directoryPath).forEach((contractFilename) => { |
||||
|
const rawContractData = fs.readFileSync(path.join(`${directoryPath}/${contractFilename}`), 'utf-8'); |
||||
|
const contractJson = JSON.parse(rawContractData); |
||||
|
contracts.push(contractJson); |
||||
|
}); |
||||
|
|
||||
|
res.send(contracts); |
||||
|
}; |
||||
|
|
||||
|
export default downloadContracts; |
@ -0,0 +1,19 @@ |
|||||
|
import upload from '../middleware/upload'; |
||||
|
|
||||
|
const uploadContracts = async (req, res) => { |
||||
|
try { |
||||
|
await upload(req, res); |
||||
|
|
||||
|
if (req.files.length <= 0) { |
||||
|
return res.send('You must select at least 1 file.'); |
||||
|
} |
||||
|
|
||||
|
return res.send('Files have been uploaded.'); |
||||
|
} catch (error) { |
||||
|
console.log(error); |
||||
|
|
||||
|
return res.send(`Error when trying upload many files: ${error}`); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
export default uploadContracts; |
@ -0,0 +1,19 @@ |
|||||
|
import express from 'express'; |
||||
|
import cors from 'cors'; |
||||
|
import initRoutes from './routes/web'; |
||||
|
import { API_HOST, API_PORT } from './constants'; |
||||
|
|
||||
|
const app = express(); |
||||
|
|
||||
|
const corsOptions = { |
||||
|
origin: ['localhost:7000', '127.0.0.1:7000', 'http://localhost:7000'], |
||||
|
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
|
||||
|
}; |
||||
|
|
||||
|
app.use(express.urlencoded({ extended: true })); |
||||
|
app.use(cors(corsOptions)); |
||||
|
|
||||
|
initRoutes(app); |
||||
|
app.listen(API_PORT, () => { |
||||
|
console.log(`Contracts provider listening at http://${API_HOST}:${API_PORT}`); |
||||
|
}); |
@ -0,0 +1,32 @@ |
|||||
|
import * as util from 'util'; |
||||
|
import * as path from 'path'; |
||||
|
import * as fs from 'fs'; |
||||
|
import multer from 'multer'; |
||||
|
import { UPLOADED_CONTRACTS_DIR } from '../constants'; |
||||
|
|
||||
|
const storage = multer.diskStorage({ |
||||
|
destination: (req, file, callback) => { |
||||
|
const { params: { hash } } = req; |
||||
|
const contractsPath = path.join(`${__dirname}/../../${UPLOADED_CONTRACTS_DIR}/${hash}`); |
||||
|
|
||||
|
fs.mkdirSync(contractsPath, { recursive: true }); |
||||
|
callback(null, contractsPath); |
||||
|
// callback(null, UPLOADED_CONTRACTS_DIR);
|
||||
|
}, |
||||
|
filename: (req, file, callback) => { |
||||
|
const match = ['application/json']; |
||||
|
|
||||
|
if (match.indexOf(file.mimetype) === -1) { |
||||
|
const message = `<strong>${file.originalname}</strong> is invalid. Only JSON files are accepted.`; |
||||
|
return callback(message, null); |
||||
|
} |
||||
|
|
||||
|
const filename = `${file.originalname}`; |
||||
|
callback(null, filename); |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
const uploadFiles = multer({ storage }).array('contracts'); |
||||
|
const uploadFilesMiddleware = util.promisify(uploadFiles); |
||||
|
|
||||
|
export default uploadFilesMiddleware; |
@ -0,0 +1,14 @@ |
|||||
|
import express from 'express'; |
||||
|
import downloadContracts from '../controllers/download'; |
||||
|
import uploadContracts from '../controllers/upload'; |
||||
|
|
||||
|
const router = express.Router(); |
||||
|
|
||||
|
const routes = (app) => { |
||||
|
router.get('/contracts/:hash', downloadContracts); |
||||
|
router.post('/contracts/:hash', uploadContracts); |
||||
|
|
||||
|
return app.use('/', router); |
||||
|
}; |
||||
|
|
||||
|
export default routes; |
Loading…
Reference in new issue