will-core
Version:
core module
347 lines (346 loc) • 15.1 kB
JavaScript
"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;