UNPKG

will-core

Version:
347 lines (346 loc) 15.1 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseHandler = void 0; const os_1 = __importDefault(require("os")); const will_db_1 = require("will-db"); const will_sql_1 = require("will-sql"); const will_lib_1 = require("will-lib"); const will_dh_1 = require("will-dh"); const will_util_1 = require("will-util"); const will_api_1 = require("will-api"); const Accessor_1 = require("../models/Accessor"); const VerifyError_1 = require("../models/VerifyError"); const AssureAlias_1 = require("../models/AssureAlias"); const EnvironmentVariable_1 = require("../utils/EnvironmentVariable"); class BaseHandler extends will_db_1.KnHandler { constructor(model, settings, accessor) { super(model, settings); this.section = EnvironmentVariable_1.DB_SECTION; this.accessor = accessor; } async getAccessor(conn, useruuid) { if (useruuid && useruuid.trim().length > 0) { let sql = new will_sql_1.KnSQL("select tusertoken.useruuid,tusertoken.userid,tusertoken.authtoken,tuserinfo.* "); sql.append("from tusertoken "); sql.append("left join tuserinfo on tuserinfo.userid = tusertoken.userid "); sql.append("where tusertoken.useruuid = ?useruuid "); sql.set("useruuid", useruuid); this.logger.info(this.constructor.name + ".getAccessor", sql); let rs = await sql.executeQuery(conn); if (rs && rs.rows.length > 0) { let row = rs.rows[0]; let info = { ...row }; delete info.useruuid; delete info.userid; delete info.authtoken; return Promise.resolve(new Accessor_1.Accessor(row.useruuid, row.userid, row.authtoken, info)); } } return Promise.resolve(undefined); } async retainAccessor(conn, useruuid) { try { this.accessor = await this.getAccessor(conn, useruuid); } catch (ex) { this.logger.error(this.constructor.name, ex); } } getHeaderParameter(context, parameterName) { let result = undefined; if (context) { if (context.meta.headers) { result = context.meta.headers[parameterName]; } if (context.params && context.params.req) { result = context.params.req.headers[parameterName]; } if (context.options && context.options.parentCtx && context.options.parentCtx.params && context.options.parentCtx.params.req) { result = context.options.parentCtx.params.req.headers[parameterName]; } } return result; } isInPageSetting(key, model) { let result = AssureAlias_1.RESERVED_FIELDS.includes(key); return result ? result : super.isInPageSetting(key, model); } getCurrentUser() { return os_1.default.userInfo().username; } getAuthorizationInfo(context) { if (context) { if (context.meta.headers && context.meta.headers.authorization) { return { authorization: context.meta.headers.authorization, client: context.meta.headers.client }; } if (context.params && context.params.req && context.params.req.headers && context.params.req.headers.authorization) { return { authorization: context.params.req.headers.authorization, client: context.params.req.headers.client }; } if (context.options && context.options.parentCtx && context.options.parentCtx.params && context.options.parentCtx.params.req && context.options.parentCtx.params.req.headers && context.options.parentCtx.params.req.headers.authorization) { return { authorization: context.options.parentCtx.params.req.headers.authorization, client: context.options.parentCtx.params.req.headers.client }; } } return undefined; } getTokenKey(context) { let token = undefined; if (context) { if (context.meta.headers) { token = context.meta.headers.authtoken || context.meta.headers.tokenkey; if (token) return token; } if (context.params && context.params.req) { token = context.params.req.headers.authtoken || context.params.req.headers.tokenkey; if (token) return token; } if (context.options && context.options.parentCtx && context.options.parentCtx.params && context.options.parentCtx.params.req) { token = context.options.parentCtx.params.req.headers.authtoken || context.options.parentCtx.params.req.headers.tokenkey; if (token) return token; } if (context.params && context.params.authtoken) { token = context.params.authtoken || context.params.tokenkey; if (token) return token; } } return token; } async getUserTokenInfo(context, onlyMeta = false, db) { if (context && context.meta) { if (context.meta.user && context.meta.user.tokenstatus == "C") { return Promise.resolve(context.meta.user); } if (context.meta.session && context.meta.session.user && context.meta.session.user.tokenstatus == "C") { return Promise.resolve(context.meta.session.user); } } let result = undefined; if (!onlyMeta) { result = await this.getUserTokenInfoByToken(context, db); if (result) { context.meta.user = result; context.meta.session.user = result; } } if (!result) { let token = await this.getAuthenToken(context, false, false); if (token) { result = { useruuid: token.identifier, userid: token.accessor, site: token.site }; } } return Promise.resolve(result); } async getUserTokenInfoByToken(context, db) { let token = this.getTokenKey(context); if (token && token != "") { let plib = new will_lib_1.PasswordLibrary(); if (db) { return await plib.getUserTokenInfoByToken(db, token); } let dbc = null; try { dbc = this.getConnector(this.section); return await plib.getUserTokenInfoByToken(dbc, token); } finally { if (dbc) dbc.close(); } } return Promise.resolve(undefined); } async getUserDiffie(userInfo, verifyHandShaked = false, uncheckTokenStatus = false) { if (userInfo && userInfo.prime && userInfo.generator && userInfo.publickey && userInfo.privatekey && userInfo.sharedkey && userInfo.otherkey) { let valid = userInfo.tokenstatus == "C"; if (uncheckTokenStatus) valid = true; if (valid) { let dh = new will_dh_1.DH(); dh.prime = userInfo.prime; dh.generator = userInfo.generator; dh.privateKey = userInfo.privatekey; dh.publicKey = userInfo.publickey; dh.sharedKey = userInfo.sharedkey; dh.otherPublicKey = userInfo.otherkey; return Promise.resolve(dh); } if (verifyHandShaked && (userInfo.tokenstatus === null || userInfo.tokenstatus === undefined)) { return Promise.reject(new VerifyError_1.VerifyError("Token does not handshaked", will_api_1.HTTP.NOT_ALLOWED, -16008)); } } return Promise.resolve(undefined); } async getUserDH(context, verifyHandShaked = false, uncheckTokenStatus = false) { let token = await this.getUserTokenInfo(context); let dh = await this.getUserDiffie(token, verifyHandShaked, uncheckTokenStatus); return Promise.resolve(dh); } async getAuthenToken(context, verifyTokenKey = true, verifyIdentifier = true) { let token = this.getTokenKey(context); return await this.verifyAuthenToken(token, verifyTokenKey, verifyIdentifier); } async verifyAuthenToken(token, verifyTokenKey = true, verifyIdentifier = true) { if (token != undefined) { const atoken = will_lib_1.AuthenToken.verifyAuthenToken(token, false); if (verifyIdentifier && (atoken.identifier == undefined)) { return Promise.reject(new VerifyError_1.VerifyError("Token is invalid", will_api_1.HTTP.UNAUTHORIZED, -16001)); } return Promise.resolve(atoken); } if (verifyTokenKey) { return Promise.reject(new VerifyError_1.VerifyError("Token undefined", will_api_1.HTTP.UNAUTHORIZED, -16002)); } return Promise.resolve(undefined); } async exposeContext(context, includeChiperData = true) { if (this.isCipherData(context)) { let dh = await this.getUserDH(context); if (dh) { let ciphertext = context.params.ciphertext; this.logger.debug(this.constructor.name + ".exposeContext: ciphertext", ciphertext); if (ciphertext && ciphertext != "") { let jsonstr = dh.decrypt(ciphertext); this.logger.debug(this.constructor.name + ".exposeContext", jsonstr); if (jsonstr && jsonstr != "") { let json = JSON.parse(jsonstr); if (!includeChiperData) { delete context.params.ciphertext; } context.params = { ...context.params, ...json }; } } } } return Promise.resolve(context); } isCipherData(context) { let result = this.getHeaderParameter(context, "data-type"); return result == "json/cipher"; } isCipherText(context) { let result = this.getHeaderParameter(context, "data-type"); return result == "text/cipher"; } isCipherDataAccept(context) { let result = this.getHeaderParameter(context, "accept-type"); return result == "json/cipher"; } isCipherTextAccept(context) { let result = this.getHeaderParameter(context, "accept-type"); return result == "text/cipher"; } /** * try to encrypt data if found user DH * @param context * @param data * @returns cipher string */ async encryptData(context, data, verifyHandShaked = false) { if (data) { let dh = await this.getUserDH(context, verifyHandShaked); if (dh) { return Promise.resolve(dh.encrypt(JSON.stringify(data))); } } return Promise.resolve(data); } /** * try to encrypt data when header accept-type is json/cipher * @param context * @param data * @returns json format { data: ? } */ async cipherData(context, data, verifyHandShaked = false) { if (data && this.isCipherDataAccept(context)) { let dh = await this.getUserDH(context, verifyHandShaked); if (dh) { return Promise.resolve({ data: dh.encrypt(JSON.stringify(data)) }); } } return Promise.resolve(data); } /** * try to encrypt data when header accept-type is text/cipher * @param context * @param data * @returns cipher string */ async cipherText(context, data, verifyHandShaked = false) { if (data && this.isCipherTextAccept(context)) { let dh = await this.getUserDH(context, verifyHandShaked); if (dh) { return Promise.resolve(dh.encrypt(JSON.stringify(data))); } } return Promise.resolve(data); } createJSONReply(method, data, model) { let reply = new will_api_1.JSONReply(); reply.head.modeling(model ? model : this.constructor.name, method); reply.head.composeNoError(); reply.body = data; return reply; } async createCipherData(context, method, data, verifyHandShaked = true, model) { if (this.isCipherDataAccept(context)) { return this.cipherData(context, data, verifyHandShaked); } else if (this.isCipherTextAccept(context)) { let result = await this.cipherText(context, this.createJSONReply(method, data, model), verifyHandShaked); if (will_util_1.Utilities.isString(result)) { context.meta.$responseRaw = true; if (!context.meta.$responseType) { context.meta.$responseType = "text/plain"; } } return result; } return Promise.resolve(data); } async validateAuthenToken(context) { if (!EnvironmentVariable_1.VALIDATE_TOKEN) return Promise.resolve(undefined); let authtoken = await this.getAuthenToken(context, true, true); return Promise.resolve(authtoken); } validateParameters(params, ...args) { if (args && args.length > 0) { for (let i = 0, isz = args.length; i < isz; i++) { let name = args[i]; let value = params[name]; if (value == undefined || value == null || value == "") { return { valid: false, info: name }; } } } return { valid: true }; } recordNotFound() { return Promise.reject(new VerifyError_1.VerifyError("Record not found", will_api_1.HTTP.NOT_FOUND, -16004)); } notImplementation() { return Promise.reject(new VerifyError_1.VerifyError("Not implemented", will_api_1.HTTP.NOT_IMPLEMENTED, -16005)); } createRecordSet(result = { rows: [], columns: null }) { let records = 0; if (result.rows) { if (Array.isArray(result.rows)) { records = result.rows.length; } else { if (result.rows.affectedRows) { records = result.rows.affectedRows; } } } return { records: records, rows: result.rows, columns: null, offsets: result.offsets }; } } exports.BaseHandler = BaseHandler;