@gdjiami/jslib
Version:
Jiami FrontEnd helpers and Services
262 lines (261 loc) • 10.9 kB
JavaScript
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 };