2 lines
11 KiB
JavaScript
2 lines
11 KiB
JavaScript
"use strict";var e,n=(e=require("crypto"))&&"object"==typeof e&&"default"in e?e.default:e;const i={TOKEN_EXPIRED:"uni-id-token-expired",CHECK_TOKEN_FAILED:"uni-id-check-token-failed",PARAM_REQUIRED:"uni-id-param-required",ACCOUNT_EXISTS:"uni-id-account-exists",ACCOUNT_NOT_EXISTS:"uni-id-account-not-exists",ACCOUNT_CONFLICT:"uni-id-account-conflict",ACCOUNT_BANNED:"uni-id-account-banned",ACCOUNT_AUDITING:"uni-id-account-auditing",ACCOUNT_AUDIT_FAILED:"uni-id-account-audit-failed",ACCOUNT_CLOSED:"uni-id-account-closed"};function t(e){return!!e&&("object"==typeof e||"function"==typeof e)&&"function"==typeof e.then}function r(e){if(!e)return;const n=e.match(/^(\d+).(\d+).(\d+)/);return n?n.slice(1,4).map(e=>parseInt(e)):void 0}function o(e,n){const i=r(e),t=r(n);return i?t?function(e,n){const i=Math.max(e.length,n.length);for(let t=0;t<i;t++){const i=e[t],r=n[t];if(i>r)return 1;if(i<r)return-1}return 0}(i,t):1:t?-1:0}const s={"uni-id-token-expired":30203,"uni-id-check-token-failed":30202};function c(e){const{errCode:n,errMsgValue:i}=e;e.errMsg=this._t(n,i),n in s&&(e.code=s[n]),delete e.errMsgValue}function a(e){return"object"===(t=e,Object.prototype.toString.call(t).slice(8,-1).toLowerCase())&&e.errCode&&(n=e.errCode,Object.values(i).includes(n))&&!!e.errCode;var n,t}let u={"zh-Hans":{"uni-id-token-expired":"登录状态失效,token已过期","uni-id-check-token-failed":"token校验未通过","uni-id-param-required":"缺少参数: {param}","uni-id-account-exists":"此账号已注册","uni-id-account-not-exists":"此账号未注册","uni-id-account-conflict":"用户账号冲突","uni-id-account-banned":"从账号已封禁","uni-id-account-auditing":"此账号正在审核中","uni-id-account-audit-failed":"此账号审核失败","uni-id-account-closed":"此账号已注销"},en:{"uni-id-token-expired":"The login status is invalid, token has expired","uni-id-check-token-failed":"Check token failed","uni-id-param-required":"Parameter required: {param}","uni-id-account-exists":"Account exists","uni-id-account-not-exists":"Account does not exists","uni-id-account-conflict":"User account conflict","uni-id-account-banned":"Account has been banned","uni-id-account-auditing":"Account audit in progress","uni-id-account-audit-failed":"Account audit failed","uni-id-account-closed":"Account has been closed"}};try{const e=require.resolve("uni-config-center/uni-id/lang/index.js");u=function(e,n){const i=Object.keys(e);i.push(...Object.keys(n));const t={};for(let r=0;r<i.length;r++){const o=i[r];t[o]=Object.assign({},e[o],n[o])}return t}(u,require(e))}catch(e){}var d=u;function l(e){return e.replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")}function h(e){return JSON.parse((n=function(e){var n=4-(e=e.toString()).length%4;if(4!==n)for(var i=0;i<n;++i)e+="=";return e.replace(/-/g,"+").replace(/_/g,"/")}(e),Buffer.from(n,"base64").toString("utf-8")));var n}function f(e){return l((n=JSON.stringify(e),Buffer.from(n,"utf-8").toString("base64")));var n}function p(e,i){return l(n.createHmac("sha256",i).update(e).digest("base64"))}const k=function(e,n){if("string"!=typeof e)throw new Error("Invalid token");const i=e.split(".");if(3!==i.length)throw new Error("Invalid token");const[t,r,o]=i;if(p(t+"."+r,n)!==o)throw new Error("Invalid token");const s=h(t);if("HS256"!==s.alg||"JWT"!==s.typ)throw new Error("Invalid token");const c=h(r);if(1e3*c.exp<Date.now()){const e=new Error("Token expired");throw e.name="TokenExpiredError",e}return c},g=function(e,n,i={}){const{expiresIn:t}=i;if(!t)throw new Error("expiresIn is required");const r=parseInt(Date.now()/1e3),o={...e,iat:r,exp:r+i.expiresIn},s=f({alg:"HS256",typ:"JWT"})+"."+f(o);return s+"."+p(s,n)},_=uniCloud.database(),I=_.command,C=_.collection("uni-id-users"),T=_.collection("uni-id-roles");class m{constructor({uniId:e}={}){this.uid=null,this.userRecord=null,this.userPermission=null,this.oldToken=null,this.oldTokenPayload=null,this.uniId=e,this.config=this.uniId._getConfig(),this.clientInfo=this.uniId._clientInfo,this.checkConfig()}checkConfig(){const{tokenExpiresIn:e,tokenExpiresThreshold:n}=this.config;if(n>=e)throw new Error("Config error, tokenExpiresThreshold should be less than tokenExpiresIn");n>e/2&&console.warn(`Please check whether the tokenExpiresThreshold configuration is set too large, tokenExpiresThreshold: ${n}, tokenExpiresIn: ${e}`)}get customToken(){return this.uniId.interceptorMap.get("customToken")}isTokenInDb(e){return o(e,"1.0.10")>=0}async getUserRecord(){if(this.userRecord)return this.userRecord;const e=await C.doc(this.uid).get();if(this.userRecord=e.data[0],!this.userRecord)throw{errCode:i.ACCOUNT_NOT_EXISTS};switch(this.userRecord.status){case void 0:case 0:break;case 1:throw{errCode:i.ACCOUNT_BANNED};case 2:throw{errCode:i.ACCOUNT_AUDITING};case 3:throw{errCode:i.ACCOUNT_AUDIT_FAILED};case 4:throw{errCode:i.ACCOUNT_CLOSED}}if(this.oldTokenPayload){if(this.isTokenInDb(this.oldTokenPayload.uniIdVersion)){if(-1===(this.userRecord.token||[]).indexOf(this.oldToken))throw{errCode:i.CHECK_TOKEN_FAILED}}if(this.userRecord.valid_token_date&&this.userRecord.valid_token_date>1e3*this.oldTokenPayload.iat)throw{errCode:i.TOKEN_EXPIRED}}return this.userRecord}async updateUserRecord(e){await C.doc(this.uid).update(e)}async getUserPermission(){if(this.userPermission)return this.userPermission;const e=(await this.getUserRecord()).role||[];if(0===e.length)return this.userPermission={role:[],permission:[]},this.userPermission;if(e.includes("admin"))return this.userPermission={role:e,permission:[]},this.userPermission;const n=await T.where({role_id:I.in(e)}).get(),i=(t=n.data.reduce((e,n)=>(n.permission&&e.push(...n.permission),e),[]),Array.from(new Set(t)));var t;return this.userPermission={role:e,permission:i},this.userPermission}async _createToken({uid:e,role:n,permission:t}={}){if(!n||!t){const e=await this.getUserPermission();n=e.role,t=e.permission}let r={uid:e,role:n,permission:t};if(this.uniId.interceptorMap.has("customToken")){const i=this.uniId.interceptorMap.get("customToken");if("function"!=typeof i)throw new Error("Invalid custom token file");r=await i({uid:e,role:n,permission:t})}const o=Date.now(),{tokenSecret:s,tokenExpiresIn:c,maxTokenLength:a=10}=this.config,u=g({...r,uniIdVersion:"1.0.19"},s,{expiresIn:c}),d=await this.getUserRecord(),l=(d.token||[]).filter(e=>{try{const n=this._checkToken(e);if(d.valid_token_date&&d.valid_token_date>1e3*n.iat)return!1}catch(e){if(e.errCode===i.TOKEN_EXPIRED)return!1}return!0});return l.push(u),l.length>a&&l.splice(0,l.length-a),await this.updateUserRecord({last_login_ip:this.clientInfo.clientIP,last_login_date:o,token:l}),{token:u,tokenExpired:o+1e3*c}}async createToken({uid:e,role:n,permission:t}={}){if(!e)throw{errCode:i.PARAM_REQUIRED,errMsgValue:{param:"uid"}};this.uid=e;const{token:r,tokenExpired:o}=await this._createToken({uid:e,role:n,permission:t});return{errCode:0,token:r,tokenExpired:o}}async refreshToken({token:e}={}){if(!e)throw{errCode:i.PARAM_REQUIRED,errMsgValue:{param:"token"}};this.oldToken=e;const n=this._checkToken(e);this.uid=n.uid,this.oldTokenPayload=n;const{uid:t}=n,{role:r,permission:o}=await this.getUserPermission(),{token:s,tokenExpired:c}=await this._createToken({uid:t,role:r,permission:o});return{errCode:0,token:s,tokenExpired:c}}_checkToken(e){const{tokenSecret:n}=this.config;let t;try{t=k(e,n)}catch(e){if("TokenExpiredError"===e.name)throw{errCode:i.TOKEN_EXPIRED};throw{errCode:i.CHECK_TOKEN_FAILED}}return t}async checkToken(e,{autoRefresh:n=!0}={}){if(!e)throw{errCode:i.CHECK_TOKEN_FAILED};this.oldToken=e;const t=this._checkToken(e);this.uid=t.uid,this.oldTokenPayload=t;const{tokenExpiresThreshold:r}=this.config,{uid:o,role:s,permission:c}=t,a={role:s,permission:c};if(!s&&!c){const{role:e,permission:n}=await this.getUserPermission();a.role=e,a.permission=n}if(!r||!n){const e={code:0,errCode:0,...t,...a};return delete e.uniIdVersion,e}const u=Date.now();let d={};1e3*t.exp-u<1e3*r&&(d=await this._createToken({uid:o}));const l={code:0,errCode:0,...t,...a,...d};return delete l.uniIdVersion,l}}var E=Object.freeze({__proto__:null,checkToken:async function(e,{autoRefresh:n=!0}={}){return new m({uniId:this}).checkToken(e,{autoRefresh:n})},createToken:async function({uid:e,role:n,permission:i}={}){return new m({uniId:this}).createToken({uid:e,role:n,permission:i})},refreshToken:async function({token:e}={}){return new m({uniId:this}).refreshToken({token:e})}});const w=require("uni-config-center")({pluginId:"uni-id"});class x{constructor({context:e,clientInfo:n,config:i}={}){this._clientInfo=e?function(e){return{appId:e.APPID,platform:e.PLATFORM,locale:e.LOCALE,clientIP:e.CLIENTIP,deviceId:e.DEVICEID}}(e):n,this._config=i,this.config=this._getOriginConfig(),this.interceptorMap=new Map,w.hasFile("custom-token.js")&&this.setInterceptor("customToken",require(w.resolve("custom-token.js")));this._i18n=uniCloud.initI18n({locale:this._clientInfo.locale,fallbackLocale:"zh-Hans",messages:JSON.parse(JSON.stringify(d))}),d[this._i18n.locale]||this._i18n.setLocale("zh-Hans")}setInterceptor(e,n){this.interceptorMap.set(e,n)}_t(...e){return this._i18n.t(...e)}_parseOriginConfig(e){return Array.isArray(e)?e:e[0]?Object.values(e):e}_getOriginConfig(){if(this._config)return this._config;if(w.hasFile("config.json")){let e;try{e=w.config()}catch(e){throw new Error("Invalid uni-id config file\n"+e.message)}return this._parseOriginConfig(e)}try{return this._parseOriginConfig(require("uni-id/config.json"))}catch(e){throw new Error("Invalid uni-id config file")}}_getAppConfig(){const e=this._getOriginConfig();return Array.isArray(e)?e.find(e=>e.dcloudAppid===this._clientInfo.appId)||e.find(e=>e.isDefaultConfig):e}_getPlatformConfig(){const e=this._getAppConfig();if(!e)throw new Error(`Config for current app (${this._clientInfo.appId}) was not found, please check your config file or client appId`);let n;switch(["app-plus","app-android","app-ios"].indexOf(this._clientInfo.platform)>-1&&(this._clientInfo.platform="app"),"h5"===this._clientInfo.platform&&(this._clientInfo.platform="web"),this._clientInfo.platform){case"web":n="h5";break;case"app":n="app-plus"}const i=[{tokenExpiresIn:7200,tokenExpiresThreshold:1200,passwordErrorLimit:6,passwordErrorRetryTime:3600},e];n&&e[n]&&i.push(e[n]),i.push(e[this._clientInfo.platform]);const t=Object.assign(...i);return["tokenSecret","tokenExpiresIn"].forEach(e=>{if(!t||!t[e])throw new Error(`Config parameter missing, ${e} is required, please check your config file uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json`)}),t}_getConfig(){return this._getPlatformConfig()}}for(const e in E)x.prototype[e]=E[e];function y(e){const n=new x(e);return new Proxy(n,{get(e,n){if(n in e&&0!==n.indexOf("_")){if("function"==typeof e[n])return(i=e[n],function(){let e;try{e=i.apply(this,arguments)}catch(e){if(a(e))return c.call(this,e),e;throw e}return t(e)?e.then(e=>(a(e)&&c.call(this,e),e),e=>{if(a(e))return c.call(this,e),e;throw e}):(a(e)&&c.call(this,e),e)}).bind(e);if("context"!==n&&"config"!==n)return e[n]}var i}})}x.prototype.createInstance=y;const O={createInstance:y};module.exports=O;
|