-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3cde7fa
commit e541ef2
Showing
6 changed files
with
356 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
|
||
const config = require('./config/index'); | ||
const log = require('./components/logger'); | ||
const dotenv = require('dotenv'); | ||
const express = require("express"); | ||
const axios = require("axios"); | ||
const cors = require('cors'); | ||
const NodeCache = require("node-cache"); | ||
const apiRouter = express.Router(); | ||
const instituteRouter = require('./routes/institute-router'); | ||
const app = express(); | ||
app.use(cors()); | ||
|
||
app.use(/(\/api)?/, apiRouter); | ||
|
||
//institute Router | ||
apiRouter.use('/v1/institute', instituteRouter); | ||
|
||
|
||
//Handle 500 error | ||
app.use((err, _req, res, next) => { | ||
res?.redirect(config?.get('server:frontend') + '/error?message=500_internal_error'); | ||
next(); | ||
}); | ||
|
||
// Handle 404 error | ||
app.use((_req, res) => { | ||
res.redirect(config?.get('server:frontend') + '/error?message=404_Page_Not_Found'); | ||
}); | ||
|
||
// Prevent unhandled errors from crashing application | ||
process.on('unhandledRejection', err => { | ||
}); | ||
module.exports = app; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
'use strict'; | ||
|
||
const config = require('../config/index'); | ||
const { createLogger, format, transports } = require('winston'); | ||
require('winston-daily-rotate-file'); | ||
const { inspect } = require('util'); | ||
const { omit, pickBy } = require('lodash'); | ||
const stripAnsi = require('strip-ansi'); | ||
const safeStringify = require('fast-safe-stringify'); | ||
|
||
|
||
function isPrimitive(val) { | ||
return val === null || (typeof val !== 'object' && typeof val !== 'function'); | ||
} | ||
|
||
function formatWithInspect(val, colors = true) { | ||
if (val instanceof Error) { | ||
return ''; | ||
} | ||
|
||
const shouldFormat = typeof val !== 'string'; | ||
const formattedVal = shouldFormat ? inspect(val, { depth: null, colors }) : (colors ? val : stripAnsi(val)); | ||
|
||
return isPrimitive(val) ? formattedVal : `\n${formattedVal}`; | ||
} | ||
|
||
/** | ||
* Handles all the different log formats | ||
* https://github.com/winstonjs/winston/issues/1427#issuecomment-535297716 | ||
* https://github.com/winstonjs/winston/issues/1427#issuecomment-583199496 | ||
* @param {*} colors | ||
*/ | ||
function getDomainWinstonLoggerFormat(colors = true) { | ||
const colorize = colors ? format.colorize() : null; | ||
const loggingFormats = [ | ||
format.timestamp({ | ||
format: 'YYYY-MM-DD HH:mm:ss.SSS' | ||
}), | ||
format.errors({ stack: true }), | ||
colorize, | ||
format.printf((info) => { | ||
const stackTrace = info.stack ? `\n${info.stack}` : ''; | ||
|
||
// handle single object | ||
if (!info.message) { | ||
const obj = omit(info, ['level', 'timestamp', Symbol.for('level')]); | ||
return `${info.timestamp} - ${info.level}: ${formatWithInspect(obj, colors)}${stackTrace}`; | ||
} | ||
|
||
const splatArgs = info[Symbol.for('splat')] || []; | ||
const rest = splatArgs.map(data => formatWithInspect(data, colors)).join(' '); | ||
const msg = formatWithInspect(info.message, colors); | ||
|
||
return `${info.timestamp} - ${info.level}: ${msg} ${rest}${stackTrace}`; | ||
}), | ||
].filter(Boolean); | ||
return format.combine(...loggingFormats); | ||
} | ||
|
||
/** | ||
* Handles JSON formats | ||
*/ | ||
function getDomainWinstonLoggerJsonFormat() { | ||
const loggingFormats = [ | ||
format.timestamp({ | ||
format: 'YYYY-MM-DD HH:mm:ss.SSS' | ||
}), | ||
format.errors({ stack: true }), | ||
format.printf((info) => { | ||
const stackTrace = info.stack || ''; | ||
|
||
let message; | ||
// handle single object | ||
if (!info.message) { | ||
const obj = omit(info, ['level', 'timestamp', Symbol.for('level')]); | ||
message = obj; | ||
} else { | ||
message = stripAnsi(info.message); | ||
} | ||
|
||
const splatArgs = info[Symbol.for('splat')] || []; | ||
const detail = splatArgs.map(data => typeof data === 'string' ? stripAnsi(data) : data); | ||
|
||
return safeStringify(pickBy({ | ||
timestamp: info.timestamp, | ||
level: info.level, | ||
message, | ||
detail: detail.length > 0 ? detail : null, | ||
stackTrace | ||
})); | ||
}), | ||
]; | ||
return format.combine(...loggingFormats); | ||
} | ||
|
||
const logger = createLogger({ | ||
level: config.get('server:logLevel'), | ||
format: getDomainWinstonLoggerJsonFormat(), | ||
transports: [ | ||
new transports.DailyRotateFile({ | ||
filename: 'app-%DATE%.log', | ||
dirname: './logs', | ||
datePattern: 'YYYY-MM-DD', | ||
maxSize: '5m', | ||
maxFiles: 1, | ||
zippedArchive: true, | ||
}) | ||
] | ||
}); | ||
|
||
logger.add(new transports.Console({ | ||
format: getDomainWinstonLoggerFormat(true) | ||
})); | ||
|
||
module.exports = logger; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
'use strict'; | ||
const nconf = require('nconf'); | ||
const dotenv = require('dotenv'); | ||
const path = require('path'); | ||
dotenv.config(); | ||
|
||
const env = process.env.NODE_ENV || 'local'; | ||
nconf.argv() | ||
.env() | ||
.file({ file: path.join(__dirname, `${env}.json`) }); | ||
|
||
//injects environment variables into the json file | ||
nconf.overrides({ | ||
environment: env, | ||
|
||
server: { | ||
logLevel: process.env.LOG_LEVEL, | ||
morganFormat: 'dev', | ||
port: 8080 | ||
} | ||
}); | ||
nconf.defaults({ | ||
environment: env, | ||
server: { | ||
frontend: process.env.SERVER_FRONTEND, | ||
backend: process.env.SERVER_FRONTEND + '/api', | ||
logLevel: process.env.LOG_LEVEL, | ||
morganFormat: 'dev', | ||
port: 8080, | ||
session: { | ||
maxAge: +process.env.SESSION_MAX_AGE | ||
}, | ||
instituteAPIURL: process.env.INSTITUTE_API_URL, | ||
}, | ||
oidc: { | ||
clientId: process.env.SOAM_CLIENT_ID, | ||
clientSecret: process.env.SOAM_CLIENT_SECRET, | ||
discovery: process.env.SOAM_DISCOVERY | ||
}, | ||
}); | ||
module.exports = nconf; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
|
||
const express = require('express'); | ||
const router = express.Router(); | ||
const log = require('../components/logger'); | ||
const config = require('../config/index'); | ||
const NodeCache = require("node-cache"); | ||
const jsonwebtoken = require("jsonwebtoken"); | ||
const axios = require("axios"); | ||
|
||
const cache = new NodeCache({ stdTTL: config.get("server:instituteAPITokenExpiry") }); | ||
const clientId = config.get("oidc:clientId"); | ||
const clientSecret = config.get("oidc:clientSecret") | ||
const tokenEndpoint = config.get("oidc:tokenEndpoint") | ||
|
||
const data = { | ||
grant_type: "client_credentials", | ||
client_id: clientId, | ||
client_secret: clientSecret, | ||
}; | ||
|
||
//Batch Routes | ||
router.get('/*',checkToken, getInstituteAPI); | ||
|
||
async function getNewToken(req, res, next) { | ||
await axios | ||
.post(tokenEndpoint, data, { | ||
headers: { | ||
"Content-Type": "application/x-www-form-urlencoded", | ||
}, | ||
}) | ||
.then((response) => { | ||
let accessToken = response.data.access_token; | ||
cache.set("token", accessToken); | ||
}) | ||
.catch((error) => { | ||
console.error("Error:", error.response.data); | ||
}); | ||
} | ||
async function checkToken(req, res, next) { | ||
try{ | ||
if(await !cache.has("token") ){ | ||
await getNewToken(); | ||
} | ||
next(); | ||
}catch(error){ | ||
console.log(error) | ||
} | ||
} | ||
async function getInstituteAPI(req, res) { | ||
const memToken = await cache.get("token"); | ||
const url = `${config.get('server:instituteAPIURL')}/institute` + req.url; | ||
axios | ||
.get(url, { headers: { Authorization: `Bearer ${memToken}` } }) | ||
.then((response) => { | ||
res.json(response.data); | ||
log.info(req.url); | ||
}) | ||
.catch((e) => { | ||
log.error('getData Error', e.response ? e.response.status : e.message); | ||
}); | ||
} | ||
module.exports = router; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
'use strict'; | ||
|
||
const config = require('./config/index'); | ||
const http = require('http'); | ||
const log = require('./components/logger'); | ||
const dotenv = require('dotenv'); | ||
dotenv.config(); | ||
|
||
const app = require('./app'); | ||
|
||
/** | ||
* Get port from environment and store in Express. | ||
*/ | ||
const port = config.get('server:port'); | ||
|
||
const server = http.createServer(app); | ||
|
||
/** | ||
* Listen on provided port, on all network interfaces. | ||
*/ | ||
server.listen(port); | ||
server.on('error', onError); | ||
server.on('listening', onListening); | ||
|
||
/** | ||
* Normalize a port into a number, string, or false. | ||
*/ | ||
function normalizePort(val) { | ||
const portNum = parseInt(val, 10); | ||
|
||
if (isNaN(portNum)) { | ||
// named pipe | ||
return val; | ||
} | ||
|
||
if (portNum >= 0) { | ||
// port number | ||
return portNum; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
/** | ||
* Event listener for HTTP server "error" event. | ||
*/ | ||
function onError(error) { | ||
if (error.syscall !== 'listen') { | ||
throw error; | ||
} | ||
|
||
var bind = typeof port === 'string' ? | ||
'Pipe ' + port : | ||
'Port ' + port; | ||
|
||
// handle specific listen errors with friendly messages | ||
|
||
} | ||
|
||
/** | ||
* Event listener for HTTP server "listening" event. | ||
*/ | ||
|
||
function onListening() { | ||
const addr = server.address(); | ||
const bind = typeof addr === 'string' ? | ||
'pipe ' + addr : | ||
'port ' + addr.port; | ||
log.info('Listening on ' + bind); | ||
} | ||
process.on('SIGINT',() => { | ||
server.close(() => { | ||
}); | ||
}); | ||
|
||
process.on('SIGTERM', () => { | ||
server.close(() => { | ||
}); | ||
}); | ||
|
||
//exports are purely for testing | ||
module.exports = { | ||
normalizePort, | ||
onError, | ||
onListening, | ||
server | ||
}; |