@mamba-le/auth
Version:
337 lines (334 loc) • 9.72 kB
text/typescript
import lodash from 'lodash';
import { BindAll } from 'lodash-decorators';
import { computed, toJS } from 'mobx';
import { lastValueFrom, Subject, zip } from 'rxjs';
import { AuthController, IAuthOptions } from './auth';
import env from './env';
import { InfoController } from './info';
import { AuthOptions } from './options';
declare global {
interface Window {
__MICRO_APP_ENVIRONMENT__: boolean;
rawWindow: Window;
/**
* 挂载的顶层 PortalAuthController
* @type {PortalAuthController}
* @memberof Window
*/
PortalAuth: PortalAuthController;
}
}
export interface IPortalAuthOptions {
/**
* Portal 类型
* @type {('General' | 'BP' | 'SP')}
* @memberof IPortalAuthOptions
*/
PortalType?: 'General' | 'BP' | 'SP'
/**
* Token 类型
* @type {('JWT' | 'Other')}
* @memberof IPortalAuthOptions
*/
TokenType?: 'JWT' | 'Other'
BPAuth?: IAuthOptions
SPAuth?: IAuthOptions
}
/**
* Portal 认证信息 BP&SP
* @export
* @class PortalAuthController
*/
export class PortalAuthController {
static get env() {
return env
}
get env() {
return env
}
/**
* 存储的单列
* @private
* @static
* @type {PortalAuthController}
* @memberof PortalAuthController
*/
protected static PortalAuth: PortalAuthController = undefined;
/**
* 混合认证
* @protected
* @static
* @type {AuthController}
* @memberof PortalAuthController
*/
protected static GeneralAuth: AuthController = undefined;
/**
* BP 认证
* @protected
* @static
* @type {AuthController}
* @memberof PortalAuthController
*/
protected static BPAuth: AuthController = undefined;
/**
* SP 认证
* @protected
* @static
* @type {AuthController}
* @memberof PortalAuthController
*/
protected static SPAuth: AuthController = undefined;
/**
* 基础信息
* @protected
* @static
* @type {InfoController}
* @memberof PortalAuthController
*/
protected static PortalInfo: InfoController = undefined;
/**
* 引流信息
* @protected
* @static
* @type {InfoController}
* @memberof PortalAuthController
*/
protected static PortalDrainage: InfoController = undefined;
protected static createAuth(options: IPortalAuthOptions) {
switch (options.PortalType) {
case 'BP':
PortalAuthController.BPAuth = new AuthController({
CookieKey: ['BPPORTAL_TOKEN'],
StorageKey: 'BPPortal',
TokenType: options.TokenType || 'JWT'
})
return
case 'SP':
PortalAuthController.SPAuth = new AuthController({
CookieKey: ['SALES_TOKEN'],
StorageKey: 'SALESPortal',
TokenType: options.TokenType || 'Other'
})
return
default:
PortalAuthController.GeneralAuth = new AuthController({
CookieKey: ['BPPORTAL_TOKEN', 'SALES_TOKEN'],
StorageKey: 'Portal',
TokenType: options.TokenType || 'Other'
})
}
};
constructor(protected readonly options: IPortalAuthOptions = { PortalType: 'BP' }) {
// 浏览器
if (AuthOptions.browser) {
// 微前端 环境中
if (AuthOptions.micro && window?.rawWindow?.PortalAuth) {
PortalAuthController.PortalAuth = window.rawWindow.PortalAuth
} else if (window?.PortalAuth) {
PortalAuthController.PortalAuth = window.PortalAuth
}
// 非微前端环境
if (!AuthOptions.micro) {
window.PortalAuth = this
}
// 单例
if (PortalAuthController.PortalAuth) {
return PortalAuthController.PortalAuth;
}
}
PortalAuthController.createAuth(this.options);
PortalAuthController.PortalInfo = new InfoController({ StorageKey: 'PortalInfo' });
PortalAuthController.PortalDrainage = new InfoController({ StorageKey: 'PortalDrainage' });
this.createHydrate();
PortalAuthController.PortalAuth = this;
AuthOptions.log('PortalAuth', this)
}
/**
* 持久化初始化完成 Subject
* @type {Promise<any>}
* @memberof ControllerUser
*/
protected readonly HydrateSubject = new Subject<Boolean>();
/**
* 持久化初始化完成 Promise
* @type {Promise<any>}
* @memberof ControllerUser
*/
get HydrateAsync(): Promise<this> {
return lastValueFrom(this.HydrateSubject, { defaultValue: undefined });
}
/**
* 异步 HydrateSubject 已经完成
* @readonly
* @memberof PortalAuthController
*/
get HydrateisStopped() {
return this.HydrateSubject.isStopped
}
/**
* BP Auth
* @type {AuthController}
* @memberof PortalAuthController
*/
protected get BPAuth() {
return PortalAuthController.BPAuth
}
/**
* SP Auth
* @type {AuthController}
* @memberof PortalAuthController
*/
protected get SPAuth() {
return PortalAuthController.SPAuth
}
/**
* 通用的 Auth
* @type {AuthController}
* @memberof PortalAuthController
*/
protected get GeneralAuth() {
return PortalAuthController.GeneralAuth
}
/**
* 数据 Info
* @readonly
* @memberof PortalAuthController
*/
protected get PortalInfo() {
return PortalAuthController.PortalInfo
}
/**
* 数据 引流
* @readonly
* @protected
* @memberof PortalAuthController
*/
protected get PortalDrainage() {
return PortalAuthController.PortalDrainage
}
/**
* 基础数据
* @readonly
* @memberof PortalAuthController
*/
get Info() {
return toJS(this.PortalInfo.value)
}
/**
* 引流数据
* @readonly
* @memberof PortalAuthController
*/
get Drainage() {
return toJS(this.PortalDrainage.value)
}
/**
* AccessToken 返回校验 时间是否过期 过期 的 AccessToken 不返回
* @readonly
* @memberof PortalAuthController
*/
get AccessToken() {
switch (this.options.PortalType) {
case 'BP':
return this.BPAuth.AccessToken
case 'SP':
return this.SPAuth.AccessToken
default:
return this.GeneralAuth.AccessToken
}
}
/**
* AccessToken 解码信息
* @readonly
* @memberof PortalAuthController
*/
get JwtDecoded() {
switch (this.options.PortalType) {
case 'BP':
return this.BPAuth.JwtDecoded
case 'SP':
return this.SPAuth.JwtDecoded
default:
return this.GeneralAuth.JwtDecoded
}
}
/**
* 保存 AccessToken 校验有效性 无效过滤
* @param {string} [AccessToken=undefined]
* @memberof PortalAuthController
*/
onSaveAccessToken(AccessToken: string = undefined, setCookie = false) {
this.BPAuth?.onSaveAccessToken(AccessToken, setCookie)
this.SPAuth?.onSaveAccessToken(AccessToken, setCookie)
this.GeneralAuth?.onSaveAccessToken(AccessToken, setCookie)
}
/**
* 存储info 信息
* @param {*} value
* @memberof PortalAuthController
*/
onSaveInfo(value: any) {
this.PortalInfo.onSave(value)
AuthOptions.trace('Save Info', value)
}
/**
* 存储 Drainage 信息
* @param {*} value
* @memberof PortalAuthController
*/
onSaveDrainage(value: any) {
this.PortalDrainage.onSave(value)
AuthOptions.trace('Save Drainage', value)
}
/**
* 清理所有的登录信息
* @return {*}
* @memberof AuthController
*/
async onClear() {
try {
AuthOptions.writeCheck()
AuthOptions.trace('clear start')
this.BPAuth?.onClear()
this.SPAuth?.onClear()
this.GeneralAuth?.onClear()
this.PortalInfo?.onClear()
this.PortalDrainage?.onClear()
if (AuthOptions.browser) {
window.localStorage?.clear()
window.sessionStorage?.clear()
await this.HydrateAsync
await AuthOptions.LocalForage.clear();
}
AuthOptions.log('clear success', 'localStorage,sessionStorage,IndexedDB,cookie 全部清理')
} catch (error) {
AuthOptions.trace('clear error', error)
}
}
/**
* 创建持久化存储
* @memberof BaseModel
*/
protected async createHydrate() {
try {
const observables = lodash.compact([
this.BPAuth?.HydrateAsync,
this.SPAuth?.HydrateAsync,
this.GeneralAuth?.HydrateAsync,
this.PortalInfo?.HydrateAsync
])
await lastValueFrom(zip(observables), { defaultValue: undefined })
this.HydrateSubject.next(true)
this.HydrateSubject.complete()
} catch (error) {
AuthOptions.trace('error', error)
this.HydrateSubject.next(false)
this.HydrateSubject.complete()
}
}
}