will-core
Version:
core module
662 lines (661 loc) • 34.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SigninHandler = void 0;
const uuid_1 = require("uuid");
const will_lib_1 = require("will-lib");
const will_api_1 = require("will-api");
const will_sql_1 = require("will-sql");
const will_util_1 = require("will-util");
const will_lib_2 = require("will-lib");
const EnvironmentVariable_1 = require("../utils/EnvironmentVariable");
const UserToken_1 = require("../models/UserToken");
const VerifyError_1 = require("../models/VerifyError");
const Responser_1 = require("../utils/Responser");
const DiffieHandler_1 = require("./DiffieHandler");
const SchemeHandler_1 = require("./SchemeHandler");
const TwoFactorHandler_1 = require("./TwoFactorHandler");
const bcrypt = require('bcrypt');
class SigninHandler extends SchemeHandler_1.SchemeHandler {
constructor() {
super(...arguments);
this.model = { name: "tuser", alias: { privateAlias: this.section } };
//declared addon actions name
this.handlers = [{ name: "signin" }, { name: "accesstoken" }, { name: "fetchtoken" }, { name: "validatetoken" }, { name: "signout" }, { name: "account" }];
}
getSigninInfo(context) {
return { username: context.params.username, password: context.params.password, site: context.params.site };
}
async signin(context) {
return this.callFunctional(context, { operate: "signin", raw: false }, this.doSignin);
}
async doSignin(context, model) {
let signinfo = this.getSigninInfo(context);
this.logger.debug(this.constructor.name + ".doSignin : username=" + signinfo.username);
let db = this.getPrivateConnector(model);
try {
let authinfo = this.getAuthorizationInfo(context);
this.logger.debug(this.constructor.name + ".doSignin: auth info", authinfo);
if (authinfo && authinfo.authorization.trim().length > 0) {
//if authen by basic, then decrypt
let blib = new will_lib_1.BasicLibrary();
let basicinfo = await blib.decrypt(authinfo.authorization, authinfo.client, db);
if (basicinfo) {
this.logger.debug(this.constructor.name + ".doSignin: basic info: username=" + basicinfo.username);
signinfo = { ...signinfo, ...basicinfo };
}
this.logger.debug(this.constructor.name + ".doSignin: sign info: username=" + signinfo.username);
}
if ((!signinfo.username || signinfo.username.trim().length == 0) || (!signinfo.password || signinfo.password.trim().length == 0)) {
return Promise.reject(new VerifyError_1.VerifyError("Invalid user or password", will_api_1.HTTP.BAD_REQUEST, -16081));
}
if (EnvironmentVariable_1.AUTHEN_BY_VERIFY_DOMAIN) {
return await this.doSigninByDomain(context, model, signinfo, db);
}
else {
return await this.doSigninByConfigure(context, model, signinfo, db);
}
}
catch (ex) {
this.logger.error(this.constructor.name, ex);
return Promise.reject(this.getDBError(ex));
}
finally {
if (db)
db.close();
}
}
async doSigninByDomain(context, model, signinfo, db) {
try {
let loginfo = await this.loginWow(signinfo.username, signinfo.password);
let account = will_lib_2.ActiveAuthen.getAccountDomain(signinfo.username);
let adconfig = await will_lib_2.ActiveLibrary.getActiveConfig(db, account.domainName);
this.logger.debug(this.constructor.name + ".doSigninByDomain: ad config = " + (adconfig ? adconfig.hasConfigure() : false));
if (adconfig && adconfig.hasConfigure()) {
return await this.processSigninActiveDirectory(context, model, signinfo, db, adconfig, loginfo);
}
else {
return await this.processSigninInternalSystem(context, model, signinfo, db, loginfo);
}
}
catch (ex) {
this.logger.error(this.constructor.name, ex);
return Promise.reject(ex);
}
}
async doSigninByConfigure(context, model, signinfo, db) {
let loginfo = undefined;
let errmsg = undefined;
let authlist = will_util_1.Configure.getConfig("authentications");
if (authlist && authlist.length > 0) {
for (let i = 0, isz = authlist.length; i < isz; i++) {
let aut = authlist[i];
if (aut.enabled) {
if ("SYSTEM" == aut.authtype) {
let response = await this.processSigninInternalSystem(context, model, signinfo, db, loginfo);
if (response.head.errorflag == "N") {
return Promise.resolve(response);
}
else {
errmsg = response.head.errordesc;
}
}
else if ("AD" == aut.authtype) {
let adconfig = will_lib_2.ActiveLibrary.createConfigure(aut);
this.logger.debug(this.constructor.name + ".doSigninByConfigure: ad config = " + (adconfig ? adconfig.hasConfigure() : false));
if (adconfig && adconfig.hasConfigure()) {
let response = await this.processSigninActiveDirectory(context, model, signinfo, db, adconfig, loginfo);
if (response.head.errorflag == "N") {
return Promise.resolve(response);
}
else {
errmsg = response.head.errordesc;
}
}
}
else {
let response = await this.processSigninPromptSystem(context, model, signinfo, db, loginfo);
if (response.head.errorflag == "N") {
return Promise.resolve(response);
}
else {
errmsg = response.head.errordesc;
}
}
}
}
}
return Promise.reject(new will_lib_1.AuthenError(errmsg ? errmsg : "Authentication fail", will_api_1.HTTP.UNAUTHORIZED));
}
async processTwoFactor(context, db, row) {
let handler = new TwoFactorHandler_1.TwoFactorHandler();
let factorInfo = await handler.getFactorInfo(db, row.userid, true);
if (factorInfo.factorverify && !factorInfo.factorfound && factorInfo.factorid.trim().length == 0) {
factorInfo.userid = row.userid;
factorInfo.email = row.email;
factorInfo = await handler.performCreateFactor(context, db, factorInfo);
}
return factorInfo;
}
async processSigninInternalSystem(context, model, signinfo, db, loginfo) {
let pname = signinfo.username;
let ppass = signinfo.password;
let pcode = context.params.code;
let pstate = context.params.state;
let pnonce = context.params.nonce;
let response = new will_api_1.JSONReply();
response.head.modeling("signin", "signin");
response.head.composeNoError();
let body = new Map();
let sql = new will_sql_1.KnSQL("select tuser.userid,tuser.username,tuser.userpassword,tuser.passwordexpiredate,tuser.site,");
sql.append("tuser.accessdate,tuser.accesstime,tuser.changeflag,tuser.newflag,tuser.loginfailtimes,tuser.failtime,tuser.lockflag,");
sql.append("tuserinfo.userename,tuserinfo.useresurname,tuserinfo.email,tuserinfo.displayname,tuserinfo.activeflag,tuserinfo.langcode,tuserinfo.usercontents ");
sql.append("from tuser,tuserinfo ");
sql.append("where tuser.username = ?username ");
sql.append("and tuser.userid = tuserinfo.userid ");
sql.set("username", pname);
this.logger.info(this.constructor.name + ".processSigninInternalSystem", sql);
let rs = await sql.executeQuery(db, context);
let rows = rs.rows;
this.logger.debug(this.constructor.name + ".processSigninInternalSystem: effected " + rows.length + " rows.");
let passed = true;
if (rows && rows.length > 0) {
let row = rows[0];
let userid = row.userid;
let site = row.site;
this.logger.debug(this.constructor.name + ".processSigninInternalSystem: MAX_FAILURE=" + EnvironmentVariable_1.MAX_FAILURE + ", loginfailtimes=" + row.loginfailtimes);
let failtimes = row.loginfailtimes;
if (failtimes >= EnvironmentVariable_1.MAX_FAILURE) {
let now = new Date();
let failtime = row.failtime;
let difftime = now.getTime() - failtime;
this.logger.debug(this.constructor.name + ".processSigninInternalSystem: MAX_WAITTIME=" + EnvironmentVariable_1.MAX_WAITTIME + ", failtime=" + failtime + ", difftime=" + difftime);
if (difftime <= EnvironmentVariable_1.MAX_WAITTIME) {
passed = false;
response.head.composeError("-5012", "Signin failure over " + EnvironmentVariable_1.MAX_FAILURE + " times. Please contact administrator or wait and retry again after 3 minute");
}
}
if (passed) {
let ismatch = false;
let tempmatch = false;
let usrpass = row.userpassword;
let plib = new will_lib_2.PasswordLibrary();
let tmppwd = await plib.getUserTemporaryPassword(db, userid);
if (tmppwd && tmppwd.trxid) {
tempmatch = bcrypt.compareSync(ppass, tmppwd.userpassword);
ismatch = tempmatch;
}
if (!ismatch) {
ismatch = bcrypt.compareSync(ppass, usrpass);
}
this.logger.debug(this.constructor.name + ".processSigninInternalSystem: temporary match=" + tempmatch + ", is match=" + ismatch);
if (!ismatch) {
passed = false;
response.head.composeError("-3002", "Invalid user or password");
}
else {
try {
let factorInfo = await this.processTwoFactor(context, db, row);
await db.beginWork();
try {
if (tempmatch) {
await plib.updatePasswordFromTemporary(db, tmppwd.trxid, userid);
}
let usrinfo = { userid: userid, site: site, code: pcode, state: pstate, nonce: pnonce, loginfo: loginfo };
let token = await this.createUserAccess(db, usrinfo, context);
let dhinfo = await this.createDiffie(context, db, token);
this.composeResponseBody(body, token, pname, { ...row, ...factorInfo, accesscontents: loginfo }, tempmatch, dhinfo);
await db.commitWork();
}
catch (er) {
this.logger.error(this.constructor.name, er);
db.rollbackWork();
this.logger.debug(this.constructor.name + ".processSigninInternalSystem: roll back work");
response = Responser_1.Responser.createDbError("ensure", "signin", er);
}
}
catch (ex) {
this.logger.error(this.constructor.name, ex);
response = Responser_1.Responser.createDbError("ensure", "signin", ex);
}
}
}
}
else {
passed = false;
response.head.composeError("-3003", "Invalid user or password");
}
try {
if (passed) {
this.updateUserAccessing(context, model, { userid: body.get("userid"), username: pname, lockflag: "0" });
}
else {
this.updateUserAccessing(context, model, { username: pname, lockflag: "1" });
}
}
catch (ex) {
this.logger.error(this.constructor.name, ex);
}
response.body = Object.fromEntries(body);
return Promise.resolve(response);
}
async processSigninActiveDirectory(context, model, signinfo, db, config, loginfo) {
let pname = signinfo.username;
let ppass = signinfo.password;
let pcode = context.params.code;
let pstate = context.params.state;
let pnonce = context.params.nonce;
let response = new will_api_1.JSONReply();
response.head.modeling("signin", "signin");
response.head.composeNoError();
let body = new Map();
let alib = new will_lib_2.ActiveLibrary();
try {
let au = await alib.authenticate(pname, ppass, config, db);
try {
let row = { accessdate: new Date(), accesstime: will_util_1.Utilities.currentTime(), userid: au.accountName, userename: au.firstName, useresurname: au.lastName, email: au.principalName, displayname: au.displayName, activeflag: "1", usercontents: null, changeflag: "0", site: undefined };
let sql = new will_sql_1.KnSQL("select site,accessdate,accesstime,userid,userename,useresurname,email,displayname,activeflag,usercontents,'0' as changeflag,'0' as newflag ");
sql.append("from tuserinfo where userid = ?userid ");
sql.set("userid", au.accountName);
let rs = await sql.executeQuery(db);
if (rs.rows && rs.rows.length > 0) {
row = rs.rows[0];
}
let factorInfo = await this.processTwoFactor(context, db, row);
await db.beginWork();
try {
await alib.saveUserInfo(db, au);
let usrinfo = { userid: au.accountName, site: row.site, code: pcode, state: pstate, nonce: pnonce, loginfo: loginfo };
let token = await this.createUserAccess(db, usrinfo, context);
let dhinfo = await this.createDiffie(context, db, token);
this.composeResponseBody(body, token, pname, { ...row, ...factorInfo, accesscontents: loginfo }, false, dhinfo);
await db.commitWork();
this.updateUserAccessing(context, model, { userid: au.accountName });
}
catch (er) {
this.logger.error(this.constructor.name, er);
db.rollbackWork();
this.logger.debug(this.constructor.name + ".processSigninActiveDirectory: roll back work");
response = Responser_1.Responser.createError("ensure", "signin", er);
}
}
catch (ex) {
this.logger.error(this.constructor.name, ex);
response = Responser_1.Responser.createError("ensure", "signin", ex);
}
response.body = Object.fromEntries(body);
}
catch (ex) {
this.logger.error(this.constructor.name, ex);
response = Responser_1.Responser.createError("ensure", "signin", ex);
}
return Promise.resolve(response);
}
async processSigninPromptSystem(context, model, signinfo, db, config, loginfo) {
let pname = signinfo.username;
let ppass = signinfo.password;
let pcode = context.params.code;
let pstate = context.params.state;
let pnonce = context.params.nonce;
let response = new will_api_1.JSONReply();
response.head.modeling("signin", "signin");
response.head.composeNoError();
let body = new Map();
let alib = new will_lib_2.AuthenLibrary();
try {
let pu = await alib.authenticate(pname, ppass, config, db);
try {
let row = { accessdate: new Date(), accesstime: will_util_1.Utilities.currentTime(), userid: pu.userid, userename: pu.username, useresurname: pu.usersurname, email: pu.email, displayname: pu.displayname, activeflag: "1", usercontents: null, changeflag: "0", site: undefined };
let sql = new will_sql_1.KnSQL("select site,accessdate,accesstime,userid,userename,useresurname,email,displayname,activeflag,usercontents,'0' as changeflag,'0' as newflag ");
sql.append("from tuserinfo where userid = ?userid ");
sql.set("userid", pu.userid);
this.logger.info(this.constructor.name + ".processSigninPromptSystem", sql);
let rs = await sql.executeQuery(db);
if (rs.rows && rs.rows.length > 0) {
row = rs.rows[0];
}
let factorInfo = await this.processTwoFactor(context, db, row);
await db.beginWork();
try {
await alib.saveUserInfo(db, pu);
let usrinfo = { userid: pu.userid, site: row.site, code: pcode, state: pstate, nonce: pnonce, loginfo: pu };
let token = await this.createUserAccess(db, usrinfo, context);
let dhinfo = await this.createDiffie(context, db, token);
this.composeResponseBody(body, token, pname, { ...row, ...factorInfo, accesscontents: pu }, false, dhinfo);
await db.commitWork();
this.updateUserAccessing(context, model, { userid: pu.userid });
}
catch (er) {
this.logger.error(this.constructor.name, er);
db.rollbackWork();
this.logger.debug(this.constructor.name + ".processSigninPromptSystem: roll back work");
response = Responser_1.Responser.createError("ensure", "signin", er);
}
}
catch (ex) {
this.logger.error(this.constructor.name, ex);
response = Responser_1.Responser.createError("ensure", "signin", ex);
}
response.body = Object.fromEntries(body);
}
catch (ex) {
this.logger.error(this.constructor.name, ex);
response = Responser_1.Responser.createError("ensure", "signin", ex);
}
return Promise.resolve(response);
}
composeResponseBody(body, token, username, row, tempmatch = false, dhinfo) {
let expdate = new Date(token.expiretimes);
let expireflag = "0";
if (row.passwordexpiredate) {
let expired = will_util_1.Utilities.compareDate(row.passwordexpiredate, will_util_1.Utilities.now());
if (expired < 0) {
expireflag = "1";
}
}
body.set("useruuid", token.useruuid);
body.set("expiretimes", token.expiretimes);
body.set("expireddate", will_util_1.Utilities.currentDate(expdate) + " " + will_util_1.Utilities.currentTime(expdate));
body.set("code", token.code);
body.set("state", token.state);
body.set("nonce", token.nonce);
body.set("authtoken", token.authtoken);
body.set("username", username);
body.set("userid", row.userid);
body.set("name", row.userename);
body.set("surname", row.useresurname);
body.set("displayname", row.displayname);
body.set("email", row.email);
body.set("site", row.site);
body.set("accessdate", will_util_1.Utilities.getDMY(row.accessdate));
body.set("accesstime", will_util_1.Utilities.getHMS(row.accesstime));
body.set("activeflag", row.activeflag);
body.set("changeflag", row.changeflag);
body.set("expireflag", expireflag);
body.set("newflag", row.newflag);
body.set("langcode", row.langcode);
body.set("factorverify", row?.factorverify);
body.set("factorflag", row?.factorflag);
body.set("factorid", row?.factorid);
body.set("factorcode", row?.factorcode);
body.set("usercontents", row.usercontents);
let accessinfo = row.accesscontents;
if (will_util_1.Utilities.isString(row.accesscontents) && row.accesscontents.trim().length > 0) {
accessinfo = JSON.parse(row.accesscontents);
}
body.set("accesscontents", accessinfo);
if (tempmatch)
body.set("changeflag", "1");
if (dhinfo)
body.set("info", dhinfo);
}
async createUserAccess(db, usrinfo, context) {
let useruuid = (0, uuid_1.v4)();
let authdata = { identifier: useruuid, site: usrinfo.site, accessor: usrinfo.userid };
let authtoken = will_lib_2.AuthenToken.createAuthenToken(authdata);
return this.createUserToken(db, usrinfo, useruuid, authtoken, "S", EnvironmentVariable_1.EXPIRE_TIMES, context);
}
async createUserToken(db, usrinfo, useruuid, authtoken, tokentype = "S", expireins = EnvironmentVariable_1.EXPIRE_TIMES, context) {
let now = new Date();
let expiretimes = now.getTime() + expireins;
let expdate = new Date(expiretimes);
let code = usrinfo.code ? usrinfo.code : (0, uuid_1.v4)();
let state = usrinfo.state ? usrinfo.state : (0, uuid_1.v4)();
let nonce = usrinfo.nonce ? usrinfo.nonce : (0, uuid_1.v4)();
let accesscontents = usrinfo.loginfo ? JSON.stringify(usrinfo.loginfo) : null;
let sql = new will_sql_1.KnSQL("insert into tusertoken(useruuid,userid,createdate,createtime,createmillis,");
sql.append("expiredate,expiretime,expiretimes,site,code,state,nonce,authtoken,tokentype,accesscontents) ");
sql.append("values(?useruuid,?userid,?createdate,?createtime,?createmillis,");
sql.append("?expiredate,?expiretime,?expiretimes,?site,?code,?state,?nonce,?authtoken,?tokentype,?accesscontents) ");
sql.set("useruuid", useruuid);
sql.set("userid", usrinfo.userid);
sql.set("createdate", now, "DATE");
sql.set("createtime", now, "TIME");
sql.set("createmillis", now.getTime());
sql.set("expiredate", expdate, "DATE");
sql.set("expiretime", expdate, "TIME");
sql.set("expiretimes", expiretimes);
sql.set("site", usrinfo.site);
sql.set("code", code);
sql.set("state", state);
sql.set("nonce", nonce);
sql.set("authtoken", authtoken);
sql.set("tokentype", tokentype);
sql.set("accesscontents", accesscontents);
let rs = await sql.executeQuery(db, context);
this.logger.debug(this.constructor.name + ".createUserToken: affected " + rs.rows.affectedRows + " rows.");
return Promise.resolve(new UserToken_1.UserToken(useruuid, expiretimes, code, state, nonce, authtoken));
}
async createDiffie(context, db, token) {
let handler = new DiffieHandler_1.DiffieHandler();
let dh = await handler.createDiffie(context);
console.log(this.constructor.name + ".createDiffie", dh);
await handler.saveDiffie(db, { useruuid: token.useruuid }, dh, context);
let info = handler.createDiffieInfo(dh);
return Promise.resolve(info);
}
async updateUserAccessing(context, model, info) {
let db = this.getPrivateConnector(model);
try {
if (info.userid) {
await this.updateUserAccess(db, info.userid, context);
}
if (info.username) {
await this.updateUserLock(db, info.username, info.lockflag, context);
}
}
catch (ex) {
this.logger.error(this.constructor.name, ex);
}
finally {
if (db)
db.close();
}
}
async updateUserAccess(db, userid, context) {
let now = new Date();
let sql = new will_sql_1.KnSQL("update tuser set accessdate=?accessdate, accesstime=?accesstime, ");
sql.append("accesshits = accesshits + ?accesshits, mistakens = 0, mistakentime = 0 ");
sql.append("where userid=?userid ");
sql.set("accessdate", now, "DATE");
sql.set("accesstime", now, "TIME");
sql.set("accesshits", 1);
sql.set("userid", userid);
this.logger.info(this.constructor.name + ".updateUserAccess", sql);
let rs = await sql.executeUpdate(db, context);
this.logger.debug(this.constructor.name + ".updateUserAccess: affected " + rs.rows.affectedRows + " rows.");
sql.clear();
sql.append("update tuserinfo set accessdate=?accessdate, accesstime=?accesstime where userid=?userid ");
sql.set("accessdate", now, "DATE");
sql.set("accesstime", now, "TIME");
sql.set("userid", userid);
this.logger.info(this.constructor.name + ".updateUserAccess", sql);
rs = await sql.executeUpdate(db, context);
this.logger.debug(this.constructor.name + ".updateUserAccess: affected " + rs.rows.affectedRows + " rows.");
return Promise.resolve();
}
async updateUserLock(db, username, lockflag, context) {
let loginfailtimes = 0;
let now = new Date();
let failtime = now.getTime();
let sql = new will_sql_1.KnSQL();
let locked = "1" == lockflag;
if (locked) {
loginfailtimes = 1;
sql.append("update tuser set loginfailtimes = loginfailtimes + ?loginfailtimes, failtime=?failtime ");
}
else {
sql.append("update tuser set loginfailtimes=?loginfailtimes, failtime=?failtime ");
failtime = 0;
}
sql.append("where username = ?username ");
sql.set("loginfailtimes", loginfailtimes);
sql.set("failtime", failtime);
sql.set("username", username);
this.logger.info(this.constructor.name + ".updateUserLock", sql);
let rs = await sql.executeUpdate(db, context);
this.logger.debug(this.constructor.name + ".updateUserLock: affected " + rs.rows.affectedRows + " rows.");
return Promise.resolve();
}
async accesstoken(context) {
return this.callFunctional(context, { operate: "accesstoken", raw: false }, this.doAccessToken);
}
async account(context) {
return this.callFunctional(context, { operate: "account", raw: false }, this.doAccessToken);
}
async doAccessToken(context, model) {
let token = this.getTokenKey(context);
this.logger.debug(this.constructor.name + ".doAccessToken: token = " + token);
if (!token || token == "") {
return Promise.reject(new VerifyError_1.VerifyError("Invalid access token", will_api_1.HTTP.NOT_ACCEPTABLE, -3010));
}
await this.verifyAuthenToken(token);
let db = this.getPrivateConnector(model);
try {
let body = await this.processAccessToken(db, token, false, context);
this.updateUserAccessing(context, model, { userid: body.get("userid") });
return body;
}
catch (ex) {
this.logger.error(this.constructor.name, ex);
return Promise.reject(this.getDBError(ex));
}
finally {
if (db)
db.close();
}
}
async processAccessToken(db, useruuid, fetching = true, context) {
let body = new Map();
let now = new Date();
let sql = new will_sql_1.KnSQL("select tuser.userid,tuser.username,tuser.userpassword,tuser.passwordexpiredate,tuser.site,");
sql.append("tuser.accessdate,tuser.accesstime,tuser.changeflag,tuser.newflag,tuser.loginfailtimes,tuser.failtime,tuser.lockflag,");
sql.append("tuserinfo.userename,tuserinfo.useresurname,tuserinfo.email,tuserinfo.displayname,tuserinfo.langcode,tuserinfo.activeflag,tuserinfo.usercontents,");
sql.append("tusertoken.expiretimes,tusertoken.code,tusertoken.state,tusertoken.nonce,tusertoken.authtoken,tusertoken.accesscontents,");
sql.append("tusertoken.prime,tusertoken.generator,tusertoken.publickey,tusertoken.useruuid,tusertoken.factorcode ");
sql.append("from tusertoken,tuser,tuserinfo ");
if (fetching) {
sql.append("where tusertoken.useruuid = ?useruuid ");
sql.set("useruuid", useruuid);
}
else {
sql.append("where tusertoken.authtoken = ?authtoken ");
sql.set("authtoken", useruuid);
}
sql.append("and tusertoken.expiretimes >= ?expiretimes ");
sql.append("and tusertoken.outdate is null and tusertoken.outtime is null ");
sql.append("and tusertoken.userid = tuser.userid ");
sql.append("and tuser.userid = tuserinfo.userid ");
sql.set("expiretimes", now.getTime());
let rs = await sql.executeQuery(db, context);
this.logger.debug(this.constructor.name + ".processAccessToken: effected " + rs.rows.length + " rows.");
if (rs.rows && rs.rows.length > 0) {
let row = rs.rows[0];
let handler = new TwoFactorHandler_1.TwoFactorHandler();
let factorInfo = await handler.getFactorInfo(db, row.userid, true);
let token = new UserToken_1.UserToken(row.useruuid, row.expiretimes, row.code, row.state, row.nonce, row.authtoken);
let dh = { prime: row.prime, generator: row.generator, publickey: row.publickey };
this.composeResponseBody(body, token, row.username, { ...row, ...factorInfo }, false, dh);
}
else {
return Promise.reject(new VerifyError_1.VerifyError("Invalid access token", will_api_1.HTTP.NOT_ACCEPTABLE, -3011));
}
return Promise.resolve(body);
}
async fetchtoken(context) {
return this.callFunctional(context, { operate: "fetchtoken", raw: false }, this.doFetchToken);
}
async doFetchToken(context, model) {
let puuid = context.params.useruuid;
this.logger.debug(this.constructor.name + ".doFetchToken: useruuid = " + puuid);
if (!puuid || puuid == "") {
return Promise.reject(new VerifyError_1.VerifyError("Invalid access user", will_api_1.HTTP.NOT_ACCEPTABLE, -3010));
}
let db = this.getPrivateConnector(model);
try {
let body = await this.processAccessToken(db, puuid, true);
this.updateUserAccessing(context, model, { userid: body.get("userid") });
return body;
}
catch (ex) {
this.logger.error(this.constructor.name, ex);
return Promise.reject(this.getDBError(ex));
}
finally {
if (db)
db.close();
}
}
async signout(context) {
return this.callFunctional(context, { operate: "signout", raw: false }, this.doSignout);
}
async doSignout(context, model) {
let puuid = context.params.useruuid;
this.logger.debug(this.constructor.name + ".doSignout: useruuid = " + puuid);
if (!puuid || puuid == "") {
let token = await this.getAuthenToken(context, false, false);
if (token) {
puuid = token.identifier;
}
}
if (!puuid || puuid == "") {
return Promise.reject(new VerifyError_1.VerifyError("Invalid access token", will_api_1.HTTP.NOT_ACCEPTABLE, -3010));
}
try {
let session = context.meta?.session;
if (session) {
delete session.dh;
delete session.user;
}
delete context.meta.user;
}
catch (ex) { }
let db = this.getPrivateConnector(model);
try {
return await this.processSignout(db, puuid, context);
}
catch (ex) {
this.logger.error(this.constructor.name, ex);
return Promise.reject(this.getDBError(ex));
}
finally {
if (db)
db.close();
}
}
async processSignout(db, useruuid, context) {
let body = new Map();
let sql = new will_sql_1.KnSQL("delete from tusertoken where useruuid = ?useruuid ");
sql.set("useruuid", useruuid);
this.logger.info(this.constructor.name + ".processSignout", sql);
let rs = await sql.executeUpdate(db, context);
this.logger.debug(this.constructor.name + ".processSignout: affected " + rs.rows.affectedRows + " rows.");
if (rs.rows.affectedRows > 0) {
body.set("affected", rs.rows.affectedRows);
}
else {
return Promise.reject(new VerifyError_1.VerifyError("Invalid access token", will_api_1.HTTP.BAD_REQUEST, -3011));
}
return Promise.resolve(body);
}
async loginWow(userid, pwd, site) {
let result = {};
if (EnvironmentVariable_1.NEWS_URL_ALWAYS_OPEN)
result = will_lib_2.AuthenLibrary.getDefaultResponse();
try {
let cfg = will_lib_2.AuthenLibrary.getDefaultConfigure(site);
this.logger.debug(this.constructor.name + ".loginWow: login config", cfg);
let alib = new will_lib_2.AuthenLibrary();
let res = await alib.authenticate(userid, pwd, cfg);
return Promise.resolve(res);
}
catch (ex) {
this.logger.error(this.constructor.name, ex);
}
return Promise.resolve(result);
}
async validatetoken(context) {
await this.exposeFunctional(context, this.model, { operate: "validatetoken" });
return this.getAuthenToken(context, true, true);
}
}
exports.SigninHandler = SigninHandler;