Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into feature/addDataModel
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelTaylor3D committed May 20, 2022
2 parents 73bf7a3 + ed6433e commit 11fcf52
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 93 deletions.
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "climate-warehouse",
"version": "1.0.1",
"version": "1.0.3",
"private": true,
"bin": "build/server.js",
"type": "module",
Expand All @@ -17,13 +17,17 @@
"resetTestDb": "rm -f ./test.sqlite3 && rm -f ./testMirror.sqlite3",
"resetMirrorDb": "npx sequelize-cli db:drop --env mirror",
"prepare": "husky install",
"build": "babel src --keep-file-extension --out-dir build --copy-files",
"build": "babel src --keep-file-extension --out-dir build --copy-files && cp package.json ./build",
"build-migrations": "babel migrations --keep-file-extension --out-dir dist/migrations --copy-files",
"prepare-binary": "rm -rf dist && mkdir dist",
"create-win-x64-dist": "npm run build && npm run prepare-binary && pkg package.json -t node16-win-x64 --out-path dist",
"create-mac-x64-dist": "npm run build && npm run prepare-binary && pkg package.json -t node16-macos-x64 --out-path dist",
"create-linux-x64-dist": "npm run build && npm run prepare-binary && pkg package.json -t node16-linux-x64 --out-path dist"
},
"pkg": {
"scripts": "package.json",
"assets": "package.json"
},
"dependencies": {
"body-parser": "^1.19.0",
"char-spinner": "^1.0.1",
Expand Down
3 changes: 1 addition & 2 deletions src/datalayer/writeService.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const syncDataLayer = async (storeId, data, failedCallback) => {
};

const retry = (storeId, changeList, failedCallback, retryAttempts) => {
logger.info('RETRYING...', retryAttempts);
logger.info(`Retrying pushing to store ${storeId}: ${retryAttempts}`);
if (retryAttempts >= 60) {
logger.info(
'Could not push changelist to datalayer after retrying 10 times',
Expand All @@ -46,7 +46,6 @@ const retry = (storeId, changeList, failedCallback, retryAttempts) => {
}

setTimeout(async () => {
logger.info('Retrying...', storeId);
await pushChangesWhenStoreIsAvailable(
storeId,
changeList,
Expand Down
111 changes: 111 additions & 0 deletions src/middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
'use strict';

import _ from 'lodash';

import express from 'express';
import bodyParser from 'body-parser';
import cors from 'cors';
import fileUpload from 'express-fileupload';
import { V1Router } from './routes/v1';
import { getConfig } from './utils/config-loader';
import { logger } from './config/logger.cjs';
import {
assertChiaNetworkMatchInConfiguration,
assertDataLayerAvailable,
assertWalletIsAvailable,
} from './utils/data-assertions';
import packageJson from '../package.json';

const { API_KEY, READ_ONLY } = getConfig().APP;

const headerKeys = Object.freeze({
API_VERSION_HEADER_KEY: 'x-api-version',
CR_READY_ONLY_HEADER_KEY: 'cw-read-only',
DATA_MODEL_VERION_HEADER_KEY: 'x-datamodel-version',
});

const app = express();

app.use(
cors({
exposedHeaders: Object.values(headerKeys).join(','),
}),
);

app.use(express.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(fileUpload());

// Common assertions on every endpoint
app.use(async function (req, res, next) {
try {
await assertChiaNetworkMatchInConfiguration();
await assertDataLayerAvailable();
await assertWalletIsAvailable();
next();
} catch (err) {
res.status(400).json({
message: 'Chia Exception',
error: err.message,
});
}
});

// Add optional API key if set in .env file
app.use(function (req, res, next) {
if (API_KEY && API_KEY !== '') {
const apikey = req.header('x-api-key');
if (API_KEY === apikey) {
next();
} else {
res.status(403).json({ message: 'API key not found' });
}
} else {
next();
}
});

app.use(function (req, res, next) {
if (READ_ONLY) {
res.setHeader(headerKeys.CR_READY_ONLY_HEADER_KEY, READ_ONLY);
} else {
res.setHeader(headerKeys.CR_READY_ONLY_HEADER_KEY, false);
}

next();
});

app.use(function (req, res, next) {
logger.debug(
`Setting header x-api-verion to package.json version: ${packageJson.version}`,
);
const version = packageJson.version;
res.setHeader(headerKeys.API_VERSION_HEADER_KEY, version);

const majorVersion = version.split('.')[0];
res.setHeader(headerKeys.DATA_MODEL_VERION_HEADER_KEY, `v${majorVersion}`);

next();
});

app.use('/v1', V1Router);

app.use((err, req, res, next) => {
if (err) {
if (_.get(err, 'error.details')) {
// format Joi validation errors
return res.status(400).json({
message: 'Data Validation error',
errors: err.error.details.map((detail) => {
return _.get(detail, 'context.message', detail.message);
}),
});
}

return res.status(err.status).json(err);
}

next();
});

export default app;
90 changes: 1 addition & 89 deletions src/routes/index.js
Original file line number Diff line number Diff line change
@@ -1,82 +1,11 @@
'use strict';

import _ from 'lodash';

import express from 'express';
import bodyParser from 'body-parser';
import cors from 'cors';
import fileUpload from 'express-fileupload';
import { prepareDb } from '../database';
import scheduler from '../tasks';
import { V1Router } from './v1';
import { sequelize } from '../database';
import { getConfig } from '../utils/config-loader';
import { fileLoader } from '../utils/file-loader';
import { logger } from '../config/logger.cjs';
import {
assertChiaNetworkMatchInConfiguration,
assertDataLayerAvailable,
assertWalletIsAvailable,
} from '../utils/data-assertions';

const { API_KEY, READ_ONLY } = getConfig().APP;
const app = express();

app.use(cors());
app.use(express.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(fileUpload());

// Common assertions on every endpoint
app.use(async function (req, res, next) {
try {
await assertChiaNetworkMatchInConfiguration();
await assertDataLayerAvailable();
await assertWalletIsAvailable();
next();
} catch (err) {
res.status(400).json({
message: 'Chia Exception',
error: err.message,
});
}
});

// Add optional API key if set in .env file
app.use(function (req, res, next) {
if (API_KEY && API_KEY !== '') {
const apikey = req.header('x-api-key');
if (API_KEY === apikey) {
next();
} else {
res.status(403).json({ message: 'API key not found' });
}
} else {
next();
}
});

// Add readonly header if set in .env file
app.use(function (req, res, next) {
res.setHeader('Access-Control-Expose-Headers', 'cw-read-only');
if (READ_ONLY) {
res.setHeader('cw-read-only', READ_ONLY);
} else {
res.setHeader('cw-read-only', false);
}

next();
});

app.use(function (req, res, next) {
const packageJson = fileLoader('package.json');
logger.debug(`Setting header x-api-verion to package.json version: ${packageJson.version}`);
res.setHeader('x-api-version', packageJson.version);

next();
});

app.use('/v1', V1Router);
import app from '../middleware';

sequelize.authenticate().then(async () => {
logger.info('Connected to database');
Expand All @@ -86,21 +15,4 @@ sequelize.authenticate().then(async () => {
}, 5000);
});

app.use((err, req, res, next) => {
if (err) {
if (_.get(err, 'error.details')) {
// format Joi validation errors
return res.status(400).json({
message: 'Data Validation error',
errors: err.error.details.map((detail) => {
return _.get(detail, 'context.message', detail.message);
}),
});
}

return res.status(err.status).json(err);
}

next();
});
export default app;

0 comments on commit 11fcf52

Please sign in to comment.