UNPKG

w-web-sso

Version:
1,181 lines (922 loc) 40.3 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>WWebSso.mjs - Documentation</title> <script src="scripts/prettify/prettify.js"></script> <script src="scripts/prettify/lang-css.js"></script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc.css"> <script src="scripts/nav.js" defer></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <input type="checkbox" id="nav-trigger" class="nav-trigger" /> <label for="nav-trigger" class="navicon-button x"> <div class="navicon"></div> </label> <label for="nav-trigger" class="overlay"></label> <nav > <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WWebSso.html">WWebSso</a></li></ul> </nav> <div id="main"> <h1 class="page-title">WWebSso.mjs</h1> <section> <article> <pre class="prettyprint source linenums"><code>import path from 'path' import fs from 'fs' import get from 'lodash-es/get.js' import iseobj from 'wsemi/src/iseobj.mjs' import isestr from 'wsemi/src/isestr.mjs' import ispint from 'wsemi/src/ispint.mjs' import isearr from 'wsemi/src/isearr.mjs' import ispnum from 'wsemi/src/ispnum.mjs' import isErr from 'wsemi/src/isErr.mjs' import isfun from 'wsemi/src/isfun.mjs' import cint from 'wsemi/src/cint.mjs' import strleft from 'wsemi/src/strleft.mjs' import strright from 'wsemi/src/strright.mjs' import strdelright from 'wsemi/src/strdelright.mjs' import pm2resolve from 'wsemi/src/pm2resolve.mjs' import fsIsFolder from 'wsemi/src/fsIsFolder.mjs' import fsIsFile from 'wsemi/src/fsIsFile.mjs' import replace from 'wsemi/src/replace.mjs' import WServHapiServer from 'w-serv-hapi/src/WServHapiServer.mjs' import WServOrm from 'w-serv-orm/src/WServOrm.mjs' import ds from '../src/schema/index.mjs' import * as s from '../src/plugins/mShare.mjs' import srlog from './srlog.mjs' import procCore from './procCore.mjs' import procProtect from './procProtect.mjs' import procStaInfor from './procStaInfor.mjs' import procSettings from './procSettings.mjs' /** * 權限伺服器 * * @class * @param {Function} WOrm 輸入資料庫ORM函數 * @param {String} url 輸入資料庫連線字串,例如w-orm-lmdb為'./db',或w-orm-mongodb為'mongodb://username:password@$127.0.0.1:27017' * @param {String} db 輸入資料庫名稱字串 * @param {String} [pathSettings='./settings'] 輸入設定檔案路徑字串,預設'./settings' * @returns {Object} 回傳物件,其內server為hapi伺服器實體,wsrv為w-converhp的伺服器事件物件,wsds為w-serv-webdata的伺服器事件物件,可監聽error事件 * @example * * * */ function WWebSso(WOrm, url, db, pathSettings) { let instWServHapiServer = null //check WOrm if (!isfun(WOrm)) { console.log('invalid WOrm', WOrm) throw new Error('invalid WOrm') } //check url if (!isestr(url)) { console.log('invalid url', url) throw new Error('invalid url') } //check db if (!isestr(db)) { console.log('invalid db', db) throw new Error('invalid db') } //check pathSettings if (!fsIsFile(pathSettings)) { pathSettings = './settings.json' } //setFilepath procSettings.setFilepath(pathSettings) //getSettings let opt = procSettings.getSettings() // console.log('opt', opt) // * @param {Object|String} [opt={}] 輸入設定物件或設定檔檔案路徑字串,若給予檔案路徑則會預設檔案為json格式且讀入成為opt物件,預設{} // * @param {Integer} [opt.serverPort=11007] 輸入伺服器通訊port整數,預設11007 // * @param {Boolean} [opt.useCheckUser=false] 輸入是否檢查使用者資訊布林值,預設false // * @param {Function} [opt.getUserById=null] 輸入當useCheckUser=true時依照使用者ID取得使用者資訊物件函數,預設null // * @param {Boolean} [opt.useExcludeWhenNotAdmin=false] 輸入使用ORM的select方法時是否自動刪除數據內isActive欄位之布林值,預設false // * @param {Object} [opt.webName={}] 輸入站台名稱物件,至少包含語系eng與cht鍵的名稱,預設{} // * @param {Object} [opt.webDescription={}] 輸入站台描述物件,至少包含語系eng與cht鍵的名稱,預設{} // * @param {String} [opt.webLogo=''] 輸入站台logo字串,採base64格式,預設'' // * @param {Array} [opt.webBackgoundGradientColors=['#FFE0B2', '#FFCC80', '#FFF59D', '#F2D6A2', '#F0CC88']] 輸入使用者登入頁顏色陣列,前3色為背景線性linear-gradient,第4色為登入區塊背景色,第5色為站台logo背景色,若不給則預設白色。預設['#FFE0B2', '#FFCC80', '#FFF59D', '#F2D6A2', '#F0CC88'] // * @param {String} [opt.webKey=''] 輸入站台識別字串,預設'' // * @param {String} [opt.salt=''] 輸入密碼加鹽字串,預設'' // * @param {Integer} [opt.minExpired=30] 輸入創建或更新金鑰有效時間整數,單位分鐘(min),預設30 // * @param {Integer} [opt.minForAccountLoginFailed=10] 輸入限制帳號最大登入失敗(密碼錯誤)次數之判準時間整數,單位分鐘(min),預設10 // * @param {Integer} [opt.numForAccountLoginFailed=3] 輸入限制帳號最大登入失敗(密碼錯誤)之次數整數,預設3 // * @param {Integer} [opt.minBlockForAccountLoginFailed=30] 輸入限制帳號最大登入失敗(密碼錯誤)次數之觸發後封鎖時間整數,單位分鐘(min),預設30 // * @param {Integer} [opt.minForTokenCallApi=10] 輸入限制token最大調用API次數之判準時間整數,單位分鐘(min),預設10 // * @param {Integer} [opt.numForTokenCallApi=1000] 輸入限制token最大調用API之次數整數,預設1000 // * @param {Integer} [opt.minBlockForTokenCallApi=30] 輸入限制token最大調用API次數之觸發後封鎖時間整數,單位分鐘(min),預設30 // * @param {Integer} [opt.minForIpCallApi=10] 輸入限制IP最大調用API次數之判準時間整數,單位分鐘(min),預設10 // * @param {Integer} [opt.numForIpCallApi=10000] 輸入限制IP最大調用API之次數整數,預設10000 // * @param {Integer} [opt.minBlockForIpCallApi=30] 輸入限制IP最大調用API次數之觸發後封鎖時間整數,單位分鐘(min),預設30 // * @param {String} [opt.userLogo=''] 輸入使用者logo字串,採base64格式,預設'' // * @param {String} [opt.subfolder=''] 輸入站台所在子目錄字串,提供站台位於內網採反向代理進行服務時,故需支援位於子目錄情形,預設'' // * @param {String} [opt.mappingBy='email'] 輸入外部系統識別使用者token後所提供之資料物件,與權限系統之使用者資料物件,兩者間查找之對應欄位,可選'id'、'email'、'name',預設'email' //serverPort let serverPort = get(opt, 'serverPort') if (!ispint(serverPort)) { serverPort = 11007 } serverPort = cint(serverPort) //useCheckUser let useCheckUser = get(opt, 'useCheckUser', false) //getUserById let getUserById = get(opt, 'getUserById', null) //useExcludeWhenNotAdmin let useExcludeWhenNotAdmin = get(opt, 'useExcludeWhenNotAdmin', false) //webName let webName = get(opt, 'webName', {}) //webDescription let webDescription = get(opt, 'webDescription', {}) //webLogo let webLogo = get(opt, 'webLogo', '') //webBackgoundGradientColors let webBackgoundGradientColors = get(opt, 'webBackgoundGradientColors', []) if (!isearr(webBackgoundGradientColors)) { webBackgoundGradientColors = ['#FFE0B2', '#FFCC80', '#FFF59D', '#F2D6A2', '#F0CC88'] } //webKey let webKey = get(opt, 'webKey', '') //salt let salt = get(opt, 'salt', '') //minExpired, 使用者成功登入後產生token之有效時間(分鐘) let minExpired = get(opt, 'minExpired', '') if (!ispnum(minExpired)) { minExpired = 30 } //minForAccountLoginFailed, 限制帳號最大登入失敗(密碼錯誤)次數之判準時間(分鐘) let minForAccountLoginFailed = get(opt, 'minForAccountLoginFailed', '') if (!ispnum(minForAccountLoginFailed)) { minForAccountLoginFailed = 10 } //numForAccountLoginFailed, 限制帳號最大登入失敗(密碼錯誤)之次數 let numForAccountLoginFailed = get(opt, 'numForAccountLoginFailed', '') if (!ispnum(numForAccountLoginFailed)) { numForAccountLoginFailed = 3 } //minBlockForAccountLoginFailed, 限制帳號最大登入失敗(密碼錯誤)次數之觸發後封鎖時間(分鐘) let minBlockForAccountLoginFailed = get(opt, 'minBlockForAccountLoginFailed', '') if (!ispnum(minBlockForAccountLoginFailed)) { minBlockForAccountLoginFailed = 30 } //minForTokenCallApi, 限制token最大調用API次數之判準時間(分鐘) let minForTokenCallApi = get(opt, 'minForTokenCallApi', '') if (!ispnum(minForTokenCallApi)) { minForTokenCallApi = 10 } //numForTokenCallApi, 限制token最大調用API之次數 let numForTokenCallApi = get(opt, 'numForTokenCallApi', '') if (!ispnum(numForTokenCallApi)) { numForTokenCallApi = 1000 } //minBlockForTokenCallApi, 限制token最大調用API次數之觸發後封鎖時間(分鐘) let minBlockForTokenCallApi = get(opt, 'minBlockForTokenCallApi', '') if (!ispnum(minBlockForTokenCallApi)) { minBlockForTokenCallApi = 30 } //minForIpCallApi, 限制IP最大調用API次數之判準時間(分鐘) let minForIpCallApi = get(opt, 'minForIpCallApi', '') if (!ispnum(minForIpCallApi)) { minForIpCallApi = 10 } //numForIpCallApi, 限制IP最大調用API之次數 let numForIpCallApi = get(opt, 'numForIpCallApi', '') if (!ispnum(numForIpCallApi)) { numForIpCallApi = 10000 } //minBlockForIpCallApi, 限制IP最大調用API次數之觸發後封鎖時間(分鐘) let minBlockForIpCallApi = get(opt, 'minBlockForIpCallApi', '') if (!ispnum(minBlockForIpCallApi)) { minBlockForIpCallApi = 30 } //是否啟用要求使用者定期更換密碼 // 若是,預設6個月更換密碼,是否允許使用同樣密碼 //userLogo let userLogo = get(opt, 'userLogo', '') //subfolder let subfolder = get(opt, 'subfolder', '') if (isestr(subfolder)) { if (strright(subfolder, 1) === '/') { //右邊不需要給「/」 subfolder = strdelright(subfolder, 1) } if (strleft(subfolder, 1) !== '/') { //左邊需要給「/」 subfolder = `/${subfolder}` } } //params let showLanguage = get(opt, 'showLanguage', 'n') let language = get(opt, 'language', 'eng') let showModeEditUsers = get(opt, 'showModeEditUsers', 'n') let modeEditUsers = get(opt, 'modeEditUsers', 'n') let showModeEditTokens = get(opt, 'showModeEditTokens', 'n') let modeEditTokens = get(opt, 'modeEditTokens', 'n') let showModeEditIps = get(opt, 'showModeEditIps', 'n') let modeEditIps = get(opt, 'modeEditIps', 'n') //是否可於登入頁提供申請註冊使用者按鈕 //是否使用圖形驗證碼模組 //email模板 // 註冊驗證信模板 // 變更使用者密碼驗證信模板 // 註冊請求通知(給SSO系統管理員)信模板 // 註冊核可成功通知信模板 // 變更使用者資訊通知信模板 //mappingBy let mappingBy = get(opt, 'mappingBy', '') if (mappingBy !== 'id' &amp;&amp; mappingBy !== 'email' &amp;&amp; mappingBy !== 'name') { mappingBy = 'email' } // console.log('mappingBy', mappingBy) //kpLangExt let kpLangExt = get(opt, 'kpLangExt', null) //WServOrm let optWServOrm = { useCheckUser, getUserById, useExcludeWhenNotAdmin, } let wp = {} try { wp = WServOrm(ds, WOrm, url, db, optWServOrm) } catch (err) { console.log(err) } let { woItems, procOrm } = wp //getWebInfor let getWebInfor = () => { return { webName, webDescription, webLogo, webBackgoundGradientColors, webKey, userLogo, showLanguage, language, showModeEditUsers, modeEditUsers, showModeEditTokens, modeEditTokens, showModeEditIps, modeEditIps, kpLangExt, } } //procCore, procProtect, procStaInfor let p = procCore(woItems, procOrm, { salt, minExpired }) let pp = procProtect(woItems, p, { minForAccountLoginFailed, numForAccountLoginFailed, minBlockForAccountLoginFailed, minForTokenCallApi, numForTokenCallApi, minBlockForTokenCallApi, minForIpCallApi, numForIpCallApi, minBlockForIpCallApi, }) let pf = procStaInfor(woItems, p, { }) // //parseToken // let parseToken = (req) => { // //token // let token = get(req, 'query.token', '') // // console.log('token', token) // return token // } // //getTokenUser // let getTokenUser = async(token) => { // //userSelf // let userSelf = null // if (isestr(token)) { // userSelf = getUserByToken(token) // if (ispm(userSelf)) { // userSelf = await userSelf // } // } // // console.log('userSelf', userSelf) // //check // if (!iseobj(userSelf)) { // console.log(`token`, token) // console.log(`can not find the user from token`) // return Promise.reject(`can not find the user from token`) // } // //check userSelf // if (true) { // let id = get(userSelf, 'id', '') // if (!isestr(id)) { // console.log('userSelf', userSelf) // console.log('can not get the userId') // return Promise.reject(`can not get the userId`) // } // let email = get(userSelf, 'email', '') // if (!isestr(email)) { // console.log('userSelf', userSelf) // console.log('can not get the email of user') // return Promise.reject(`can not get the email of user`) // } // let name = get(userSelf, 'name', '') // if (!isestr(name)) { // console.log('userSelf', userSelf) // console.log('can not get userName') // return Promise.reject(`can not get userName`) // } // let isAdmin = get(userSelf, 'isAdmin', '') // if (isAdmin !== 'y' &amp;&amp; isAdmin !== 'n') { // console.log('userSelf', userSelf) // console.log('userSelf.isAdmin is not y or n', userSelf.isAdmin) // console.log('can not get the role of user') // return Promise.reject(`can not get the role of user`) // } // } // //須反查sso內users, 提供正規化屬性 // let vSelf = get(userSelf, mappingBy, '') // // console.log('vSelf', vSelf) // //check // if (!isestr(vSelf)) { // console.log('userSelf', userSelf) // console.log('mappingBy', mappingBy) // console.log('can not get the prop of user by mappingBy') // return Promise.reject(`can not get the prop of user by mappingBy`) // } // //userFind // let userFind = await woItems.users.select({ [mappingBy]: vSelf, isActive: 'y' }) // userFind = get(userFind, 0, null) // // console.log('userFind', userFind) // //check // if (!iseobj(userFind)) { // console.log('userSelf', userSelf) // console.log('mappingBy', mappingBy) // console.log('can not get the user from sso') // return Promise.reject(`can not get the user from sso`) // } // //複寫isAdmin // let isAdminSrc = get(userSelf, 'isAdmin', '') // let isAdminSelf = get(userFind, 'isAdmin', '') // if (isAdminSrc !== isAdminSelf) { // userFind.isAdmin = isAdminSelf // } // // console.log('userFind(isAdmin)', userFind) // return userFind // } // //getAndVerifyBrowserTokenUser // let getAndVerifyBrowserTokenUser = async (token, caller = '') => { // //getTokenUser // let userSelf = await getTokenUser(token) // //verifyClientUser // let b = verifyClientUser(userSelf, caller) // if (ispm(b)) { // b = await b // } // //check // if (!b) { // console.log('userSelf', userSelf) // console.log(`user does not have permission`) // return Promise.reject(`user does not have permission`) // } // return userSelf // } // //getAndVerifyAppTokenUser // let getAndVerifyAppTokenUser = async (token, caller = '') => { // //getTokenUser // let userSelf = await getTokenUser(token) // //verifyAppUser // let b = verifyAppUser(userSelf, caller) // if (ispm(b)) { // b = await b // } // //check // if (!b) { // console.log('userSelf', userSelf) // console.log(`user does not have permission`) // return Promise.reject(`user does not have permission`) // } // return userSelf // } // //parsePayload // let parsePayload = async (req, key) => { // //inp // let inp = get(req, 'payload') // //to obj // if (isestr(inp)) { // inp = j2o(inp) // } // //check // if (!iseobj(inp)) { // console.log('inp', inp) // console.log('invalid inp from req') // return Promise.reject(`invalid inp from req`) // } // //from // let from = get(inp, 'from', '') // //check // if (!isestr(from)) { // console.log('inp', inp) // console.log('from', from) // console.log('invalid from from inp') // return Promise.reject(`invalid from from inp`) // } // //vs // let vs = get(inp, key, []) // //check // if (!isearr(vs)) { // console.log('inp', inp) // console.log(key, vs) // console.log(`invalid ${key} from inp`) // return Promise.reject(`invalid ${key} from inp`) // } // //r // let r = { // from, // [key]: vs, // } // return r // } // //syncAndReplaceRows // let syncAndReplaceRows = async (params, key) => { // //from // let from = get(params, 'from', '') // // console.log('from', from) // //check // if (!isestr(from)) { // console.log('params', params) // console.log('from', from) // console.log(`invalid from`) // return Promise.reject(`invalid from`) // } // //vs // let vs = get(params, key, []) // // console.log(key, vs) // //check // if (!isearr(vs)) { // console.log('params', params) // console.log(key, vs) // console.log(`invalid ${key}`) // return Promise.reject(`invalid ${key}`) // } // //save from // each(vs, (v, k) => { // vs[k].from = from // }) // //delAll from // await woItems[key].delAll({ from }) // //insert // let r = await woItems[key].insert(vs) // return r // } //funCheckAdmin let funCheckAdmin = (tk, u) => { // console.log('tk', tk, 'u', u) let b = s.checkUserAdmin(u) // console.log('checkUserAdmin', b) return b } //pathStaticFiles let pathStaticFiles = 'dist' let npmPathStaticFiles = './node_modules/w-web-sso/dist' if (fsIsFolder(npmPathStaticFiles)) { pathStaticFiles = npmPathStaticFiles } // console.log('pathStaticFiles', pathStaticFiles) //subfolder let fnEntryIn = 'index.tmp' let fnEntryOut = 'index.html' try { let fpEntryIn = path.resolve(pathStaticFiles, fnEntryIn) if (!fsIsFile(fpEntryIn)) { fpEntryIn = path.resolve(pathStaticFiles, fnEntryOut) //本機開發另使用html替代tmp } if (!fsIsFile(fpEntryIn)) { console.log('fpEntryIn', fpEntryIn) throw new Error(`invalid fpEntryIn`) } let fpEntryOut = path.resolve(pathStaticFiles, fnEntryOut) let c = fs.readFileSync(fpEntryIn, 'utf8') c = replace(c, '/msso/', '{sfd}/') //方法同genEntry c = replace(c, '{sfd}', subfolder) c = replace(c, '{language}', language) fs.writeFileSync(fpEntryOut, c, 'utf8') } catch (err) { console.log(err) console.log(`can not generate ${fnEntryOut}`) } //apis let apis = [ //sso不使用w-ui-loginout // { // method: 'GET', // path: '/api/getUserByToken', //未登入主頁時需先檢測token, getUserByToken為w-ui-loginout預設值, 若要更改兩邊須同時修改 // }, { method: 'GET', path: '/api/logoutSsoUser', handler: async function (req, res) { // console.log('logoutSsoUser', req) async function core() { //token let token = get(req, 'query.token', '') // console.log('token', token) //info srlog.info({ event: 'api/logoutSsoUser', token }) //logoutByToken let b = await p.logoutByToken(token) // console.log('b', b) return b } //pm2resolve core let r = await pm2resolve(core)() if (isErr(r.msg)) { r.msg = r.msg.message } // console.log('logoutSsoUser', r) return r }, }, { method: 'GET', path: '/api/checkToken', handler: async function (req, res) { // console.log('checkToken', req) async function core() { //token let token = get(req, 'query.token', '') // console.log('token', token) //info srlog.info({ event: 'api/checkToken', token }) //callApiByToken pp.callApiByToken(token) //checkToken let b = await p.checkToken(token) // console.log('b', b) return b } //pm2resolve core let r = await pm2resolve(core)() if (isErr(r.msg)) { r.msg = r.msg.message } // console.log('checkToken', r) return r }, }, { method: 'GET', path: '/api/refreshToken', handler: async function (req, res) { // console.log('refreshToken', req) async function core() { //token let token = get(req, 'query.token', '') // console.log('token', token) //info srlog.info({ event: 'api/refreshToken', token }) //callApiByToken pp.callApiByToken(token) //refreshToken let b = await p.refreshToken(token) // console.log('b', b) return b } //pm2resolve core let r = await pm2resolve(core)() if (isErr(r.msg)) { r.msg = r.msg.message } // console.log('refreshToken', r) return r }, }, { method: 'GET', path: '/api/logoutByToken', handler: async function (req, res) { // console.log('logoutByToken', req) async function core() { //token let token = get(req, 'query.token', '') // console.log('token', token) //info srlog.info({ event: 'api/logoutByToken', token }) //callApiByToken pp.callApiByToken(token) //logoutByToken let b = await p.logoutByToken(token) // console.log('b', b) return b } //pm2resolve core let r = await pm2resolve(core)() if (isErr(r.msg)) { r.msg = r.msg.message } // console.log('logoutByToken', r) return r }, }, { method: 'GET', path: '/api/getSsoUsersList', handler: async function (req, res) { // console.log('getSsoUsersList', req) async function core() { //token let token = get(req, 'query.token', '') // console.log('token', token) //info srlog.info({ event: 'api/getSsoUsersList', token }) //callApiByToken pp.callApiByToken(token) //checkTokenAndGetUsersList let us = await p.checkTokenAndGetUsersList(token) // console.log('us', us) return us } //pm2resolve core let r = await pm2resolve(core)() if (isErr(r.msg)) { r.msg = r.msg.message } // console.log('getSsoUsersList', r) return r }, }, { method: 'GET', path: '/api/getSsoUserInfor', handler: async function (req, res) { // console.log('getSsoUserInfor', req) async function core() { //token let token = get(req, 'query.token', '') // console.log('token', token) //key let key = get(req, 'query.key', '') // console.log('key', key) //value let value = get(req, 'query.value', '') // console.log('value', value) //info srlog.info({ event: 'api/getSsoUserInfor', token, key, value }) //callApiByToken pp.callApiByToken(token) //userTarget let userTarget = null if (key === 'token') { userTarget = await p.checkTokenAndGetUserByToken(token, value) // console.log('checkTokenAndGetUserByToken userTarget', userTarget) } else { userTarget = await p.checkTokenAndGetUserInfor(token, key, value) // console.log('checkTokenAndGetUserInfor userTarget', userTarget) } //check if (!iseobj(userTarget)) { console.log('token', token) console.log('key', key, 'value', value) console.log(`token does not have permission`) return Promise.reject(`token does not have permission`) } return userTarget } //pm2resolve core let r = await pm2resolve(core)() if (isErr(r.msg)) { r.msg = r.msg.message } // console.log('getSsoUserInfor', r) return r }, }, ] //WServHapiServer instWServHapiServer = new WServHapiServer({ port: opt.serverPort, pathStaticFiles, apiName: 'api', apis, tokenType: 'Bearer', verifyConn: async ({ apiType, authorization, query, headers, req }) => { // console.log('headers', headers) //getIpByHeaders let ip = pp.getIpByHeaders(req) // console.log('ip', ip) //origin let origin = get(headers, 'origin', '') //referer let referer = get(headers, 'referer', '') //info srlog.info({ event: 'verifyConn', ip, origin, referer }) //callApiByIp pp.callApiByIp(ip) //getBlockedByIp let b = true await pp.getBlockedByIp(ip) .then((res) => { // console.log('pp.getBlockedByIp(ip) then', res) b = res }) .catch(() => { // console.log('pp.getBlockedByIp(ip) catch', err) b = true }) // console.log('pp.getBlockedByIp(ip)', b) //b改為代表通行(未封鎖)狀態 b = !b // //getInforsByIpCallApi // let rs = await pp.getInforsByIpCallApi(ip) // console.log('getInforsByIpCallApi', [ // rs[0], // rs[rs.length - 1], // ], rs.length) //logshow if (!b) { console.log(`block ip[${ip}]`) //[tag:測試:顯示被封鎖ip] } return b }, getUserIdByToken: async (token) => { //可使用async或sync函數 return '' //不檢核, 查找與變更數據皆由kpFunExt內各函數各自檢核 }, corsOrigins: ['*'], useDbOrm: false, // kpOrm: woItems, // operOrm: procOrm, //procOrm的輸入為: userId, tableName, methodName, input tableNamesExec: [], methodsExec: [], //['select', 'insert', 'save', 'del', 'delAll'], tableNamesSync: [], kpFunExt: { //接收參數第1個為userId, 之後才是前端給予參數 getWebInfor: async (_t) => { return getWebInfor() }, checkToken: async(_t, token) => { //sso前端通過$fapi.checkToken調用 srlog.info({ event: 'kpfun-checkToken', token }) let r = await p.checkToken(token) return r }, refreshToken: async(_t, token) => { //sso前端通過$fapi.refreshToken調用 srlog.info({ event: 'kpfun-refreshToken', token }) let r = await p.refreshToken(token) return r }, loginByAccountAndPassword: async (_t, account, password) => { //info, 使用者登入前 srlog.info({ event: 'kpfun-loginByAccountAndPassword-before', account }) let u = null let msg = '' await pp.loginByAccountAndPassword(account, password) //記得不能使用p.loginByAccountAndPassword, 此未提供保護機制 .then((res) => { u = res }) .catch((err) => { msg = err }) //info, 使用者登入成功或失敗 if (iseobj(u)) { srlog.info({ event: 'kpfun-loginByAccountAndPassword-success', account }) } else { srlog.info({ event: 'kpfun-loginByAccountAndPassword-error', account, msg }) } if (iseobj(u)) { return u } return Promise.reject(msg) }, logoutByToken: async (_t, token) => { srlog.info({ event: 'kpfun-logoutByToken', token }) let r = await p.logoutByToken(token) return r }, getUserByToken: async (_t, token) => { srlog.info({ event: 'kpfun-getUserByToken', token }) //console.log('call getUserByToken...') let r = await p.checkTokenAndGetUserByToken(token, token) //console.log('call getUserByToken end') return r }, getUserInfor: async (_t, token, key, value) => { srlog.info({ event: 'kpfun-getUserInfor', token, key, value }) //console.log('call getUserInfor...') let r = await p.checkTokenAndGetUserInfor(token, key, value) //console.log('call getUserInfor end') return r }, getUsersList: async (_t, token) => { srlog.info({ event: 'kpfun-getUsersList', token }) //console.log('call getUsersList...') let rs = await p.checkTokenAndGetUsersList(token, { fun: funCheckAdmin }) //console.log('call getUsersList end') return rs }, updateUsersList: async (_t, token, rows) => { srlog.info({ event: 'kpfun-updateUsersList', token }) //console.log('call updateUsersList...') let rs = await p.checkTokenAndUpdateUsersList(token, rows, { fun: funCheckAdmin }) //console.log('call updateUsersList end') return rs }, getTokensList: async (_t, token) => { srlog.info({ event: 'kpfun-getTokensList', token }) //console.log('call getTokensList...') let rs = await p.checkTokenAndGetTokensList(token, { fun: funCheckAdmin }) //console.log('call getTokensList end') return rs }, updateTokensList: async (_t, token, rows) => { srlog.info({ event: 'kpfun-updateTokensList', token }) //console.log('call updateTokensList...') let rs = await p.checkTokenAndUpdateTokensList(token, rows, { fun: funCheckAdmin }) //console.log('call updateTokensList end') return rs }, getIpsList: async (_t, token) => { srlog.info({ event: 'kpfun-getIpsList', token }) //console.log('call getIpsList...') let rs = await p.checkTokenAndGetIpsList(token, { fun: funCheckAdmin }) //console.log('call getIpsList end') return rs }, updateIpsList: async (_t, token, rows) => { srlog.info({ event: 'kpfun-updateIpsList', token }) //console.log('call updateIpsList...') let rs = await p.checkTokenAndUpdateIpsList(token, rows, { fun: funCheckAdmin }) //console.log('call updateIpsList end') return rs }, getStaUserSummary: async (_t, token) => { srlog.info({ event: 'kpfun-getStaUserSummary', token }) //console.log('call getStaUserSummary...') let r = await pf.getStaUserSummary(token, { fun: funCheckAdmin }) //console.log('call getStaUserSummary end') return r }, getStaTokenSummary: async (_t, token) => { srlog.info({ event: 'kpfun-getStaTokenSummary', token }) //console.log('call getStaTokenSummary...') let r = await pf.getStaTokenSummary(token, { fun: funCheckAdmin }) //console.log('call getStaTokenSummary end') return r }, getStaIpSummary: async (_t, token) => { srlog.info({ event: 'kpfun-getStaIpSummary', token }) //console.log('call getStaIpSummary...') let r = await pf.getStaIpSummary(token, { fun: funCheckAdmin }) //console.log('call getStaIpSummary end') return r }, getStaUserAccountLogin: async (_t, token) => { srlog.info({ event: 'kpfun-getStaUserAccountLogin', token }) //console.log('call getStaUserAccountLogin...') let r = await pf.checkTokenAndGetStaUserAccountLogin(token, { fun: funCheckAdmin }) //console.log('call getStaUserAccountLogin end') return r }, getStaToken: async (_t, token) => { srlog.info({ event: 'kpfun-getStaToken', token }) //console.log('call getStaToken...') let r = await pf.checkTokenAndGetStaToken(token, { fun: funCheckAdmin }) //console.log('call getStaToken end') return r }, getStaIp: async (_t, token) => { srlog.info({ event: 'kpfun-getStaIp', token }) //console.log('call getStaIp...') let r = await pf.checkTokenAndGetStaIp(token, { fun: funCheckAdmin }) //console.log('call getStaIp end') return r }, // getSettings: async (_t, token) => { // //checkToken // await p.checkToken(token) // return procSettings.getSettings() // }, // updateSettings: async (_t, token, st) => { // //checkToken // await p.checkToken(token) // return procSettings.setSettings(st) // }, }, fnTableTags: 'tableTags-web-sso.json', }) return instWServHapiServer } export default WWebSso </code></pre> </article> </section> </div> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.4</a> on Mon Aug 04 2025 13:02:44 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme. </footer> <script>prettyPrint();</script> <script src="scripts/polyfill.js"></script> <script src="scripts/linenumber.js"></script> </body> </html>