UNPKG

w-web-perm

Version:
1,286 lines (1,029 loc) 43.9 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>WWebPerm.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="WWebPerm.html">WWebPerm</a></li></ul> </nav> <div id="main"> <h1 class="page-title">WWebPerm.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 each from 'lodash-es/each.js' import map from 'lodash-es/map.js' import keys from 'lodash-es/keys.js' import size from 'lodash-es/size.js' import join from 'lodash-es/join.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 isErr from 'wsemi/src/isErr.mjs' import isfun from 'wsemi/src/isfun.mjs' import ispm from 'wsemi/src/ispm.mjs' import cint from 'wsemi/src/cint.mjs' import j2o from 'wsemi/src/j2o.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 strdelleft from 'wsemi/src/strdelleft.mjs' import haskey from 'wsemi/src/haskey.mjs' import arrHas from 'wsemi/src/arrHas.mjs' import ltdtDiffByKey from 'wsemi/src/ltdtDiffByKey.mjs' import ltdtmapping from 'wsemi/src/ltdtmapping.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 { getUserRules } from '../src/plugins/mShare.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 {Function} getUserByToken 輸入處理函數,函數會傳入使用者token,通過此函數處理後並回傳使用者資訊物件,並至少須提供'id'、'email'、'name'、'isAdmin'欄位,且'isAdmin'限輸入'y'或'n',且輸入'y'時會複寫權限系統該使用者之'isAdmin'欄位值 * @param {Function} verifyClientUser 輸入驗證瀏覽使用者身份之處理函數,函數會傳入使用者資訊物件,通過此函數識別後回傳布林值,允許使用者回傳true,反之回傳false * @param {Function} verifyAppUser 輸入驗證應用程序使用者身份之處理函數,函數會傳入使用者資訊物件,通過此函數識別後回傳布林值,允許使用者回傳true,反之回傳false * @param {Object} [opt={}] 輸入設定物件,預設{} * @param {Integer} [opt.serverPort=11006] 輸入伺服器通訊port,預設11006 * @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 {String} [opt.subfolder=''] 輸入站台所在子目錄字串,提供站台位於內網採反向代理進行服務時,故需支援位於子目錄情形,預設'' * @param {String} [opt.urlRedirect=''] 輸入錯誤時自動轉址字串,提供站台例如無法登入或驗證失敗時須自動轉址,預設'' * @param {String} [opt.mappingBy='email'] 輸入外部系統識別使用者token後所提供之資料物件,與權限系統之使用者資料物件,兩者間查找之對應欄位,可選'id'、'email'、'name',預設'email' * @returns {Object} 回傳物件,其內server為hapi伺服器實體,wsrv為w-converhp的伺服器事件物件,wsds為w-serv-webdata的伺服器事件物件,可監聽error事件 * @example * * import WOrm from 'w-orm-lmdb/src/WOrmLmdb.mjs' * import WWebPerm from './server/WWebPerm.mjs' * import getSettings from './g.getSettings.mjs' * * * //st * let st = getSettings() * * let url = st.dbUrl * let db = st.dbName * let opt = { * * useCheckUser: false, * getUserById: null, * useExcludeWhenNotAdmin: false, * * serverPort: 11006, * subfolder: '', //mperm * urlRedirect: 'https://www.google.com/', //本機測試時得先編譯, 再瀏覽: http://localhost:11006/ * * webName: { * 'eng': 'Permission Service', * 'cht': '權限管理系統', * }, * webDescription: { * 'eng': 'A web service package for user permissions and management targets.', * 'cht': 'A web service package for user permissions and management targets.', * }, * webLogo: 'data:image/svg+xml;base64,...', * * } * * let getUserByToken = async (token) => { * // return {} //測試無法登入 * if (token === '{token-for-application}') { //提供外部應用系統作為存取使用者 * return { * id: 'id-for-application', * name: 'application', * email: 'application@example.com', * isAdmin: 'y', * } * } * if (token === 'sys') { //開發階段w-ui-loginout自動給予browser使用者(且位於localhost)的token為sys * return { * id: 'id-for-admin', * name: 'tester', * email: 'admin@example.com', //mappingBy為email, 開發階段時會使用email找到所建置之使用者資料 * isAdmin: 'y', * } * } * console.log('invalid token', token) * console.log('於生產環境時得加入SSO等驗證token機制') * return {} * } * * let verifyClientUser = (user, from) => { * console.log('verifyClientUser/user', user) * // return false //測試無法登入 * console.log('於生產環境時得加入限制瀏覽器使用者身份機制') * return user.isAdmin === 'y' //測試僅系統管理者使用 * } * * let verifyAppUser = (user, from) => { * console.log('verifyAppUser/user', user) * // return false //測試無法登入 * console.log('於生產環境時得加入限制應用程式使用者身份機制') * return user.isAdmin === 'y' //測試僅系統管理者使用 * } * * //WWebPerm * let instWWebPerm = WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser, opt) * * instWWebPerm.on('error', (err) => { * console.log(err) * }) * */ function WWebPerm(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser, opt = {}) { 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 getUserByToken if (!isfun(getUserByToken)) { console.log('invalid getUserByToken', getUserByToken) throw new Error('invalid getUserByToken') } //check verifyClientUser if (!isfun(verifyClientUser)) { console.log('invalid verifyClientUser', verifyClientUser) throw new Error('invalid verifyClientUser') } //check verifyAppUser if (!isfun(verifyAppUser)) { console.log('invalid verifyAppUser', verifyAppUser) throw new Error('invalid verifyAppUser') } //serverPort let serverPort = get(opt, 'serverPort') if (!ispint(serverPort)) { serverPort = 11006 } 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', '') //subfolder let subfolder = get(opt, 'subfolder', '') if (isestr(subfolder)) { if (strright(subfolder, 1) === '/') { //右邊不需要給「/」 subfolder = strdelright(subfolder, 1) } if (strleft(subfolder, 1) !== '/') { //左邊需要給「/」 subfolder = `/${subfolder}` } } //urlRedirect let urlRedirect = get(opt, 'urlRedirect', '') // console.log('urlRedirect', urlRedirect) //params let showLanguage = get(opt, 'showLanguage', 'n') let language = get(opt, 'language', 'eng') let showModeEditTargets = get(opt, 'showModeEditTargets', 'n') let showModeEditPemis = get(opt, 'showModeEditPemis', 'n') let showModeEditGrups = get(opt, 'showModeEditGrups', 'n') let showModeEditUsers = get(opt, 'showModeEditUsers', 'n') let modeEditTargets = get(opt, 'modeEditTargets', 'n') let modeEditPemis = get(opt, 'modeEditPemis', 'n') let modeEditGrups = get(opt, 'modeEditGrups', 'n') let modeEditUsers = get(opt, 'modeEditUsers', 'n') let widthTargetId = get(opt, 'widthTargetId', '') let widthTargetDescription = get(opt, 'widthTargetDescription', '') let widthPemisName = get(opt, 'widthPemisName', '') let widthPemisDescription = get(opt, 'widthPemisDescription', '') let widthGrupsName = get(opt, 'widthGrupsName', '') let widthGrupsDescription = get(opt, 'widthGrupsDescription', '') let widthUsersName = get(opt, 'widthUsersName', '') let widthUsersEmail = get(opt, 'widthUsersEmail', '') let widthUsersDescription = get(opt, 'widthUsersDescription', '') //mappingBy let mappingBy = get(opt, 'mappingBy', '') if (mappingBy !== 'id' &amp;&amp; mappingBy !== 'email' &amp;&amp; mappingBy !== 'name') { mappingBy = 'id' } // 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 = (userId) => { return { webName, webDescription, webLogo, // urlRedirect, //登入失敗就需要轉址, 故須通過html模板取代提供, 無法用api提供 showLanguage, language, showModeEditTargets, showModeEditPemis, showModeEditGrups, showModeEditUsers, modeEditTargets, modeEditPemis, modeEditGrups, modeEditUsers, widthTargetId, widthTargetDescription, widthPemisName, widthPemisDescription, widthGrupsName, widthGrupsDescription, widthUsersName, widthUsersEmail, widthUsersDescription, kpLangExt, } } // //getTargetsList // let getTargetsList = async (userId) => { // let rs = await woItems.targets.select() // return rs // } // //getPemisList // let getPemisList = async (userId) => { // let rs = await woItems.pemis.select() // return rs // } // //getGrupsList // let getGrupsList = async (userId) => { // let rs = await woItems.grups.select() // return rs // } // //getUsersList // let getUsersList = async (userId) => { // let rs = await woItems.users.select() // return rs // } //updateTabItems let updateTabItems = async (keyTable, userId, rows, keyDetect) => { // console.log('updateTabItems', keyTable, userId, rows.length, keyDetect) //ltdtmapping rows = ltdtmapping(rows, ds[keyTable].keys) // console.log('ltdtmapping rows', rows) //重給order rows = map(rows, (r, k) => { r.order = k + 1 return r }) //ckKey let ckKey = (rows, key) => { let err = null //check let kp = {} each(rows, (v, k) => { //value let value = get(v, key, '') //check if (!isestr(value)) { err = `rows[${k}].${key} is not an effective string` return false //跳出 } //check if (haskey(kp, value)) { err = `rows[${k}].${key}[${value}] is duplicate` return false //跳出 } //kp kp[value] = true }) return err } //偵測未給予或重複 let err = null if (true) { if (arrHas(keyTable, ['targets'])) { err = ckKey(rows, 'id') if (err !== null) { return Promise.reject(err) } } if (arrHas(keyTable, ['pemis', 'grups'])) { //users可重複name故不列入 err = ckKey(rows, 'name') if (err !== null) { return Promise.reject(err) } } if (arrHas(keyTable, ['users'])) { err = ckKey(rows, 'email') if (err !== null) { return Promise.reject(err) } } } //ltdtDiffByKey let ltdtOld = await woItems[keyTable].select() let ltdtNew = rows let r = ltdtDiffByKey(ltdtOld, ltdtNew, keyDetect) // console.log('ltdtDiffByKey r', r) //del if (size(r.del) > 0) { await procOrm(userId, keyTable, 'del', r.del) //須使用procOrm才有辦法自動給予相關欄位 // .catch((err) => { // console.log('woItems[keyTable].del err', err) // }) } //add if (size(r.add) > 0) { await procOrm(userId, keyTable, 'insert', r.add) //須使用procOrm才有辦法自動給予相關欄位 // .catch((err) => { // console.log('woItems[keyTable].insert err', err) // }) } //diff if (size(r.diff) > 0) { await procOrm(userId, keyTable, 'save', r.diff) //須使用procOrm才有辦法自動給予相關欄位 // .catch((err) => { // console.log('woItems[keyTable].save err', err) // }) } return ltdtNew } //updateTargets let updateTargets = async (userId, rows) => { rows = await updateTabItems('targets', userId, rows, 'id') return rows } //updatePemis let updatePemis = async (userId, rows) => { rows = await updateTabItems('pemis', userId, rows, 'name') return rows } //updateGrups let updateGrups = async (userId, rows) => { rows = await updateTabItems('grups', userId, rows, 'name') return rows } //updateUsers let updateUsers = async (userId, rows) => { rows = await updateTabItems('users', userId, rows, 'id') return rows } //checkUser let checkUser = async(user) => { let id = get(user, 'id', '') if (!isestr(id)) { console.log('user', user) console.log('can not get the userId') return Promise.reject(`can not get the userId`) } let email = get(user, 'email', '') if (!isestr(email)) { console.log('user', user) console.log('can not get the email of user') return Promise.reject(`can not get the email of user`) } let name = get(user, 'name', '') if (!isestr(name)) { console.log('user', user) console.log('can not get userName') return Promise.reject(`can not get userName`) } let isAdmin = get(user, 'isAdmin', '') if (isAdmin !== 'y' &amp;&amp; isAdmin !== 'n') { console.log('user', user) console.log('user.isAdmin is not y or n', user.isAdmin) console.log('can not get the role of user') return Promise.reject(`can not get the role of user`) } return true } //getTokenUser let getTokenUser = async(token) => { //基於token查找使用者, 會基於外部getUserByToken以及perm內部users進行查找並比對 //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 await checkUser(userSelf) //須反查perm內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 perm') return Promise.reject(`can not get the user from perm`) } //複寫isAdmin let isAdminSrc = get(userSelf, 'isAdmin', '') let isAdminSelf = get(userFind, 'isAdmin', '') if (isAdminSrc !== isAdminSelf) { userFind.isAdmin = isAdminSelf } // console.log('userFind(isAdmin)', userFind) return userFind } //p let p = { checkToken: async(token) => { //getUserByToken let u = await getUserByToken(token) // console.log('u', u) //checkUser await checkUser(u) return true }, } //getAndVerifyClientUser let getAndVerifyClientUser = async (token, from = '') => { //基於token查找client使用者, 會基於外部getUserByToken以及perm內部users進行查找並比對 //getTokenUser let user = await getTokenUser(token) //verifyClientUser let b = verifyClientUser(user, from) if (ispm(b)) { b = await b } //check if (!b) { console.log('user', user) console.log(`user does not have permission`) return Promise.reject(`user does not have permission`) } return user } //getAndVerifyAppUser let getAndVerifyAppUser = async (token, from = '') => { //基於token查找app使用者, 會基於外部getUserByToken進行查找, 故只要getUserByToken提供使用者即可, 可支援getUserByToken給予針對應用程式所產生之虛擬使用者 //user let user = null if (isestr(token)) { user = getUserByToken(token) if (ispm(user)) { user = await user } } // console.log('user', user) //check if (!iseobj(user)) { console.log(`token`, token) console.log(`can not find the user from token`) return Promise.reject(`can not find the user from token`) } //verifyAppUser let b = verifyAppUser(user, from) if (ispm(b)) { b = await b } //check if (!b) { console.log('user', user) console.log(`user does not have permission`) return Promise.reject(`user does not have permission`) } return user } //parsePayload let parsePayload = async (req) => { //payload let payload = get(req, 'payload') //to obj if (isestr(payload)) { payload = j2o(payload) } //check if (!iseobj(payload)) { console.log('payload', payload) console.log('invalid payload in req') return Promise.reject(`invalid payload in req`) } //from let from = get(payload, 'from', '') //check if (!isestr(from)) { console.log('payload', payload) console.log('invalid from in payload') return Promise.reject(`invalid from in payload`) } //rows let rows = get(payload, 'rows', []) //check if (!isearr(rows)) { console.log('payload', payload) console.log(`invalid rows in payload`) return Promise.reject(`invalid rows in payload`) } //inp let inp = { from, rows, } return inp } //syncAndReplaceTabs let syncAndReplaceTabs = async (userId, inp, keyTable) => { //from let from = get(inp, 'from', '') // console.log('from', from) //check if (!isestr(from)) { console.log('inp', inp) console.log(`invalid from`) return Promise.reject(`invalid from`) } //rows let rows = get(inp, 'rows', []) // console.log(keyTable, rows) //check if (!isearr(rows)) { console.log('inp', inp) console.log('keyTable', keyTable) return Promise.reject(`invalid rows`) } //save from rows = map(rows, (v, k) => { // v.order = k + 1 //order大部分由外部給予, 不能複寫 v.from = from return v }) //ltdtmapping rows = ltdtmapping(rows, ds[keyTable].keys) // console.log('ltdtmapping rows', rows) //delAll from await woItems[keyTable].delAll({ from }) //insert // let r = await woItems[keyTable].insert(rows) let r = await procOrm(userId, keyTable, 'insert', rows) //須使用procOrm才有辦法自動給予相關欄位 // console.log('r', r) return r } //getGenUserByKV let getGenUserByKV = async(keyUser, valueUser) => { //userFind let userFind = await woItems.users.select({ [keyUser]: valueUser, isActive: 'y' }) userFind = get(userFind, 0, null) //check if (!iseobj(userFind)) { return null } return userFind } //getGenUserByUserId let getGenUserByUserId = async(userId) => { //userFind let userFind = await getGenUserByKV('id', userId) //check if (!iseobj(userFind)) { return null } return userFind } //getGenUserAndRulesByUserId let getGenUserAndRulesByUserId = async (userId) => { //userFind let userFind = await getGenUserByUserId(userId) // console.log('userFind', userFind) //grups let grups = await woItems.grups.select() // console.log('grups', grups) //pemis let pemis = await woItems.pemis.select() // console.log('pemis', pemis) //targets let targets = await woItems.targets.select() // console.log('targets', targets) //getUserRules let kur = getUserRules(userFind, grups, pemis, targets) // console.log('getUserRules', kur) //check if (!iseobj(kur)) { console.log('userId', userId) console.log(`can not get rules of user`) return Promise.reject(`can not get rules of user`) } //grupsNames let grupsNames = map(get(kur, 'grups', []), 'name') //kur.grups僅會提供isActive='y', 故grupsNames為有效權限群組名稱 grupsNames = join(grupsNames, ';') return { user: { ...userFind, grupsNames, }, // grups: get(kur, 'grups', []), rules: get(kur, 'rules', []), } } //pathStaticFiles let pathStaticFiles = 'dist' let npmPathStaticFiles = './node_modules/w-web-perm/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, '/mperm/', '{sfd}/') //方法同genEntry c = replace(c, '{sfd}', subfolder) c = replace(c, '{urlRedirect}', urlRedirect) c = replace(c, '{language}', language) fs.writeFileSync(fpEntryOut, c, 'utf8') } catch (err) { console.log(err) console.log(`can not generate ${fnEntryOut}`) } //apis let apis = [ { method: 'GET', path: '/api/getUserByToken', //未登入主頁時需先檢測token, getUserByToken為w-ui-loginout預設值, 若要更改兩邊須同時修改 handler: async function (req, res) { // console.log('getUserByToken', req) async function core() { //提供對象為browser使用者, 須先檢測token是否有效, 確認後回傳該使用者之資訊物件 //token let token = get(req, 'query.token', '') // console.log('token', token) //check if (!isestr(token)) { console.log('req.query', get(req, 'query')) console.log('token', token) console.log('[API]getUserByToken/check token: invalid token') console.log(`token does not have permission`) return Promise.reject(`token does not have permission`) } //getAndVerifyClientUser let user = await getAndVerifyClientUser(token, 'getUserByToken') // console.log('user', user) //check if (!iseobj(user)) { console.log('token', token) console.log('[API]getUserByToken/check user: invalid user') console.log(`token does not have permission`) return Promise.reject(`token does not have permission`) } return user } //pm2resolve core let r = await pm2resolve(core)() //w-ui-loginout接收已預設格式用pm2resolve轉過, 須另提取state進行判斷 if (isErr(r.msg)) { r.msg = r.msg.message } // console.log('getUserByToken', r) return r }, }, { method: 'GET', path: '/api/getPerm', handler: async function (req, res) { // console.log('getPerm', req) async function core() { //提供對象為node與browser端, 須為client使用者, 須先檢測token是否有效, 再依照token取得使用者資訊物件, 再由其userId查詢回傳該使用者之權限資訊物件 //token let token = get(req, 'query.token', '') // console.log('token', token) //check if (!isestr(token)) { console.log('req.query', get(req, 'query')) console.log('token', token) console.log('[API]getPerm/check token: invalid token') console.log(`token does not have permission`) return Promise.reject(`token does not have permission`) } //getAndVerifyClientUser, 發起token的所屬使用者, 驗證僅對client使用者, 不得使用app使用者 let userSelf = await getAndVerifyClientUser(token, 'getPerm') // console.log('userSelf', userSelf) //check if (!iseobj(userSelf)) { console.log('token', token) console.log('[API]getPerm/check userSelf: invalid userSelf') console.log(`token does not have permission`) return Promise.reject(`token does not have permission`) } //userIdSelf, client使用者的userId let userIdSelf = get(userSelf, 'id', '') // console.log('userIdSelf', userIdSelf) //check if (!isestr(userIdSelf)) { console.log('token', token) console.log('userSelf', userSelf) console.log('[API]getPerm/check userIdSelf: invalid userIdSelf') console.log(`token does not have permission`) return Promise.reject(`token does not have permission`) } //getGenUserAndRulesByUserId, 查找到的client使用者與權限 let userWithRulesSelf = await getGenUserAndRulesByUserId(userIdSelf) // console.log('getGenUserAndRulesByUserId', r) //check if (!iseobj(userWithRulesSelf)) { console.log('token', token) console.log('userSelf', userSelf) console.log('userIdSelf', userIdSelf) console.log('[API]getPerm/check userWithRulesSelf: invalid userWithRulesSelf') console.log(`token does not have permission`) return Promise.reject(`token does not have permission`) } return userWithRulesSelf } //pm2resolve core let r = await pm2resolve(core)() if (isErr(r.msg)) { r.msg = r.msg.message } // console.log('getPerm r', r) return r }, }, { method: 'GET', path: '/api/getPermUserInfor', handler: async function (req, res) { // console.log('getPermUserInfor', req) async function core() { //提供對象為node端, 須為app使用者, 須先檢測token是否有效, 再由其userId查詢回傳該使用者權限資訊物件 //tokenSelf let tokenSelf = get(req, 'query.token', '') // console.log('token', token) //check if (!isestr(tokenSelf)) { console.log('req.query', get(req, 'query')) console.log('[API]getPermUserInfor/check tokenSelf: invalid tokenSelf') console.log(`token does not have permission`) return Promise.reject(`token does not have permission`) } //getAndVerifyAppUser, 發起token的所屬使用者, 驗證須為app使用者 let userSelf = await getAndVerifyAppUser(tokenSelf, 'getPermUserInfor') // console.log('userSelf', userSelf) //check if (!iseobj(userSelf)) { console.log('req.query', get(req, 'query')) console.log('tokenSelf', tokenSelf) console.log('[API]getPermUserInfor/check userSelf: invalid userSelf') console.log(`token does not have permission`) return Promise.reject(`token does not have permission`) } //userIdFind, 欲查找使用者的userId let userIdFind = get(req, 'query.userId', '') // console.log('userIdFind', userIdFind) //check if (!isestr(userIdFind)) { console.log('req.query', get(req, 'query')) console.log('tokenSelf', tokenSelf) console.log('[API]getPermUserInfor/check userIdFind: invalid userIdFind') console.log(`token does not have permission`) return Promise.reject(`token does not have permission`) } //getGenUserAndRulesByUserId, 查找到的使用者與權限 let userWithRulesFind = await getGenUserAndRulesByUserId(userIdFind) // console.log('getGenUserAndRulesByUserId', userWithRulesFind) //check if (!iseobj(userWithRulesFind)) { console.log('userIdFind', userIdFind) console.log('[API]getPermUserInfor/check userWithRulesFind: invalid userWithRulesFind') console.log(`userId does not have permrules`) return Promise.reject(`userId does not have permrules`) } return userWithRulesFind } //pm2resolve core let r = await pm2resolve(core)() //w-ui-loginout接收已預設格式用pm2resolve轉過, 須另提取state進行判斷 if (isErr(r.msg)) { r.msg = r.msg.message } // console.log('getPermUserInfor', r) return r }, }, { method: 'POST', path: '/syncAndReplaceTabs', handler: async function (req, res) { // console.log('syncAndReplaceTabs', req) // console.log('syncAndReplaceTabs payload', req.payload) async function core() { //提供對象為node使用者, 須為系統管理者, 須先檢測token是否有效, 再進行數據變更 //token let token = get(req, 'query.token', '') //check if (!isestr(token)) { console.log('req.query', get(req, 'query')) console.log('token', token) console.log('[API]syncAndReplaceTabs/check token: invalid token') console.log(`token does not have permission`) return Promise.reject(`token does not have permission`) } //keyTable let keyTable = get(req, 'query.keyTable', '') //check if (!isestr(keyTable)) { console.log('req.query', get(req, 'query')) console.log('keyTable', keyTable) console.log('[API]syncAndReplaceTabs/check keyTable: invalid keyTable') console.log(`token does not have permission`) return Promise.reject(`token does not have permission`) } //check keyTable let allowedTables = ['targets', 'pemis', 'grups', 'users'] if (!allowedTables.includes(keyTable)) { console.log('[API]syncAndReplaceTabs/check keyTable: unexpected keyTable', keyTable) return Promise.reject(`invalid keyTable: ${keyTable}`) } //getAndVerifyAppUser let user = await getAndVerifyAppUser(token, 'syncAndReplaceTabs') //check user if (!iseobj(user)) { console.log('token', token) console.log('[API]syncAndReplaceTabs/check user: invalid user') console.log(`token does not have permission`) return Promise.reject(`token does not have permission`) } //userId let userId = get(user, 'id', '') //check userId if (!isestr(userId)) { console.log('token', token) console.log('user', user) console.log('[API]syncAndReplaceTabs/check userId: invalid userId') console.log(`token does not have permission`) return Promise.reject(`token does not have permission`) } //parsePayload let inp = await parsePayload(req) //syncAndReplaceTabs let r = await syncAndReplaceTabs(userId, inp, keyTable) return r } //pm2resolve core let r = await pm2resolve(core)() if (isErr(r.msg)) { r.msg = r.msg.message } // console.log('syncAndReplaceTabs', r) return r }, }, ] //tableNamesExec, tableNamesSync let tableNamesExec = keys(ds) // let tableNamesSync = filter(tableNamesExec, (v) => { // return strright(v, 5) !== 'Items'//不同步數據 // }) let tableNamesSync = tableNamesExec //WServHapiServer instWServHapiServer = new WServHapiServer({ port: opt.serverPort, pathStaticFiles, apiName: 'api', apis, tokenType: 'Bearer', verifyConn: async ({ apiType, authorization, query, headers, req }) => { // console.log('verifyConn', `apiType[${apiType}]`, `authorization[${authorization}]`) //token let token = strdelleft(authorization, 7) //刪除Bearer // console.log('token', token) //check if (!isestr(token)) { console.log('apiType', apiType) console.log('authorization', authorization) console.log('invalid token') return false } //checkToken let b = await p.checkToken(token) // console.log('b', b) return b }, getUserIdByToken: async (token) => { //可使用async或sync函數 // console.log('getUserIdByToken', token) let user = await getUserByToken(token) let userId = get(user, 'id', '') if (!isestr(userId)) { console.log('token', token) console.log('userId', userId) return Promise.reject(`can not find user.id`) } return userId }, corsOrigins: ['*'], useDbOrm: true, kpOrm: woItems, operOrm: procOrm, //procOrm的輸入為: userId, tableName, methodName, input tableNamesExec, methodsExec: ['select', 'insert', 'save', 'del', 'delAll'], //mix需於procOrm內註冊以提供 tableNamesSync, kpFunExt: { //接收參數第1個為userId, 之後才是前端給予參數 getWebInfor, // getTargetsList, // getPemisList, // getGrupsList, // getUsersList, updateTargets, updatePemis, updateGrups, updateUsers, }, fnTableTags: 'tableTags-web-perm.json', }) return instWServHapiServer } export default WWebPerm </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 Thu Dec 18 2025 22:25:20 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>