@sphereon/ssi-express-support
Version:
281 lines • 12 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExpressCorsConfigurer = exports.ExpressBuilder = void 0;
/**
* @public
*/
const body_parser_1 = __importDefault(require("body-parser"));
const cors_1 = __importDefault(require("cors"));
const express_1 = __importDefault(require("express"));
const express_session_1 = __importDefault(require("express-session"));
const http_terminator_1 = require("http-terminator");
const morgan_1 = __importDefault(require("morgan"));
const passport_1 = __importDefault(require("passport"));
const auth_utils_1 = require("./auth-utils");
const express_utils_1 = require("./express-utils");
const functions_1 = require("./functions");
class ExpressBuilder {
constructor(opts) {
this._handlers = [];
this._startListen = undefined;
this._usePassportAuth = false;
const { existingExpress, envVarPrefix } = opts !== null && opts !== void 0 ? opts : {};
if (existingExpress) {
this.withExpress(existingExpress);
}
this.envVarPrefix = envVarPrefix !== null && envVarPrefix !== void 0 ? envVarPrefix : '';
}
static fromExistingExpress(opts) {
return new ExpressBuilder(opts !== null && opts !== void 0 ? opts : {});
}
static fromServerOpts(opts) {
var _a;
const builder = new ExpressBuilder({ existingExpress: opts === null || opts === void 0 ? void 0 : opts.existingExpress, envVarPrefix: opts === null || opts === void 0 ? void 0 : opts.envVarPrefix });
return builder.withEnableListenOpts(Object.assign(Object.assign({}, opts), { hostnameOrIP: opts.hostname, startOnBuild: (_a = opts.startListening) !== null && _a !== void 0 ? _a : false }));
}
enableListen(startOnBuild) {
if (startOnBuild !== undefined) {
this._startListen = startOnBuild;
}
return this;
}
withMorganLogging(opts) {
var _a, _b;
if ((opts === null || opts === void 0 ? void 0 : opts.existingMorgan) && (opts.format || opts.options)) {
throw Error('Cannot using an existing morgan with either a format or options');
}
this._morgan = (_a = opts === null || opts === void 0 ? void 0 : opts.existingMorgan) !== null && _a !== void 0 ? _a : (0, morgan_1.default)((_b = opts === null || opts === void 0 ? void 0 : opts.format) !== null && _b !== void 0 ? _b : 'dev', opts === null || opts === void 0 ? void 0 : opts.options);
return this;
}
withEnableListenOpts({ port, hostnameOrIP, callback, startOnBuild, }) {
port && this.withPort(port);
hostnameOrIP && this.withHostname(hostnameOrIP);
if (typeof callback === 'function') {
this.withListenCallback(callback);
}
this._startListen = startOnBuild === true;
return this;
}
withPort(port) {
this.port = port;
return this;
}
withHostname(hostnameOrIP) {
this.hostnameOrIP = hostnameOrIP;
return this;
}
withListenCallback(callback) {
this.listenCallback = callback;
return this;
}
withExpress(existingExpress) {
this.existingExpress = existingExpress;
this._startListen = false;
return this;
}
withCorsConfigurer(configurer) {
this._corsConfigurer = configurer;
return this;
}
withPassportAuth(usePassport, initializeOptions) {
this._usePassportAuth = usePassport;
this._passportInitOpts = initializeOptions;
return this;
}
withGlobalUserIsInRole(userIsInRole) {
this._userIsInRole = userIsInRole;
return this;
}
withEnforcer(enforcer) {
this._enforcer = enforcer;
return this;
}
startListening(express) {
this._server = express.listen(this.getPort(), this.getHostname(), this.listenCallback);
this._terminator = (0, http_terminator_1.createHttpTerminator)({
server: this._server,
// gracefulTerminationTimeout: 10
});
return { server: this._server, terminator: this._terminator };
}
getHostname() {
var _a, _b;
return (_b = (_a = this.hostnameOrIP) !== null && _a !== void 0 ? _a : (0, functions_1.env)('HOSTNAME', this.envVarPrefix)) !== null && _b !== void 0 ? _b : '0.0.0.0';
}
getPort() {
var _a, _b;
return ((_b = (_a = this.port) !== null && _a !== void 0 ? _a : (0, functions_1.env)('PORT', this.envVarPrefix)) !== null && _b !== void 0 ? _b : 5000);
}
setHandlers(handlers) {
if (Array.isArray(handlers)) {
this._handlers = handlers;
}
else if (handlers) {
if (!this._handlers) {
this._handlers = [];
}
this._handlers.push(handlers);
}
else {
this._handlers = [];
}
return this;
}
addHandler(handler) {
if (!this._handlers) {
this._handlers = [];
}
this._handlers.push(handler);
return this;
}
withSessionOptions(sessionOpts) {
this._sessionOpts = sessionOpts;
return this;
}
build(opts) {
const express = this.buildExpress(opts);
const startListening = (opts === null || opts === void 0 ? void 0 : opts.startListening) === undefined ? this._startListen !== true : opts.startListening;
let started = this._server !== undefined;
if (startListening && !started) {
this.startListening(express);
started = true;
}
return {
express,
port: this.getPort(),
hostname: this.getHostname(),
userIsInRole: this._userIsInRole,
startListening,
enforcer: this._enforcer,
start: (opts) => {
if (opts === null || opts === void 0 ? void 0 : opts.doNotStartListening) {
console.log('Express will not start listening. You will have to start it yourself');
}
else {
if (!started) {
this.startListening(express);
started = true;
}
}
if ((opts === null || opts === void 0 ? void 0 : opts.disableErrorHandler) !== true) {
express.use(express_utils_1.jsonErrorHandler);
}
return { server: this._server, terminator: this._terminator };
},
stop: (terminator) => __awaiter(this, void 0, void 0, function* () {
const term = terminator !== null && terminator !== void 0 ? terminator : this._terminator;
if (!term) {
return false;
}
return yield term.terminate().then(() => true);
}),
};
}
buildExpress(opts) {
var _a, _b, _c;
const app = (_b = (_a = opts === null || opts === void 0 ? void 0 : opts.express) !== null && _a !== void 0 ? _a : this.existingExpress) !== null && _b !== void 0 ? _b : (0, express_1.default)();
if (this._morgan) {
app.use(this._morgan);
}
if (this._sessionOpts) {
const store = (_c = this._sessionOpts.store) !== null && _c !== void 0 ? _c : new express_session_1.default.MemoryStore();
this._sessionOpts.store = store;
app.use((0, express_session_1.default)(this._sessionOpts));
}
if (this._usePassportAuth) {
app.use(passport_1.default.initialize(this._passportInitOpts));
if (this._sessionOpts) {
// app.use(passport.authenticate('session'))
//_sessionOpts are not for passport session, they are for express above
app.use(passport_1.default.session());
}
}
if (this._userIsInRole) {
app.use((0, auth_utils_1.checkUserIsInRole)({ roles: this._userIsInRole }));
}
if (this._corsConfigurer) {
this._corsConfigurer.configure({ existingExpress: app });
}
// @ts-ignore
this._handlers && this._handlers.length > 0 && app.use(this._handlers);
// @ts-ignore
(opts === null || opts === void 0 ? void 0 : opts.handlers) && app.use(opts.handlers);
//fixme: this should come from the config
app.use(body_parser_1.default.urlencoded({ extended: true }));
app.use(body_parser_1.default.json({ limit: '5mb' }));
return app;
}
}
exports.ExpressBuilder = ExpressBuilder;
class ExpressCorsConfigurer {
constructor(args) {
const { existingExpress, envVarPrefix } = args !== null && args !== void 0 ? args : {};
this._express = existingExpress;
this._envVarPrefix = envVarPrefix;
}
allowOrigin(value) {
this._allowOrigin = value;
return this;
}
disableCors(value) {
this._disableCors = value;
return this;
}
allowMethods(value) {
this._allowMethods = value;
return this;
}
allowedHeaders(value) {
this._allowedHeaders = value;
return this;
}
allowCredentials(value) {
this._allowCredentials = value;
return this;
}
configure({ existingExpress }) {
var _a, _b, _c;
const express = existingExpress !== null && existingExpress !== void 0 ? existingExpress : this._express;
if (!express) {
throw Error('No express passed in during construction or configure');
}
const disableCorsEnv = (0, functions_1.env)('CORS_DISABLE', this._envVarPrefix);
const corsDisabled = (_a = this._disableCors) !== null && _a !== void 0 ? _a : (disableCorsEnv ? /true/.test(disableCorsEnv) : false);
if (corsDisabled) {
return;
}
const envAllowOriginStr = (_b = (0, functions_1.env)('CORS_ALLOW_ORIGIN', this._envVarPrefix)) !== null && _b !== void 0 ? _b : '*';
let envAllowOrigin;
if (envAllowOriginStr.includes(',')) {
envAllowOrigin = envAllowOriginStr.split(',');
}
else if (envAllowOriginStr.includes(' ')) {
envAllowOrigin = envAllowOriginStr.split(' ');
}
else {
envAllowOrigin = envAllowOriginStr;
}
if (Array.isArray(envAllowOrigin) && envAllowOrigin.length === 1) {
envAllowOrigin = envAllowOrigin[0];
}
const corsOptions = Object.assign(Object.assign(Object.assign(Object.assign({ origin: (_c = this._allowOrigin) !== null && _c !== void 0 ? _c : envAllowOrigin }, (this._allowMethods && { methods: this._allowMethods })), (this._allowedHeaders && { allowedHeaders: this._allowedHeaders })), (this._allowCredentials !== undefined && { credentials: this._allowCredentials })), { optionsSuccessStatus: 204 });
if (this._enablePreflightOptions) {
express.options('*', (0, cors_1.default)(corsOptions));
}
express.use((0, cors_1.default)(corsOptions));
}
}
exports.ExpressCorsConfigurer = ExpressCorsConfigurer;
//# sourceMappingURL=express-builders.js.map