@mamba-le/auth
Version:
508 lines (437 loc) • 12.8 kB
JavaScript
/**
* @description 认证模块
* @version 0.3.7
* @author lengyingxin <lengyingxin8966@gmail.com> (https://github.com/LengYXin)
*/
import _isEqual from 'lodash/isEqual';
import _assign from 'lodash/assign';
import _map from 'lodash/map';
import _compact from 'lodash/compact';
import _head from 'lodash/head';
import _pick from 'lodash/pick';
import _merge from 'lodash/merge';
import _concat from 'lodash/concat';
import _eq from 'lodash/eq';
import { __awaiter, __generator, __decorate } from 'tslib';
import dayjs from 'dayjs';
import jsCookie from 'js-cookie';
import jwtDecode from 'jwt-decode';
import { BindAll } from 'lodash-decorators';
import { observable, computed, action } from 'mobx';
import { persist } from 'mobx-persist';
import { Subject, lastValueFrom } from 'rxjs';
import { AuthOptions } from './options';
var AuthController =
/** @class */
function () {
function AuthController(options) {
if (options === void 0) {
options = {};
}
/**
* 持久化初始化完成 Subject
* @type {Promise<any>}
* @memberof ControllerUser
*/
this.HydrateSubject = new Subject();
this.options = {
StorageKey: 'mamba-auth',
CookieKey: ['mamba-auth'],
CookieDomain: ['.lenovo.com.cn', '.lenovo.com'],
TokenType: 'JWT'
};
/**
* AccessToken
* @protected
* @memberof AuthController
*/
this._AccessToken = undefined;
/**
* 最后一次更新 值 HydrateisStopped 未完成前 存储 用于对比变化 default 表示默认无值
* @protected
* @memberof AuthController
*/
this.lastValue = 'default';
this.resetConfig(options);
this.createHydrate();
}
Object.defineProperty(AuthController.prototype, "HydrateAsync", {
/**
* 持久化初始化完成 Promise
* @type {Promise<any>}
* @memberof ControllerUser
*/
get: function get() {
return lastValueFrom(this.HydrateSubject, {
defaultValue: undefined
});
},
enumerable: false,
configurable: true
});
Object.defineProperty(AuthController.prototype, "HydrateisStopped", {
/**
* 异步 HydrateSubject 已经完成
* @readonly
* @memberof PortalAuthController
*/
get: function get() {
return this.HydrateSubject.isStopped;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AuthController.prototype, "JsCookie", {
get: function get() {
return jsCookie;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AuthController.prototype, "JWTDecode", {
get: function get() {
return jwtDecode;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AuthController.prototype, "IsJWT", {
get: function get() {
return _eq(this.options.TokenType, 'JWT');
},
enumerable: false,
configurable: true
});
Object.defineProperty(AuthController.prototype, "StorageKey", {
/**
* 存储 key
* @readonly
* @memberof AuthController
*/
get: function get() {
return "_Auth_" + this.options.StorageKey;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AuthController.prototype, "CookieKey", {
/**
* CookieKey
* @readonly
* @memberof AuthController
*/
get: function get() {
if (AuthOptions.browser) {
return _concat([], this.options.CookieKey);
}
return [];
},
enumerable: false,
configurable: true
});
Object.defineProperty(AuthController.prototype, "CookieDomain", {
/**
* Cookie 站点信息
* @readonly
* @memberof AuthController
*/
get: function get() {
if (AuthOptions.browser) {
return _concat(["." + window.location.hostname], this.options.CookieDomain);
}
return [];
},
enumerable: false,
configurable: true
});
Object.defineProperty(AuthController.prototype, "AllCookieKeys", {
/**
* 所有的 Cookie
* @readonly
* @memberof AuthController
*/
get: function get() {
if (AuthOptions.browser) {
try {
var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
for (var nIdx = 0; nIdx < aKeys.length; nIdx++) {
aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]);
}
return aKeys;
} catch (error) {
return [];
}
}
},
enumerable: false,
configurable: true
});
/**
* 重置配置
* @param options
*/
AuthController.prototype.resetConfig = function (options) {
if (options === void 0) {
options = {};
}
try {
AuthOptions.writeCheck();
_merge(this.options, _pick(options, ['StorageKey', 'CookieKey', 'CookieDomain']));
} catch (error) {
AuthOptions.log('error', error);
}
};
Object.defineProperty(AuthController.prototype, "AccessToken", {
/**
* 提供外部访问的 AccessToken
* @readonly
* @memberof AuthController
*/
get: function get() {
var AccessToken = this.getAccessToken();
var Decoded = this.getDecoded(AccessToken);
if (Decoded && Decoded.overdue) {
AuthOptions.log('Warning 已过期 不返回', Decoded, this);
return undefined;
}
return AccessToken;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AuthController.prototype, "JwtDecoded", {
/**
* 解析后的 JWT
* @readonly
* @type {JWTDecoded}
* @memberof AuthController
*/
get: function get() {
return this.getDecoded();
},
enumerable: false,
configurable: true
});
Object.defineProperty(AuthController.prototype, "CookieAccessToken", {
/**
* Cookie 中存储的值
* @readonly
* @private
* @memberof AuthController
*/
get: function get() {
// 微信小程序中不使用 cookie
if (AuthOptions.isWeappBowser) {
return undefined;
}
if (AuthOptions.browser) {
try {
return _head(_compact(_map(this.CookieKey, function (key) {
return jsCookie.get(key);
})));
} catch (error) {
AuthOptions.log('error', this, error);
return undefined;
}
}
},
enumerable: false,
configurable: true
});
/**
* 获取 JWT 解析后数据
* @returns
*/
AuthController.prototype.getDecoded = function (AccessToken) {
if (AccessToken === void 0) {
AccessToken = this.getAccessToken();
}
try {
if (!AccessToken || !this.IsJWT) {
return {};
}
var Decode = jwtDecode(AccessToken);
return _assign(Decode, {
expFormat: dayjs(Decode.exp * 1000).format('YYYY-MM-DD HH:mm:ss'),
iatFormat: dayjs(Decode.iat * 1000).format('YYYY-MM-DD HH:mm:ss'),
// 是否过期
overdue: dayjs(Decode.exp * 1000).isBefore(dayjs())
});
} catch (error) {
// AuthOptions.log('error', 'Decoded', this, error)
return {
overdue: true
};
}
};
/**
* 获取 AccessToken
* @returns
*/
AuthController.prototype.getAccessToken = function () {
return _head(_compact([this.CookieAccessToken, this._AccessToken]));
};
/**
* 保存 Token
* @param _AccessToken
* @returns
*/
AuthController.prototype.onSaveAccessToken = function (_AccessToken, setCookie) {
var _this = this;
if (_AccessToken === void 0) {
_AccessToken = undefined;
}
if (setCookie === void 0) {
setCookie = false;
}
try {
AuthOptions.writeCheck();
AuthOptions.trace('Save AccessToken', _AccessToken, setCookie);
if (_AccessToken && this.IsJWT) {
var Decoded = this.getDecoded(_AccessToken);
AuthOptions.log('AccessToken Decoded', Decoded); // if (!Decoded.aud) {
// throw 'AccessToken 非法'
// }
if (Decoded.overdue) {
throw 'AccessToken 已过期';
}
}
if (_AccessToken && _eq(this.getAccessToken(), _AccessToken)) {
throw 'AccessToken 已存在 【 Cookie 存在将不在写入 】';
}
if (!this.HydrateisStopped) {
this.lastValue = _AccessToken;
}
this._AccessToken = _AccessToken;
if (setCookie && AuthOptions.browser) {
_map(this.CookieDomain, function (domain) {
_map(_this.CookieKey, function (key) {
AuthOptions.log('jsCookie set', key, _AccessToken, domain);
jsCookie.set(key, _AccessToken);
jsCookie.set(key, _AccessToken, {
domain: domain
});
});
});
}
} catch (error) {
AuthOptions.log('AccessToken Error', error, this);
}
};
/**
* 清理所有的登录信息
* @return {*}
* @memberof AuthController
*/
AuthController.prototype.onClear = function () {
var _this = this;
try {
AuthOptions.writeCheck();
this._AccessToken = undefined;
if (!this.HydrateisStopped) {
this.lastValue = undefined;
}
this.onRemove();
_map(this.CookieDomain, function (domain) {
return _this.onRemove({
domain: domain
});
}); // return AuthOptions.LocalForage.clear();
} catch (error) {
AuthOptions.log('error', error);
}
};
AuthController.prototype.onRemove = function (options) {
if (AuthOptions.browser) {
try {
AuthOptions.writeCheck();
_map(this.CookieKey, function (key) {
return jsCookie.remove(key, options);
});
_map(this.AllCookieKeys, function (key) {
return jsCookie.remove(key, options);
});
} catch (error) {
AuthOptions.log('error', error);
}
}
};
/**
* 创建持久化存储
* @memberof BaseModel
*/
AuthController.prototype.createHydrate = function () {
return __awaiter(this, void 0, void 0, function () {
var Hydrate, Decoded, error_1;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2,, 3]);
if (!AuthOptions.browser) {
throw '非浏览器环境 不进行 Hydrate';
} // 微信小程序中不使用 cookie
if (AuthOptions.isWeappBowser) {
this.onRemove();
_map(this.CookieDomain, function (domain) {
return _this.onRemove({
domain: domain
});
});
}
Hydrate = AuthOptions.createHydrate();
persist({
_AccessToken: true
})(this);
AuthOptions.log("Storage " + this.StorageKey, this);
return [4
/*yield*/
, Hydrate(this.StorageKey, this)];
case 1:
_a.sent();
if (!_eq(this.lastValue, 'default') && !_isEqual(this._AccessToken, this.lastValue)) {
AuthOptions.log("Storage " + this.StorageKey + " LastValue", this, this.lastValue);
this.onSaveAccessToken(this.lastValue);
} // jwt 校验正确性
if (this.IsJWT) {
Decoded = this.getDecoded(); // 过期清理 或者无效
if (Decoded.overdue) {
this.onClear();
}
} // const CookieAccessToken = lodash.find(this.CookieAccessToken, lodash.identity);
// if (!this._AccessToken && CookieAccessToken) {
// this.onSaveAccessToken(CookieAccessToken)
// }
this.HydrateSubject.next(true);
this.HydrateSubject.complete();
return [3
/*break*/
, 3];
case 2:
error_1 = _a.sent();
if (AuthOptions.browser) {
AuthOptions.log('error', error_1);
}
this.HydrateSubject.next(false);
this.HydrateSubject.complete();
return [3
/*break*/
, 3];
case 3:
return [2
/*return*/
];
}
});
});
};
__decorate([observable], AuthController.prototype, "_AccessToken", void 0);
__decorate([computed], AuthController.prototype, "AccessToken", null);
__decorate([computed], AuthController.prototype, "JwtDecoded", null);
__decorate([action], AuthController.prototype, "onSaveAccessToken", null);
__decorate([action], AuthController.prototype, "onClear", null);
AuthController = __decorate([BindAll()], AuthController);
return AuthController;
}();
export { AuthController };
//# sourceMappingURL=auth.js.map