@jovian/type-tools
Version:
TypeTools is a Typescript library for providing extensible tooling runtime validations and type helpers.
1,051 lines (1,050 loc) • 85.9 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
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 __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HttpCacheOp = exports.CacheEntry = exports.CacheDef = exports.CacheParser = exports.PostHandler = exports.PreHandler = exports.HttpOp = exports.HttpPathResolution = exports.HttpResponse = exports.HttpRequest = exports.HttpServerShim = exports.HTTP = exports.isClass = exports.HttpBaseLib = exports.HttpServerShimApi = exports.HttpApiOptions = exports.ReqProcessor = exports.HttpShimCode = void 0;
var express = __importStar(require("express"));
var config_util_1 = require("../../src/common/util/config.util");
var dev_null_proxy_1 = require("../../src/common/util/convenience/dev.null.proxy");
var secure_channel_1 = require("../secure-channel/secure-channel");
var http_models_1 = require("./http.models");
var http_shim_worker_security_1 = require("./http.shim.worker.security");
var defaultConfig = __importStar(require("./http.shim.default.config.json"));
var defaultGlobalConfig = __importStar(require("./http.shim.global.conf.json"));
var axios = __importStar(require("axios"));
var globals_ix_1 = require("../../src/common/globals.ix");
var secret_resolver_1 = require("../secret-resoluton/secret-resolver");
var destor_client_1 = require("./destor/destor.client");
var url = __importStar(require("url"));
var process_exit_handler_1 = require("../proc/process.exit.handler");
var HttpShimCodeEnum;
(function (HttpShimCodeEnum) {
HttpShimCodeEnum[HttpShimCodeEnum["ACCESSOR_HEADER_NOT_FOUND"] = 0] = "ACCESSOR_HEADER_NOT_FOUND";
HttpShimCodeEnum[HttpShimCodeEnum["ACCESSOR_BAD_FORMAT"] = 1] = "ACCESSOR_BAD_FORMAT";
HttpShimCodeEnum[HttpShimCodeEnum["NO_ACCESSOR"] = 2] = "NO_ACCESSOR";
HttpShimCodeEnum[HttpShimCodeEnum["ENCRYPTED_OP_NO_SECURE_PAYLOAD"] = 3] = "ENCRYPTED_OP_NO_SECURE_PAYLOAD";
HttpShimCodeEnum[HttpShimCodeEnum["ENCRYPTED_OP_PATH_NOT_FOUND"] = 4] = "ENCRYPTED_OP_PATH_NOT_FOUND";
HttpShimCodeEnum[HttpShimCodeEnum["ENCRYPTED_OP_METHOD_NOT_FOUND"] = 5] = "ENCRYPTED_OP_METHOD_NOT_FOUND";
HttpShimCodeEnum[HttpShimCodeEnum["ENCRYPTED_OP_NON_JSON_PAYLOAD"] = 6] = "ENCRYPTED_OP_NON_JSON_PAYLOAD";
HttpShimCodeEnum[HttpShimCodeEnum["SECURE_CHANNEL_NOT_FOUND"] = 7] = "SECURE_CHANNEL_NOT_FOUND";
HttpShimCodeEnum[HttpShimCodeEnum["AUTH_HEADER_NOT_FOUND"] = 8] = "AUTH_HEADER_NOT_FOUND";
HttpShimCodeEnum[HttpShimCodeEnum["AUTH_HEADER_NOT_VALID"] = 9] = "AUTH_HEADER_NOT_VALID";
HttpShimCodeEnum[HttpShimCodeEnum["AUTH_HEADER_SIGNED_BUT_PUBLIC_KEY_NOT_FOUND"] = 10] = "AUTH_HEADER_SIGNED_BUT_PUBLIC_KEY_NOT_FOUND";
HttpShimCodeEnum[HttpShimCodeEnum["AUTH_HEADER_SIGNED_NO_ROLES_MAP"] = 11] = "AUTH_HEADER_SIGNED_NO_ROLES_MAP";
HttpShimCodeEnum[HttpShimCodeEnum["AUTH_HEADER_SIGNED_ROLE_UNAUTHORZIED_FOR_API"] = 12] = "AUTH_HEADER_SIGNED_ROLE_UNAUTHORZIED_FOR_API";
HttpShimCodeEnum[HttpShimCodeEnum["AUTH_HEADER_SIGNED_BUT_API_DENIES_ALL"] = 13] = "AUTH_HEADER_SIGNED_BUT_API_DENIES_ALL";
})(HttpShimCodeEnum || (HttpShimCodeEnum = {}));
exports.HttpShimCode = (0, globals_ix_1.ReturnCodeFamily)('HttpShimCode', HttpShimCodeEnum);
var ReqProcessor;
(function (ReqProcessor) {
ReqProcessor["AUTH"] = "AUTH";
ReqProcessor["BASIC"] = "BASIC";
ReqProcessor["DECRYPT"] = "DECRYPT";
ReqProcessor["ENCRYPT"] = "ENCRYPT";
})(ReqProcessor = exports.ReqProcessor || (exports.ReqProcessor = {}));
var HttpApiOptions = (function () {
function HttpApiOptions() {
}
return HttpApiOptions;
}());
exports.HttpApiOptions = HttpApiOptions;
var HttpServerShimApi = (function (_super) {
__extends(HttpServerShimApi, _super);
function HttpServerShimApi() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.path = '';
_this.fullpath = '';
_this.method = http_models_1.HttpMethod.GET;
return _this;
}
return HttpServerShimApi;
}(HttpApiOptions));
exports.HttpServerShimApi = HttpServerShimApi;
var HttpBaseLib;
(function (HttpBaseLib) {
HttpBaseLib["EXPRESS"] = "EXPRESS";
})(HttpBaseLib = exports.HttpBaseLib || (exports.HttpBaseLib = {}));
function isClass(target) {
return !!target.prototype && !!target.constructor.name;
}
exports.isClass = isClass;
function methodsRegister(httpMethods, path, apiOptions) {
path = path.replace(/\/\//g, '/');
return function (target, propertyKey, descriptor) {
for (var _i = 0, httpMethods_1 = httpMethods; _i < httpMethods_1.length; _i++) {
var httpMethod = httpMethods_1[_i];
var apiKey = "".concat(httpMethod, " ").concat(path);
var methodApi = {
class: target.constructor,
className: target.constructor.name,
method: httpMethod,
path: path,
handlerName: propertyKey
};
if (apiOptions) {
Object.assign(methodApi, apiOptions);
}
if (!target.apiMap) {
target.apiMap = {};
}
target.apiMap[apiKey] = methodApi;
if (!target.apiRegistrations) {
target.apiRegistrations = [];
}
target.addRegistration(methodApi);
}
};
}
var HTTP = (function () {
function HTTP() {
}
var _a;
_a = HTTP;
HTTP.GET = (function (path, apiOptions) {
return methodsRegister([http_models_1.HttpMethod.GET], path, apiOptions);
});
HTTP.POST = (function (path, apiOptions) {
return methodsRegister([http_models_1.HttpMethod.POST], path, apiOptions);
});
HTTP.PATCH = (function (path, apiOptions) {
return methodsRegister([http_models_1.HttpMethod.PATCH], path, apiOptions);
});
HTTP.DELETE = (function (path, apiOptions) {
return methodsRegister([http_models_1.HttpMethod.DELETE], path, apiOptions);
});
HTTP.METHODS = (function (methods, path, apiOptions) {
return methodsRegister(methods, path, apiOptions);
});
HTTP.ACCESS = function (access) {
return function (target, propertyKey, descriptor) {
if (typeof access === 'string') {
var strAccess = access;
access = {};
Object.defineProperty(access, strAccess, { value: true });
}
Object.defineProperty(access, 'class', { value: target.constructor });
target.addAccessRule(propertyKey, access);
};
};
HTTP.ACL = _a.ACCESS;
HTTP.SHIM = {
ROOT_API_PROXY_REQUEST: '/proxy-request',
ROOT_API_PUBLIC_INFO: '/public-info',
ROOT_API_NEW_CHANNEL: '/secure-channel',
ROOT_API_SECURE_API: '/secure-api',
};
HTTP.STATUS = http_models_1.HttpCode;
return HTTP;
}());
exports.HTTP = HTTP;
;
var HttpServerShim = (function () {
function HttpServerShim(config, globalConf, beforeSuper) {
var _this = this;
this.publicInfo = {};
this.publicInfoString = '';
this.authServers = {};
this.apiPath = 'api';
this.apiVersion = 'v1';
this.apiPathList = [];
this.apiPathIface = {};
this.pathTree = {};
this.defaultProcessors = [];
this.proxyRequest = {
enabled: false,
requestCheckers: [],
};
this.secureChannels = {};
this.workerFleet = {};
this.cacheData = {};
this.state = {
activePort: 0,
closed: false,
started: false,
apiRegistered: false,
apiRegisterStack: null,
closingPromise: null,
};
this.baseLibData = {
express: {
server: null,
},
};
if (beforeSuper) {
beforeSuper();
}
this.configGlobal = (0, config_util_1.completeConfig)(globalConf ? globalConf : {}, defaultGlobalConfig);
this.config = this.normalizeServerConfig(config);
this.preHandler = new PreHandler();
this.postHandler = new PostHandler();
this.configResolutionPromise = this.configResolution();
this.setBaseLayer();
if (!this.config.name) {
this.config.name = 'unnamed-server';
}
if (!this.config.env) {
this.config.env = 'test';
}
process_exit_handler_1.ProcessExit.addHandler(function (e) {
_this.close();
});
}
HttpServerShim.prototype.configResolution = function () {
return __awaiter(this, void 0, void 0, function () {
var destor, _b, _c, channelKey, i;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
if (!!this.config.skipConfigSecretResolution) return [3, 4];
return [4, this.getDestorClient()];
case 1:
destor = _d.sent();
_b = this;
return [4, secret_resolver_1.SecretManager.resolve(this.config, destor)];
case 2:
_b.config = _d.sent();
if (!!this.config.skipAuthServerResolution) return [3, 4];
_c = this;
return [4, secret_resolver_1.SecretManager.resolve('<config.authServers>', destor)];
case 3:
_c.authServers = (_d.sent());
_d.label = 4;
case 4:
if (this.config.security.secureChannel.enabled && this.config.security.secureChannel.signingKey) {
channelKey = this.config.security.secureChannel.signingKey;
if (!this.config.security.secureChannel.publicKey && channelKey && !channelKey.startsWith('<')) {
this.config.security.secureChannel.publicKey = secure_channel_1.SecureHandshake.getPublicKeyFrom(channelKey);
}
for (i = 0; i < this.config.workers.secureChannelWorkers.initialCount; ++i) {
this.addWorker(http_shim_worker_security_1.SecureChannelWorkerClient, {
workerId: i, scopeName: this.config.scopeName, signingKey: channelKey,
});
}
}
this.configResolutionPromise = null;
this.afterConfigResolution();
return [2];
}
});
});
};
HttpServerShim.prototype.registerApis = function () {
if (this.state.apiRegistered) {
throw new Error("Cannot register apis twice; already registered from ".concat(this.state.apiRegisterStack));
}
this.state.apiRegistered = true;
this.state.apiRegisterStack = new Error().stack;
for (var _i = 0, _b = this.apiRegistrations; _i < _b.length; _i++) {
var api = _b[_i];
if (this instanceof api.class) {
this.register(api);
}
}
};
HttpServerShim.prototype.normalizeServerConfig = function (config) {
if (!config.scopeName) {
config.scopeName = "httpshim;pid=".concat(process.pid);
}
var newConfig = (0, config_util_1.completeConfig)(config, defaultConfig);
newConfig.debug.showErrorStack = true;
return newConfig;
};
HttpServerShim.prototype.addDefaultProcessor = function () {
var processors = [];
for (var _i = 0; _i < arguments.length; _i++) {
processors[_i] = arguments[_i];
}
if (this.state.apiRegistered) {
throw new Error("addDefaultProcessor must be called before api registration");
}
for (var _b = 0, processors_1 = processors; _b < processors_1.length; _b++) {
var proc = processors_1[_b];
this.defaultProcessors.push(proc);
}
};
HttpServerShim.prototype.cacheDefine = function (init) {
if (this.cacheData[init.path]) {
throw new Error("Cache path '".concat(init.path, "' is already defined."));
}
var def = new CacheDef(init);
this.cacheData[def.path] = new CacheEntry({
value: null,
hits: 0,
version: 0,
def: def,
});
return def;
};
HttpServerShim.prototype.addWorker = function (workerClass, workerData) {
if (!workerData) {
workerData = {};
}
if (!this.workerFleet[workerClass.name]) {
this.workerFleet[workerClass.name] = { workers: [] };
}
var workersReg = this.workerFleet[workerClass.name];
var worker = new workerClass(workerData);
workersReg.workers.push(worker);
return worker;
};
HttpServerShim.prototype.pickWorker = function (workerClass) {
if (!this.workerFleet[workerClass.name]) {
return dev_null_proxy_1.proxyParameterFunctionToNull;
}
var workers = this.workerFleet[workerClass.name].workers;
if (workers.length === 0) {
return dev_null_proxy_1.proxyParameterFunctionToNull;
}
return this.workerFleet[workerClass.name].workers[0];
};
HttpServerShim.prototype.setBaseLayer = function () {
switch (this.config.type) {
case HttpBaseLib.EXPRESS:
this.baseApp = express.default();
var secOptions_1 = this.configGlobal.http.securityHeaders;
if (secOptions_1.profile === 'allow-all') {
this.baseApp.use(function (req, res, next) {
if (secOptions_1.allowRequestOrigin) {
res.header('Access-Control-Allow-Origin', secOptions_1.allowRequestOrigin);
}
if (secOptions_1.allowRequestHeaders) {
res.header('Access-Control-Allow-Headers', secOptions_1.allowRequestOrigin);
}
if (req.method === 'OPTIONS') {
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
return res.end();
}
next();
});
}
break;
}
};
HttpServerShim.prototype.setFinalLayer = function () {
switch (this.config.type) {
case HttpBaseLib.EXPRESS:
break;
}
};
HttpServerShim.prototype.getDestorClient = function () {
return __awaiter(this, void 0, void 0, function () {
var _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (this.destor) {
return [2, this.destor];
}
if (!this.destorPromise) return [3, 2];
return [4, this.destorPromise];
case 1: return [2, _c.sent()];
case 2:
this.destorPromise = (0, destor_client_1.getDestorClient)();
_b = this;
return [4, this.destorPromise];
case 3:
_b.destor = _c.sent();
return [2];
}
});
});
};
HttpServerShim.prototype.getRoles = function (op) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_b) {
return [2, op.res.returnJsonPreserialized('')];
});
});
};
HttpServerShim.prototype.getServerPublicInfo = function (op) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_b) {
return [2, op.res.returnJsonPreserialized(this.publicInfoString)];
});
});
};
HttpServerShim.prototype.newSecureChannel = function (op) {
return __awaiter(this, void 0, void 0, function () {
var accessInfoResult, accessInfo, peerInfo, channel, secureChannelResponseResult;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
accessInfoResult = this.checkAccessor(op, true);
if (accessInfoResult.bad) {
return [2, op.raise(accessInfoResult, HTTP.STATUS.BAD_REQUEST)];
}
accessInfo = accessInfoResult.data;
peerInfo = {
ecdhPublicKey: Buffer.from(accessInfo.channelPublicKey, 'base64'),
iden: null, data: null,
};
return [4, this.pickWorker(http_shim_worker_security_1.SecureChannelWorkerClient).newChannel(peerInfo)];
case 1:
channel = _b.sent();
channel.signing = {
type: '4Q',
public: this.config.security.secureChannel.publicKey,
private: this.config.security.secureChannel.signingKey,
};
this.secureChannels[channel.peerInfo.ecdhPublicKey.toString('base64')] = channel;
secureChannelResponseResult = channel.getSecureChannelResponse();
if (secureChannelResponseResult.bad) {
return [2, op.raise(secureChannelResponseResult, HTTP.STATUS.UNAUTHORIZED)];
}
return [2, op.res.returnJson(secureChannelResponseResult.data)];
}
});
});
};
HttpServerShim.prototype.encryptedOperation = function (op, skipRunning) {
if (skipRunning === void 0) { skipRunning = false; }
return __awaiter(this, void 0, void 0, function () {
var api;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
api = op.req.decryptedApiTarget;
if (!!skipRunning) return [3, 2];
return [4, this[api.handlerName](op)];
case 1:
_b.sent();
_b.label = 2;
case 2: return [2];
}
});
});
};
HttpServerShim.prototype.proxyRequestOperation = function (op) {
var _b;
return __awaiter(this, void 0, void 0, function () {
var _i, _c, checker, _d, allowed, message, paramsCopy, url, method, timeout, headers, newHeaders, _e, _f, headerName, headerValue, reqOpts, proxyRequestFunction;
return __generator(this, function (_g) {
switch (_g.label) {
case 0:
if (this.proxyRequest.enabled) {
return [2, op.res.returnNotOk(500, "Proxy request not enabled")];
}
if (!((_b = this.proxyRequest.requestCheckers) === null || _b === void 0 ? void 0 : _b.length)) return [3, 4];
_i = 0, _c = this.proxyRequest.requestCheckers;
_g.label = 1;
case 1:
if (!(_i < _c.length)) return [3, 4];
checker = _c[_i];
return [4, checker(op.req.params)];
case 2:
_d = _g.sent(), allowed = _d.allowed, message = _d.message;
if (!allowed) {
return [2, op.res.returnNotOk(500, "Proxy request not allowed: ".concat(message))];
}
_g.label = 3;
case 3:
_i++;
return [3, 1];
case 4:
paramsCopy = JSON.parse(JSON.stringify(op.req.params));
url = paramsCopy.__url;
method = paramsCopy.__method ? paramsCopy.__method : http_models_1.HttpMethod.GET;
timeout = paramsCopy.__timeout ? paramsCopy.__timeout : 7000;
headers = paramsCopy.__headers ? paramsCopy.__headers : '';
if (paramsCopy.__url) {
delete paramsCopy.__url;
}
if (paramsCopy.__method) {
delete paramsCopy.__method;
}
if (paramsCopy.__headers) {
delete paramsCopy.__headers;
}
if (paramsCopy.__timeout) {
delete paramsCopy.__timeout;
}
if (paramsCopy.__enc) {
delete paramsCopy.__enc;
}
newHeaders = {};
for (_e = 0, _f = headers.split(','); _e < _f.length; _e++) {
headerName = _f[_e];
headerValue = op.req.getHeader(headerName);
if (headerValue) {
newHeaders[headerName] = headerValue;
}
}
reqOpts = { timeout: timeout, headers: newHeaders, params: paramsCopy, };
switch (method) {
case 'GET': {
proxyRequestFunction = axios.default.get;
break;
}
case 'PUT': {
proxyRequestFunction = axios.default.put;
break;
}
case 'POST': {
proxyRequestFunction = axios.default.post;
break;
}
case 'PATCH': {
proxyRequestFunction = axios.default.patch;
break;
}
case 'DELETE': {
proxyRequestFunction = axios.default.delete;
break;
}
}
op.waitFor(function (resolve) {
proxyRequestFunction.apply(axios.default, [url, reqOpts]).then(function (res) {
if (typeof res.data === 'string') {
op.res.returnJson({ message: res.data });
}
else {
op.res.returnJson(res.data);
}
resolve();
}).catch(function (e) {
var res = e.response;
if (res) {
op.res.returnNotOk(res.status, "Proxy request failed: ".concat(res.data));
}
else {
op.res.returnNotOk(500, "Proxy request failed: ".concat(e.message));
}
resolve();
});
});
return [2];
}
});
});
};
HttpServerShim.prototype.addAccessRule = function (memberMethodName, access) {
if (!this.apiAccess) {
this.apiAccess = {};
}
var memberMethodName2 = memberMethodName;
if (!this[memberMethodName2]) {
throw new Error("Cannot defined roles for non-existing class method '".concat(memberMethodName2, "'"));
}
this.apiAccess[memberMethodName2] = access;
};
HttpServerShim.prototype.addRegistration = function (api) {
if (!this.apiRegistrations) {
this.apiRegistrations = [];
}
this.apiRegistrations.push(api);
};
HttpServerShim.prototype.register = function (api) {
var _this = this;
var apiVersion = api.apiVersion ? api.apiVersion : this.apiVersion;
var apiPath = api.apiPath ? api.apiPath : this.apiPath;
var finalMountPath = api.rootMount ? '' : "/".concat(apiPath, "/").concat(apiVersion);
var fullpath = "".concat(finalMountPath, "/").concat(api.path).replace(/\/\//g, '/');
api.fullpath = fullpath;
this.pathResolve(fullpath, api);
var apiKey = "".concat(api.method, " ").concat(api.fullpath);
this.apiPathList.push(apiKey);
var iface = this[api.handlerName + '_iface'];
if (iface) {
iface.consumed = 1;
this.apiPathIface[apiKey] = {
method: api.method,
path: api.path,
handlerName: api.handlerName,
description: iface.description ? iface.description : '',
params: Object.keys(iface.params).map(function (paramName) {
var paramInfo = iface.params[paramName];
return {
required: paramInfo.required ? true : false, type: paramInfo.type
};
}),
returns: iface.returns.type,
acl: null,
};
setImmediate(function () {
_this.apiPathIface[apiKey].acl = _this.apiAccess[api.handlerName] ? _this.apiAccess[api.handlerName] : null;
});
}
if (!api.pre) {
api.pre = [];
}
if (!api.preDefaultProcesserAdded) {
api.pre = __spreadArray(__spreadArray([], this.defaultProcessors, true), api.pre, true);
api.pre = api.pre.filter(function (a, i) { return api.pre.indexOf(a) === i; });
api.preDefaultProcesserAdded = true;
}
switch (this.config.type) {
case HttpBaseLib.EXPRESS:
switch (api.method) {
case http_models_1.HttpMethod.GET: return this.baseApp.get(fullpath, expressHandler(this, api));
case http_models_1.HttpMethod.POST: return this.baseApp.post(fullpath, expressHandler(this, api));
case http_models_1.HttpMethod.PUT: return this.baseApp.put(fullpath, expressHandler(this, api));
case http_models_1.HttpMethod.PATCH: return this.baseApp.patch(fullpath, expressHandler(this, api));
case http_models_1.HttpMethod.DELETE: return this.baseApp.delete(fullpath, expressHandler(this, api));
}
break;
}
console.error("unmatched api", api);
};
HttpServerShim.prototype.beforeStart = function () { };
HttpServerShim.prototype.afterStart = function () { };
HttpServerShim.prototype.afterConfigResolution = function () { };
HttpServerShim.prototype.beforeStop = function () { };
HttpServerShim.prototype.afterStop = function () { };
HttpServerShim.prototype.addPublicInfo = function (info) {
Object.assign(this.publicInfo, info);
};
HttpServerShim.prototype.start = function (options) {
var _this = this;
return (0, globals_ix_1.promise)(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
var newAccess, app;
var _this = this;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (this.state.started) {
return [2, resolve()];
}
this.state.started = true;
if (!this.configResolutionPromise) return [3, 2];
return [4, this.configResolutionPromise];
case 1:
_b.sent();
_b.label = 2;
case 2:
if (!options) {
options = this.config.startOptions;
}
if (!options) {
return [2, reject(new Error("Cannot start server without start options."))];
}
this.addPublicInfo({
tokenRequired: this.config.security.token.required,
accessorRequired: this.config.security.accessor.required,
secureChannelScheme: this.config.security.secureChannel.encryption,
secureChannelPublicKey: this.config.security.secureChannel.publicKey,
secureChannelStrict: this.config.security.secureChannel.strict,
secureChannelRequired: this.config.security.secureChannel.required,
apiPathList: this.apiPathList,
apiInterface: this.apiPathIface
});
this.apiRegistrations = this.apiRegistrations.filter(function (api) { return _this instanceof api.class; });
newAccess = {};
Object.keys(this.apiAccess).forEach(function (handlerName) {
if (_this instanceof _this.apiAccess[handlerName]['class']) {
newAccess[handlerName] = _this.apiAccess[handlerName];
}
});
this.apiAccess = newAccess;
this.registerApis();
this.publicInfoString = JSON.stringify(this.publicInfo, null, 4);
switch (this.config.type) {
case HttpBaseLib.EXPRESS:
try {
this.beforeStart();
}
catch (e) {
console.error(e);
}
try {
app = this.baseApp;
this.baseLibData.express.server = app.listen(options.port, function () {
_this.state.activePort = options.port;
resolve();
try {
_this.afterStart();
}
catch (e) {
console.error(e);
}
});
}
catch (e) {
return [2, reject(e)];
}
break;
}
return [2];
}
});
}); });
};
HttpServerShim.prototype.close = function () {
var _this = this;
if (this.state.closingPromise) {
return this.state.closingPromise;
}
this.state.closed = true;
switch (this.config.type) {
case HttpBaseLib.EXPRESS:
this.state.closingPromise = (0, globals_ix_1.promise)(function (resolve) { return __awaiter(_this, void 0, void 0, function () {
var proms;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
proms = [];
try {
this.beforeStop();
}
catch (e) {
console.error(e);
}
try {
this.baseLibData.express.server.close();
}
catch (e) {
console.error(e);
}
try {
proms.push(this.destroyAllWorkers());
}
catch (e) {
console.error(e);
}
try {
this.afterStop();
}
catch (e) {
console.error(e);
}
return [4, globals_ix_1.PromUtil.allSettled(proms)];
case 1:
_b.sent();
resolve();
return [2];
}
});
}); });
break;
}
return this.state.closingPromise;
};
HttpServerShim.prototype.stamp = function (payload, encoding) {
if (encoding === void 0) { encoding = 'ascii'; }
return __awaiter(this, void 0, void 0, function () {
var payloadB64, sig;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!payload) {
payload = secure_channel_1.SecureHandshake.timeAuth();
}
if (typeof payload === 'string') {
payloadB64 = Buffer.from(payload, encoding).toString('base64');
}
else {
payloadB64 = payload.toString('base64');
}
return [4, this.pickWorker(http_shim_worker_security_1.SecureChannelWorkerClient).signMessage(payloadB64)];
case 1:
sig = _b.sent();
return [2, { payload: payloadB64, sig: sig }];
}
});
});
};
HttpServerShim.prototype.prepareEncryptedOperation = function (op) {
if (op.req.decryptedApiTarget) {
return (0, globals_ix_1.ok)(op.req.decryptedApiTarget);
}
var decryptResult = this.getDecryptedPayload(op);
if (decryptResult.bad) {
return op.raise(decryptResult, HTTP.STATUS.UNAUTHORIZED);
}
if (!op.req.decryptedPayloadObject) {
return op.raise(http_models_1.HttpCode.BAD_REQUEST, "ENCRYPTED_OP_NON_JSON_PAYLOAD", "Supplied secure payload is not JSON format");
}
var args = op.req.decryptedPayloadObject;
var resolved = this.pathResolve(args.path);
if (!resolved) {
return op.raise(http_models_1.HttpCode.NOT_FOUND, "ENCRYPTED_OP_PATH_NOT_FOUND", "Encrypted access to unknown path: '".concat(args.path, "'"));
}
var api = resolved.methods[op.method];
if (!api) {
return op.raise(http_models_1.HttpCode.NOT_FOUND, "ENCRYPTED_OP_METHOD_NOT_FOUND", "Method ".concat(op.method, " not found for '").concat(api.fullpath, "'"));
}
if (args.headers) {
Object.assign(op.req.headers, args);
}
op.params = op.req.params;
var pathQueryParams = url.parse(args.path, true).query;
if (Object.keys(resolved.params).length > 0) {
Object.assign(op.req.params, resolved.params);
}
if (Object.keys(pathQueryParams).length > 0) {
Object.assign(op.req.params, pathQueryParams);
}
if (args.body) {
try {
var data = JSON.parse(args.body);
op.req.data = data;
if (data && typeof data === 'object' && !Array.isArray(data)) {
Object.assign(op.req.params, data);
}
}
catch (e) {
}
}
op.req.decryptedApiTarget = api;
return (0, globals_ix_1.ok)(api);
};
HttpServerShim.prototype.checkAccessor = function (op, forceVerify) {
if (forceVerify === void 0) { forceVerify = false; }
var authorizationHeader = op.req.getHeader('Accessor');
var accessorConf = this.config.security.accessor;
if (accessorConf.required || forceVerify) {
if (!authorizationHeader) {
return op.raise(http_models_1.HttpCode.UNAUTHORIZED, "ACCESSOR_HEADER_NOT_FOUND", "Accessor header does not exist");
}
}
else {
return (0, globals_ix_1.ok)({ accessor: null, t: 0, channelPublicKey: '' });
}
var authInfo = secure_channel_1.SecureHandshake.parseAuthHeader(authorizationHeader);
var accessorExpression = authInfo.accessorExpression;
var timeWindow = this.config.security.accessor.timeWindow;
if (!accessorConf.baseTokenBuffer) {
accessorConf.baseTokenBuffer = Buffer.from(accessorConf.baseToken, 'ascii');
}
var accessDataResult = secure_channel_1.SecureHandshake.verifyAccessor(accessorExpression, accessorConf.baseTokenBuffer, timeWindow);
if (accessDataResult.bad) {
return op.raise(accessDataResult, http_models_1.HttpCode.UNAUTHORIZED);
}
return (0, globals_ix_1.ok)(__assign(__assign({}, accessDataResult.data), { channelPublicKey: authInfo.peerEcdhPublicKey }));
};
HttpServerShim.prototype.getSecureChannel = function (op) {
var accessInfoResult = this.checkAccessor(op, true);
if (accessInfoResult.bad) {
return op.raise(accessInfoResult, HTTP.STATUS.BAD_REQUEST);
}
var channelId = accessInfoResult.data.channelPublicKey;
var channel = this.secureChannels[channelId];
if (!channel) {
return op.raise(http_models_1.HttpCode.UNAUTHORIZED, "SECURE_CHANNEL_NOT_FOUND", "secure channel not found: ".concat(channelId));
}
op.secureChannel = channel;
return (0, globals_ix_1.ok)(channel);
};
HttpServerShim.prototype.getDecryptedPayload = function (op) {
if (op.req.decryptedPayload) {
return (0, globals_ix_1.ok)(op.req.decryptedPayload);
}
var channelResult = this.getSecureChannel(op);
if (channelResult.bad) {
return op.raise(channelResult, HTTP.STATUS.UNAUTHORIZED);
}
var channel = channelResult.data;
var payload = channel.parseWrappedPayloadBase64(op.req.encryptedPayload);
if (!payload || !payload.__scp) {
return op.raise(http_models_1.HttpCode.BAD_REQUEST, 'ENCRYPTED_OP_NO_SECURE_PAYLOAD', 'Secure payload not found');
}
op.req.decryptedPayload = channel.decryptSecureChannelPayloadIntoString(payload);
if (isJsonString(op.req.decryptedPayload)) {
op.req.decryptedPayloadObject = JSON.parse(op.req.decryptedPayload);
}
return (0, globals_ix_1.ok)(op.req.decryptedPayload);
};
HttpServerShim.prototype.handlePre = function (op) {
var _this = this;
return (0, globals_ix_1.promise)(function (resolve) { return __awaiter(_this, void 0, void 0, function () {
var allPassed, _i, _b, preType, preFunc, passed;
var _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
allPassed = true;
if (!(((_c = op.api.pre) === null || _c === void 0 ? void 0 : _c.length) > 0)) return [3, 4];
_i = 0, _b = op.api.pre;
_d.label = 1;
case 1:
if (!(_i < _b.length)) return [3, 4];
preType = _b[_i];
preFunc = this.preHandler.byType[preType];
if (!preFunc) {
return [3, 3];
}
return [4, preFunc.apply(this.preHandler, [op])];
case 2:
passed = _d.sent();
if (!passed) {
allPassed = false;
return [3, 4];
}
_d.label = 3;
case 3:
_i++;
return [3, 1];
case 4:
resolve(allPassed);
return [2];
}
});
}); });
};
HttpServerShim.prototype.handlePost = function (op) {
var _this = this;
return (0, globals_ix_1.promise)(function (resolve) { return __awaiter(_this, void 0, void 0, function () {
var allPassed, _i, _b, postType, postFunc, passed;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
allPassed = true;
if (!op.api.post) return [3, 4];
_i = 0, _b = op.api.post;
_c.label = 1;
case 1:
if (!(_i < _b.length)) return [3, 4];
postType = _b[_i];
postFunc = this.postHandler.byType[postType];
if (!postFunc) {
return [3, 3];
}
return [4, postFunc.apply(this.postHandler, [op])];
case 2:
passed = _c.sent();
if (!passed) {
allPassed = false;
return [3, 4];
}
_c.label = 3;
case 3:
_i++;
return [3, 1];
case 4:
resolve(allPassed);
return [2];
}
});
}); });
};
HttpServerShim.prototype.pathResolve = function (path, newApi) {
if (newApi === void 0) { newApi = null; }
var paths = path.split('/');
if (paths[0] === '') {
paths.shift();
}
var paramCollector = {};
var node = this.pathTree;
for (var _i = 0, paths_1 = paths; _i < paths_1.length; _i++) {
var pathSlot = paths_1[_i];
var slot = decodeURIComponent(pathSlot.split('?')[0].split('#')[0]);
if (slot === '__apidef__') {
return null;
}
var isParam = slot.startsWith(':');
if (node[slot]) {
node = node[slot];
continue;
}
var paramDef = node['?param-name?'];
if (paramDef) {
if (newApi && isParam && paramDef.slot !== slot) {
throw new Error("Cannot register a parameter slot ".concat(slot, ", ") +
"parameter ".concat(paramDef.slot, " has been registered by ").concat(paramDef.registeredPath));
}
paramCollector[paramDef.name] = slot;
node = paramDef.nextNode;
continue;
}
if (newApi) {
var nextNode = {};