koa-neo4j
Version:
Rapidly create REST APIs, powered by Koa and Neo4j -- batteries included with built-in role based authentication via JWT and reusable backend components
116 lines (93 loc) • 4.52 kB
JavaScript
'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _extends = Object.assign || function (target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i];for (var key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {target[key] = source[key];}}}return target;};var _koa = require('koa');var _koa2 = _interopRequireDefault(_koa);
var _koaRouter = require('koa-router');var _koaRouter2 = _interopRequireDefault(_koaRouter);
var _koaBodyparser = require('koa-bodyparser');var _koaBodyparser2 = _interopRequireDefault(_koaBodyparser);
var _kcors = require('kcors');var _kcors2 = _interopRequireDefault(_kcors);
var _auth = require('./auth');
var _data = require('./data');
var _procedure = require('./procedure');
var _util = require('./util');
var _http = require('http');var _http2 = _interopRequireDefault(_http);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}
const defaultOptions = {
apis: [],
neo4j: {
url: 'neo4j://localhost',
user: 'neo4j',
password: 'neo4j' },
sensitive: true };
class KoaNeo4jApp extends _koa2.default {
constructor(options) {
super();
options = _extends({}, defaultOptions, options);
this.router = new _koaRouter2.default({ sensitive: options.sensitive });
this.methods = {
'GET': this.router.get,
'POST': this.router.post,
'PUT': this.router.put,
'DEL': this.router.del,
'PATCH': this.router.patch };
this.neo4jConnection = new _data.Neo4jConnection(options.neo4j);
this.neo4jInitialized = this.neo4jConnection.initialized;
const server = _http2.default.createServer(this.callback());
this.server = server;
if (!options.loadMiddlewareByApp) {
this.configuredAuthentication = false;
if (options.authentication)
this.configureAuthentication(options.authentication);
this.
use((0, _kcors2.default)(options.cors)).
use((0, _koaBodyparser2.default)({
onerror(error, ctx) {
ctx.throw(400, `cannot parse request body, ${JSON.stringify(error)}`);
} }));
this.use(async (ctx, next) => {
try {
const start = new Date();
await next();
const ms = new Date() - start;
console.log('%s %s - %s ms', ctx.method, ctx.originalUrl, ms);
} catch (error) {
ctx.body = String(error);
ctx.status = error.status || 500;
console.log('%s %s - then%s', ctx.method, ctx.originalUrl,
error.stack || error);
}
});
}
if (!options.loadRouteByApp) {
this.use(this.router.routes());
for (const api of options.apis)
this.defineAPI(api);
}
}
defineAPI(options) {
const api = new _data.API(this.neo4jConnection, options);
const handler = async (ctx, next) => {
if (api.requiresJwtAuthentication)
try {
await this.authentication.authenticateJwt(ctx, () => {});
} catch (error) {
// No Authorization header
ctx.throw(401, 'authorization required');
}
if (api.requiresJwtAuthentication &&
!(0, _util.haveIntersection)(ctx.user.roles, api.allowedRoles))
ctx.throw(403, 'user does not have permission for this resource');
const params = _extends({}, ctx.query, ctx.params, ctx.request.body);
ctx.body = await api.invoke(params, ctx);
await next();
};
this.methods[api.method].apply(this.router, [api.route, handler]);
return api;
}
configureAuthentication(options) {
if (this.configuredAuthentication)
throw new Error('authentication already configured');
this.authentication = new _auth.Authentication(this.neo4jConnection, options);
this.use(this.authentication.passport.initialize());
this.router.post(options.route, this.authentication.authenticateLocal);
this.configuredAuthentication = true;
}
createProcedure(options) {
return (0, _procedure.createProcedure)(this.neo4jConnection, options);
}}exports.default =
KoaNeo4jApp;