UNPKG

@gdjiami/jslib

Version:

Jiami FrontEnd helpers and Services

262 lines (261 loc) 10.9 kB
import * as tslib_1 from "tslib"; /** * 通用的Token鉴权机制服务 */ import { getSearch } from './http'; import { EventEmitter } from './EventEmitter'; export var SMS_CLIENT_TYPE = ['qxSMS', 'qxEEMS', 'qxEMS', 'qxCMS']; export var TOKEN_HEADER = 'X-Access-Token'; /** * 鉴权类型 */ export var GRANT_TYPE; (function (GRANT_TYPE) { GRANT_TYPE["Auth"] = "authorization_code"; GRANT_TYPE["Refresh"] = "refresh_token"; })(GRANT_TYPE || (GRANT_TYPE = {})); var TOKEN_CACHE_KEY = '__auth__'; var REFRESH_DURATION = 10 * 1000; /** * 基于Token的鉴权服务 * ## events * info-updated */ var TokenAuthService = /** @class */ (function (_super) { tslib_1.__extends(TokenAuthService, _super); function TokenAuthService(config) { var _this = _super.call(this) || this; _this.refreshCallbacks = []; _this.config = config; _this.getUserInfo(); return _this; } Object.defineProperty(TokenAuthService.prototype, "storage", { get: function () { return (this.config && this.config.storage) || window.sessionStorage; }, enumerable: true, configurable: true }); TokenAuthService.prototype.logout = function () { this.clean(); }; TokenAuthService.prototype.clean = function () { // @ts-ignore this.info = undefined; this.storage.removeItem(TOKEN_CACHE_KEY); }; /** * 更新鉴权信息 */ TokenAuthService.prototype.saveAuthInfo = function (info) { this.info = info; this.storage.setItem(TOKEN_CACHE_KEY, JSON.stringify(info)); this.infoUpdated(); }; /** * 通过用户名密码鉴权 */ TokenAuthService.prototype.authByPassword = function (params) { return tslib_1.__awaiter(this, void 0, void 0, function () { var info, res, err_1; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (this.config.getTokenByPassword == null) { throw new Error('TokenAuthService: getTokenByPassword 未实现'); } info = this.storage.getItem(TOKEN_CACHE_KEY); if (info != null) { this.info = JSON.parse(info); if (this.config.onAuthSuccess) { this.config.onAuthSuccess(this.info); } return [2 /*return*/]; } _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, this.config.getTokenByPassword(params)]; case 2: res = _a.sent(); this.saveAuthInfo(res); this.handleAuthSuccess(); return [3 /*break*/, 4]; case 3: err_1 = _a.sent(); if (this.config.onAuthFailed) { this.config.onAuthFailed(err_1); } throw err_1; case 4: return [2 /*return*/]; } }); }); }; /** * token 鉴权 */ TokenAuthService.prototype.auth = function (overrideParams) { return tslib_1.__awaiter(this, void 0, void 0, function () { var info, params, payload, res, err_2; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (this.config.getToken == null) { throw new Error('TokenAuthService: getToken 未实现'); } info = this.storage.getItem(TOKEN_CACHE_KEY); if (info != null) { this.info = JSON.parse(info); if (this.config.onAuthSuccess) { this.config.onAuthSuccess(this.info); } return [2 /*return*/]; } _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); params = getSearch(window.location.search); if ('from' in params) { // 直接登录 if (params.accessToken == null) { throw new Error("\u9274\u6743\u5931\u8D25(from=" + params.from + ")\uFF0CaccessToken\u4E3Anull"); } this.saveAuthInfo(params); this.handleAuthSuccess(); return [2 /*return*/]; } if (params.code == null) { throw new Error('鉴权失败,code为null'); } payload = tslib_1.__assign({ code: params.code, corpId: params.corp_id || '', clientId: this.config.clientId, grantType: GRANT_TYPE.Auth }, (overrideParams || {})); return [4 /*yield*/, this.config.getToken(payload)]; case 2: res = _a.sent(); this.saveAuthInfo(res); this.handleAuthSuccess(); return [3 /*break*/, 4]; case 3: err_2 = _a.sent(); if (this.config.onAuthFailed) { this.config.onAuthFailed(err_2); } throw err_2; case 4: return [2 /*return*/]; } }); }); }; /** * 刷新token * 这个方法可能会被调用多次,所以要将它们加入队列,以便后续重试 */ TokenAuthService.prototype.refresh = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var resRef_1, rejRef_1, promise, params, res, now, list, err_3, list; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (this.info == null) { throw new Error('必须在鉴权之后才能刷新Token'); } if (!this.refreshing) return [3 /*break*/, 2]; promise = new Promise(function (res, rej) { resRef_1 = res; rejRef_1 = rej; }); this.refreshCallbacks.push(function (err) { return (err != null ? rejRef_1(err) : resRef_1()); }); return [4 /*yield*/, promise]; case 1: _a.sent(); return [2 /*return*/]; case 2: _a.trys.push([2, 4, 5, 6]); params = { refreshToken: this.info.refreshToken, grantType: GRANT_TYPE.Refresh, }; return [4 /*yield*/, this.config.refreshToken(params)]; case 3: res = _a.sent(); now = Date.now(); if (this.lastRefreshTime != null && now - this.lastRefreshTime < REFRESH_DURATION) { throw new Error(this.config.refreshErrorMessage || '会话失效'); } this.lastRefreshTime = now; this.saveAuthInfo(tslib_1.__assign({}, this.info, res)); if (this.refreshCallbacks.length) { list = this.refreshCallbacks; this.refreshCallbacks = []; list.forEach(function (i) { return i(); }); } return [3 /*break*/, 6]; case 4: err_3 = _a.sent(); if (this.refreshCallbacks.length) { list = this.refreshCallbacks; this.refreshCallbacks = []; list.forEach(function (i) { return i(err_3); }); } if (this.config.onRefreshFailed) { this.config.onRefreshFailed(err_3); } // 清理鉴权信息 this.clean(); throw err_3; case 5: this.refreshing = false; return [7 /*endfinally*/]; case 6: return [2 /*return*/]; } }); }); }; TokenAuthService.prototype.isAdmin = function () { return SMS_CLIENT_TYPE.indexOf(this.info.clientType) !== -1; }; /** * 获取token */ TokenAuthService.prototype.getToken = function () { return this.info && this.info.accessToken; }; /** * 获取用户信息 */ TokenAuthService.prototype.getUserInfo = function () { if (this.info) { return this.info; } var info = this.storage.getItem(TOKEN_CACHE_KEY); if (info != null) { this.info = JSON.parse(info); } return this.info; }; TokenAuthService.prototype.infoUpdated = function () { var _this = this; this.emit(TokenAuthService.INFO_UPDATED, this.info); var deadline = this.info.deadline; if (deadline == null || this.config.refreshToken == null) { return; } var delta = deadline - Date.now(); if (delta > 0) { window.clearTimeout(this.refreshTimer); this.refreshTimer = window.setTimeout(function () { _this.refresh(); }, Math.floor(delta * 0.7)); } }; TokenAuthService.prototype.handleAuthSuccess = function () { if (this.config.onAuthSuccess) { this.config.onAuthSuccess(this.info); } }; TokenAuthService.INFO_UPDATED = 'info-updated'; return TokenAuthService; }(EventEmitter)); export { TokenAuthService };