@bixi/auth
Version:
1,555 lines (1,530 loc) • 42.8 kB
JavaScript
import { DOCUMENT } from '@angular/common';
import * as i0 from '@angular/core';
import { InjectionToken, Injectable, Optional, Inject, inject, Injector, NgModule } from '@angular/core';
import { Router } from '@angular/router';
import { BehaviorSubject, Observable } from 'rxjs';
import { share } from 'rxjs/operators';
import extend from 'extend';
import { HttpErrorResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
/**
* @fileoverview added by tsickle
* Generated from: src/auth.config.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
const AUTH_DEFAULT_CONFIG = {
store_key: `_token`,
token_invalid_redirect: true,
token_exp_offset: 10,
token_send_key: `token`,
// tslint:disable-next-line: no-invalid-template-strings
token_send_template: '${token}',
token_send_place: 'header',
login_url: '/login',
ignores: [/\/login/, /assets\//, /passport\//],
allow_anonymous_key: `_allow_anonymous`,
executeOtherInterceptors: true
};
/**
* @param {?} srv
* @return {?}
*/
function mergeConfig(srv) {
return srv.merge(AUTH_DEFAULT_CONFIG);
}
/**
* @fileoverview added by tsickle
* Generated from: src/config.type.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @record
*/
function BixiAuthConfig() { }
if (false) {
/**
* 存储KEY值,默认:`_token`
* @type {?|undefined}
*/
BixiAuthConfig.prototype.store_key;
/**
* 无效时跳转至登录页,默认:`true`,包括:
* - 无效token值
* - token已过期(限JWT)
* @type {?|undefined}
*/
BixiAuthConfig.prototype.token_invalid_redirect;
/**
* token过期时间偏移值,默认:`10` 秒(单位:秒)
* @type {?|undefined}
*/
BixiAuthConfig.prototype.token_exp_offset;
/**
* 发送token参数名,默认:·
* @type {?|undefined}
*/
BixiAuthConfig.prototype.token_send_key;
/**
* 发送token模板(默认为:`'${token}'`),使用 `${token}` 表示token点位符(**注意:**请务必使用 \`\` 包裹),例如:
*
* - `Bearer ${token}`
* @type {?|undefined}
*/
BixiAuthConfig.prototype.token_send_template;
/**
* 发送token参数位置,默认:`header`
* @type {?|undefined}
*/
BixiAuthConfig.prototype.token_send_place;
/**
* 登录页路由地址,默认:`/login`
* @type {?|undefined}
*/
BixiAuthConfig.prototype.login_url;
/**
* 忽略TOKEN的URL地址列表,默认值为:`[/\/login/, /assets\//, /passport\//]`
* @type {?|undefined}
*/
BixiAuthConfig.prototype.ignores;
/**
* 允许匿名登录KEY,若请求参数中带有该KEY表示忽略TOKEN,默认:`_allow_anonymous`
* @type {?|undefined}
*/
BixiAuthConfig.prototype.allow_anonymous_key;
/**
* 是否校验失效时命中后继续调用后续拦截器的 `intercept` 方法,默认:`true`
* @type {?|undefined}
*/
BixiAuthConfig.prototype.executeOtherInterceptors;
}
/** @type {?} */
const BIXI_AUTH_CONFIG = new InjectionToken('bixi-auth-config');
/**
* @fileoverview added by tsickle
* Generated from: src/auth.config.service.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* 深度合并对象
*
* @param {?} original 原始对象
* @param {?} arrayProcessMethod 数组处理方式
* - `true` 表示替换新值,不管新值为哪种类型
* - `false` 表示会合并整个数组(将旧数据与新数据合并成新数组)
* @param {...?} objects 要合并的对象
* @return {?}
*/
// tslint:disable-next-line:no-any
function deepMergeKey(original, arrayProcessMethod, ...objects) {
if (Array.isArray(original) || typeof original !== 'object')
return original;
// tslint:disable-next-line:no-any
/** @type {?} */
const isObject = (/**
* @param {?} v
* @return {?}
*/
(v) => typeof v === 'object' || typeof v === 'function');
// tslint:disable-next-line:no-any
/** @type {?} */
const merge = (/**
* @param {?} target
* @param {?} obj
* @return {?}
*/
(target, obj) => {
Object.keys(obj)
.filter((/**
* @param {?} key
* @return {?}
*/
key => key !== '__proto__' && Object.prototype.hasOwnProperty.call(obj, key)))
.forEach((/**
* @param {?} key
* @return {?}
*/
key => {
/** @type {?} */
const fromValue = obj[key];
/** @type {?} */
const toValue = target[key];
if (Array.isArray(toValue)) {
target[key] = arrayProcessMethod ? fromValue : [...toValue, ...fromValue];
}
else if (fromValue != null && isObject(fromValue) && toValue != null && isObject(toValue)) {
target[key] = merge(toValue, fromValue);
}
else {
target[key] = deepCopy(fromValue);
}
}));
return target;
});
objects.filter((/**
* @param {?} v
* @return {?}
*/
v => v != null && isObject(v))).forEach((/**
* @param {?} v
* @return {?}
*/
v => merge(original, v)));
return original;
}
// tslint:disable-next-line:no-any
/**
* @param {?} obj
* @return {?}
*/
function deepCopy(obj) {
/** @type {?} */
const result = extend(true, {}, { _: obj });
return result._;
}
class BixiConfigService {
/**
* @param {?=} defaultConfig
*/
constructor(defaultConfig) {
this.config = defaultConfig || {};
}
/**
* @param {?=} key
* @return {?}
*/
get(key) {
// tslint:disable-next-line:no-any
/** @type {?} */
const res = (/** @type {?} */ ((((/** @type {?} */ (this.config))) || {})));
return key ? { [key]: res[key] } : res;
}
/**
* @template R
* @param {...?} defaultValues
* @return {?}
*/
merge(...defaultValues) {
return deepMergeKey({}, true, ...defaultValues, this.get());
}
// tslint:disable-next-line:no-any
/**
* @template R
* @param {?} componentThis
* @param {?} defaultValues
* @return {?}
*/
attach(componentThis, defaultValues) {
Object.assign(componentThis, this.merge(defaultValues));
}
// tslint:disable-next-line:no-any
/**
* @param {?} componentThis
* @param {?} key
* @return {?}
*/
attachKey(componentThis, key) {
Object.assign(componentThis, this.get(key));
}
/**
* @param {?} value
* @return {?}
*/
set(value) {
this.config = Object.assign(Object.assign({}, this.config), value);
}
}
BixiConfigService.decorators = [
{ type: Injectable, args: [{ providedIn: 'root' },] }
];
/** @nocollapse */
BixiConfigService.ctorParameters = () => [
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [BIXI_AUTH_CONFIG,] }] }
];
/** @nocollapse */ BixiConfigService.ɵprov = i0.ɵɵdefineInjectable({ factory: function BixiConfigService_Factory() { return new BixiConfigService(i0.ɵɵinject(BIXI_AUTH_CONFIG, 8)); }, token: BixiConfigService, providedIn: "root" });
if (false) {
/**
* @type {?}
* @private
*/
BixiConfigService.prototype.config;
}
/**
* @fileoverview added by tsickle
* Generated from: src/store/local-storage.service.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* `localStorage` storage, **not lost after closing the browser**.
*
* ```ts
* { provide: BIXI_STORE_TOKEN, useClass: LocalStorageStore }
* ```
*/
class LocalStorageStore {
/**
* @param {?} key
* @return {?}
*/
get(key) {
return JSON.parse(localStorage.getItem(key) || '{}') || {};
}
/**
* @param {?} key
* @param {?} value
* @return {?}
*/
set(key, value) {
localStorage.setItem(key, JSON.stringify(value));
return true;
}
/**
* @param {?} key
* @return {?}
*/
remove(key) {
localStorage.removeItem(key);
}
}
/**
* @return {?}
*/
function BIXI_STORE_TOKEN_LOCAL_FACTORY() {
return new LocalStorageStore();
}
/**
* @fileoverview added by tsickle
* Generated from: src/store/interface.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
const BIXI_STORE_TOKEN = new InjectionToken('AUTH_STORE_TOKEN', {
providedIn: 'root',
factory: BIXI_STORE_TOKEN_LOCAL_FACTORY
});
/**
* @record
*/
function IStore() { }
if (false) {
/**
* @param {?} key
* @return {?}
*/
IStore.prototype.get = function (key) { };
/**
* @param {?} key
* @param {?} value
* @return {?}
*/
IStore.prototype.set = function (key, value) { };
/**
* @param {?} key
* @return {?}
*/
IStore.prototype.remove = function (key) { };
}
/**
* @fileoverview added by tsickle
* Generated from: src/token/token.service.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* 维护Token信息服务,[在线文档](https://bixi.datagrand.com/auth)
*/
class TokenService {
/**
* @param {?} configSrv
* @param {?} store
*/
constructor(configSrv, store) {
this.store = store;
this.change$ = new BehaviorSubject(null);
this._referrer = {};
this._options = mergeConfig(configSrv);
}
/**
* 授权失败后跳转路由路径(支持外部链接地址)
* @return {?}
*/
get login_url() {
return this._options.login_url;
}
/**
* 当前请求页面的来源页面的地址
* @return {?}
*/
get referrer() {
return this._referrer;
}
/**
* @return {?}
*/
get options() {
return this._options;
}
/**
* 设置 Token 信息,当用户 Token 发生变动时都需要调用此方法重新刷新
* @param {?} data
* @return {?}
*/
set(data) {
this.change$.next(data);
// tslint:disable-next-line:no-non-null-assertion
return this.store.set((/** @type {?} */ (this._options.store_key)), data);
}
/**
* @template T
* @param {?=} type
* @return {?}
*/
get(type) {
// tslint:disable-next-line:no-non-null-assertion
/** @type {?} */
const data = this.store.get((/** @type {?} */ (this._options.store_key)));
return type ? ((/** @type {?} */ (Object.assign(new type(), data)))) : ((/** @type {?} */ (data)));
}
/**
* 清除 Token 信息,当用户退出登录时调用。
* ```
* // 清除所有 Token 信息
* tokenService.clear();
* // 只清除 token 字段
* tokenService.clear({ onlyToken: true });
* ```
* @param {?=} options
* @return {?}
*/
clear(options = { onlyToken: false }) {
/** @type {?} */
let data = null;
if (options.onlyToken === true) {
data = (/** @type {?} */ (this.get()));
data.token = ``;
this.set(data);
}
else {
// tslint:disable-next-line:no-non-null-assertion
this.store.remove((/** @type {?} */ (this._options.store_key)));
}
this.change$.next(data);
}
/**
* 订阅 Token 对象变更通知
* @return {?}
*/
change() {
return this.change$.pipe(share());
}
}
/** @nocollapse */
TokenService.ctorParameters = () => [
{ type: BixiConfigService },
{ type: undefined, decorators: [{ type: Inject, args: [BIXI_STORE_TOKEN,] }] }
];
if (false) {
/**
* @type {?}
* @private
*/
TokenService.prototype.change$;
/**
* @type {?}
* @private
*/
TokenService.prototype._referrer;
/**
* @type {?}
* @private
*/
TokenService.prototype._options;
/**
* @type {?}
* @private
*/
TokenService.prototype.store;
}
/**
* @return {?}
*/
function BIXI_SERVICE_TOKEN_FACTORY() {
return new TokenService(inject(BixiConfigService), inject(BIXI_STORE_TOKEN));
}
/**
* @fileoverview added by tsickle
* Generated from: src/token/interface.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
const BIXI_SERVICE_TOKEN = new InjectionToken('BIXI_SERVICE_TOKEN', {
providedIn: 'root',
factory: BIXI_SERVICE_TOKEN_FACTORY
});
/**
* @record
*/
function ITokenModel() { }
if (false) {
/** @type {?} */
ITokenModel.prototype.token;
/* Skipping unhandled member: [key: string]: any;*/
}
/**
* @record
*/
function AuthReferrer() { }
if (false) {
/** @type {?|undefined} */
AuthReferrer.prototype.url;
}
/**
* @record
*/
function ITokenService() { }
if (false) {
/**
* 获取登录地址
* @type {?}
*/
ITokenService.prototype.login_url;
/**
* 获取授权失败前路由信息
* @type {?|undefined}
*/
ITokenService.prototype.referrer;
/** @type {?} */
ITokenService.prototype.options;
/**
* @param {?} data
* @return {?}
*/
ITokenService.prototype.set = function (data) { };
/**
* 获取Token,形式包括:
* - `get()` 获取 Simple Token
* - `get<JWTTokenModel>(JWTTokenModel)` 获取 JWT Token
* @param {?=} type
* @return {?}
*/
ITokenService.prototype.get = function (type) { };
/**
* 获取Token,形式包括:
* - `get()` 获取 Simple Token
* - `get<JWTTokenModel>(JWTTokenModel)` 获取 JWT Token
* @template T
* @param {?=} type
* @return {?}
*/
ITokenService.prototype.get = function (type) { };
/**
* Clean authorization data
* @param {?=} options
* @return {?}
*/
ITokenService.prototype.clear = function (options) { };
/**
* @return {?}
*/
ITokenService.prototype.change = function () { };
}
/**
* @fileoverview added by tsickle
* Generated from: src/social/social.service.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
const OPENTYPE = '_bixiAuthSocialType';
/** @type {?} */
const HREFCALLBACK = '_bixiAuthSocialCallbackByHref';
class SocialService {
/**
* @param {?} tokenService
* @param {?} doc
* @param {?} router
*/
constructor(tokenService, doc, router) {
this.tokenService = tokenService;
this.doc = doc;
this.router = router;
}
/**
* 跳转至登录页,若为 `type=window` 时,返回值是 `Observable<ITokenModel>`
* @param {?} url 获取授权地址
* @param {?=} callback 当 `type=href` 成功时的回调路由地址
* @param {?=} options options.type 打开方式,默认 `window` options.windowFeatures 等同 `window.open` 的 `features` 参数值
* @return {?}
*/
login(url, callback = '/', options = {}) {
options = Object.assign({ type: 'window', windowFeatures: 'location=yes,height=570,width=520,scrollbars=yes,status=yes' }, options);
// tslint:disable-next-line:no-non-null-assertion
localStorage.setItem(OPENTYPE, (/** @type {?} */ (options.type)));
localStorage.setItem(HREFCALLBACK, callback);
if (options.type === 'href') {
this.doc.location.href = url;
return;
}
this._win = window.open(url, '_blank', options.windowFeatures);
this._winTime = setInterval((/**
* @return {?}
*/
() => {
if (this._win && this._win.closed) {
this.ngOnDestroy();
/** @type {?} */
let model = this.tokenService.get();
if (model && !model.token)
model = null;
// 触发变更通知
if (model) {
this.tokenService.set(model);
}
this.observer.next(model);
this.observer.complete();
}
}), 100);
return new Observable((/**
* @param {?} observer
* @return {?}
*/
(observer) => {
this.observer = observer;
}));
}
/**
* 授权成功后的回调处理
*
* @param {?=} rawData 指定回调认证信息,为空时从根据当前URL解析
* @return {?}
*/
callback(rawData) {
// from uri
if (!rawData && this.router.url.indexOf('?') === -1) {
throw new Error(`url muse contain a ?`);
}
// parse
/** @type {?} */
let data = { token: `` };
if (typeof rawData === 'string') {
/** @type {?} */
const rightUrl = rawData.split('?')[1].split('#')[0];
data = (/** @type {?} */ (this.router.parseUrl('./?' + rightUrl).queryParams));
}
else {
data = (/** @type {?} */ (rawData));
}
if (!data || !data.token)
throw new Error(`invalide token data`);
this.tokenService.set(data);
/** @type {?} */
const url = localStorage.getItem(HREFCALLBACK) || '/';
localStorage.removeItem(HREFCALLBACK);
/** @type {?} */
const type = localStorage.getItem(OPENTYPE);
localStorage.removeItem(OPENTYPE);
if (type === 'window') {
window.close();
}
else {
this.router.navigateByUrl(url);
}
return data;
}
/**
* @return {?}
*/
ngOnDestroy() {
clearInterval(this._winTime);
this._winTime = null;
}
}
SocialService.decorators = [
{ type: Injectable }
];
/** @nocollapse */
SocialService.ctorParameters = () => [
{ type: undefined, decorators: [{ type: Inject, args: [BIXI_SERVICE_TOKEN,] }] },
{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] },
{ type: Router }
];
if (false) {
/**
* @type {?}
* @private
*/
SocialService.prototype._win;
/**
* @type {?}
* @private
*/
SocialService.prototype._winTime;
/**
* @type {?}
* @private
*/
SocialService.prototype.observer;
/**
* @type {?}
* @private
*/
SocialService.prototype.tokenService;
/**
* @type {?}
* @private
*/
SocialService.prototype.doc;
/**
* @type {?}
* @private
*/
SocialService.prototype.router;
}
/**
* @fileoverview added by tsickle
* Generated from: src/store/memory.service.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* 内存存储,关掉浏览器标签后**丢失**。
*
* ```ts
* { provide: BIXI_STORE_TOKEN, useClass: MemoryStore }
* ```
*/
class MemoryStore {
constructor() {
this.cache = {};
}
/**
* @param {?} key
* @return {?}
*/
get(key) {
return this.cache[key] || ((/** @type {?} */ ({})));
}
/**
* @param {?} key
* @param {?} value
* @return {?}
*/
set(key, value) {
this.cache[key] = value;
return true;
}
/**
* @param {?} key
* @return {?}
*/
remove(key) {
this.cache[key] = null;
}
}
if (false) {
/**
* @type {?}
* @private
*/
MemoryStore.prototype.cache;
}
/**
* @fileoverview added by tsickle
* Generated from: src/store/session-storage.service.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* `sessionStorage` storage, **lost after closing the browser**.
*
* ```ts
* { provide: BIXI_STORE_TOKEN, useClass: SessionStorageStore }
* ```
*/
class SessionStorageStore {
/**
* @param {?} key
* @return {?}
*/
get(key) {
return JSON.parse(sessionStorage.getItem(key) || '{}') || {};
}
/**
* @param {?} key
* @param {?} value
* @return {?}
*/
set(key, value) {
sessionStorage.setItem(key, JSON.stringify(value));
return true;
}
/**
* @param {?} key
* @return {?}
*/
remove(key) {
sessionStorage.removeItem(key);
}
}
/**
* @fileoverview added by tsickle
* Generated from: src/store/cookie-storage.service.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* `cookie` storage, muse be install
* [js-cookie](https://github.com/js-cookie/js-cookie) library
* and import `"node_modules/js-cookie/src/js.cookie.js"` in `angular.json`
*
* ```ts
* { provide: BIXI_STORE_TOKEN, useClass: CookieStorageStore }
* ```
*/
class CookieStorageStore {
/**
* @param {?} key
* @return {?}
*/
get(key) {
return JSON.parse(Cookies.get(key) || '{}') || {};
}
/**
* @param {?} key
* @param {?} value
* @return {?}
*/
set(key, value) {
Cookies.set(key, JSON.stringify(value));
return true;
}
/**
* @param {?} key
* @return {?}
*/
remove(key) {
Cookies.remove(key);
}
}
/**
* @fileoverview added by tsickle
* Generated from: src/token/helper.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @param {?} model
* @return {?}
*/
function CheckSimple(model) {
return model != null && typeof model.token === 'string' && model.token.length > 0;
}
/**
* @param {?} model
* @param {?} offset
* @return {?}
*/
function CheckJwt(model, offset) {
return model != null && !!model.token && !model.isExpired(offset);
}
/**
* @param {?} options
* @param {?} injector
* @param {?=} url
* @return {?}
*/
function ToLogin(options, injector, url) {
/** @type {?} */
const router = injector.get(Router);
// tslint:disable-next-line:no-non-null-assertion
(/** @type {?} */ (((/** @type {?} */ (injector.get(BIXI_SERVICE_TOKEN)))).referrer)).url = url || router.url;
if (options.token_invalid_redirect === true) {
setTimeout((/**
* @return {?}
*/
() => {
// tslint:disable-next-line:no-non-null-assertion
if (/^https?:\/\//g.test((/** @type {?} */ (options.login_url)))) {
injector.get(DOCUMENT).location.href = (/** @type {?} */ (options.login_url));
}
else {
router.navigate([options.login_url]);
}
}));
}
}
/**
* @fileoverview added by tsickle
* Generated from: src/token/base.interceptor.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class HttpAuthInterceptorHandler {
/**
* @param {?} next
* @param {?} interceptor
*/
constructor(next, interceptor) {
this.next = next;
this.interceptor = interceptor;
}
// tslint:disable-next-line:no-any
/**
* @param {?} req
* @return {?}
*/
handle(req) {
return this.interceptor.intercept(req, this.next);
}
}
if (false) {
/**
* @type {?}
* @private
*/
HttpAuthInterceptorHandler.prototype.next;
/**
* @type {?}
* @private
*/
HttpAuthInterceptorHandler.prototype.interceptor;
}
/**
* @abstract
*/
class BaseInterceptor {
/**
* @param {?} injector
*/
constructor(injector) {
this.injector = injector;
}
// tslint:disable-next-line:no-any
/**
* @param {?} req
* @param {?} next
* @return {?}
*/
intercept(req, next) {
/** @type {?} */
const options = mergeConfig(this.injector.get(BixiConfigService));
if (options.ignores) {
for (const item of (/** @type {?} */ (options.ignores))) {
if (item.test(req.url))
return next.handle(req);
}
}
if (options.allow_anonymous_key &&
(req.params.has(options.allow_anonymous_key) || new RegExp(`[\?|&]${options.allow_anonymous_key}=[^&]+`).test(req.urlWithParams))) {
return next.handle(req);
}
if (this.isAuth(options)) {
req = this.setReq(req, options);
}
else {
console.warn('[@bixi/auth](interceptor): Token 不存在或已过期,前往登录页');
ToLogin(options, this.injector);
// Interrupt Http request, so need to generate a new Observable
// tslint:disable-next-line:no-any
/** @type {?} */
const err$ = new Observable((/**
* @param {?} observer
* @return {?}
*/
(observer) => {
/** @type {?} */
const res = new HttpErrorResponse({
url: req.url,
headers: req.headers,
status: 401,
statusText: `来自 /auth 的拦截,所请求URL未授权,若是登录API可加入 [url?_allow_anonymous=true] 来表示忽略校验`
});
observer.error(res);
}));
if (options.executeOtherInterceptors) {
/** @type {?} */
const interceptors = this.injector.get(HTTP_INTERCEPTORS, []);
/** @type {?} */
const lastInterceptors = interceptors.slice(interceptors.indexOf(this) + 1);
if (lastInterceptors.length > 0) {
/** @type {?} */
const chain = lastInterceptors.reduceRight((/**
* @param {?} _next
* @param {?} _interceptor
* @return {?}
*/
(_next, _interceptor) => new HttpAuthInterceptorHandler(_next, _interceptor)), {
// tslint:disable-next-line:no-any
handle: (/**
* @param {?} _
* @return {?}
*/
(_) => err$)
});
return chain.handle(req);
}
}
return err$;
}
return next.handle(req);
}
}
BaseInterceptor.decorators = [
{ type: Injectable }
];
/** @nocollapse */
BaseInterceptor.ctorParameters = () => [
{ type: Injector, decorators: [{ type: Optional }] }
];
if (false) {
/**
* @type {?}
* @protected
*/
BaseInterceptor.prototype.model;
/**
* @type {?}
* @protected
*/
BaseInterceptor.prototype.injector;
/**
* @abstract
* @param {?} options
* @return {?}
*/
BaseInterceptor.prototype.isAuth = function (options) { };
/**
* @abstract
* @param {?} req
* @param {?} options
* @return {?}
*/
BaseInterceptor.prototype.setReq = function (req, options) { };
}
/**
* @fileoverview added by tsickle
* Generated from: src/token/jwt/jwt.helper.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @param {?} str
* @return {?}
*/
function urlBase64Decode(str) {
/** @type {?} */
let output = str.replace(/-/g, '+').replace(/_/g, '/');
switch (output.length % 4) {
case 0: {
break;
}
case 2: {
output += '==';
break;
}
case 3: {
output += '=';
break;
}
default: {
throw new Error(`'atob' failed: The string to be decoded is not correctly encoded.`);
}
}
return b64DecodeUnicode(output);
}
/**
* @param {?} str
* @return {?}
*/
function b64decode(str) {
/** @type {?} */
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
/** @type {?} */
let output = '';
str = String(str).replace(/=+$/, '');
for (
// initialize result and counters
// tslint:disable:no-conditional-assignment binary-expression-operand-order
// tslint:disable-next-line:no-any
let bc = 0, bs, buffer, idx = 0;
// get next character
(buffer = str.charAt(idx++));
// character found in table? initialize bit storage and add its ascii value;
// tslint:disable-next-line: no-bitwise
~buffer &&
// tslint:disable-next-line: ban-comma-operator
((bs = bc % 4 ? bs * 64 + buffer : buffer),
// and if not first of each 4 characters,
// convert the first 8 bits to one ascii character
bc++ % 4)
// tslint:disable-next-line: no-bitwise
? (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6))))
: 0) {
// try to find character in table (0-63, not found => -1)
buffer = chars.indexOf(buffer);
}
return output;
}
// https://developer.mozilla.org/en/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem
/**
* @param {?} str
* @return {?}
*/
function b64DecodeUnicode(str) {
return decodeURIComponent(Array.prototype.map
.call(b64decode(str), (/**
* @param {?} c
* @return {?}
*/
(c) => {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}))
.join(''));
}
/**
* @fileoverview added by tsickle
* Generated from: src/token/jwt/jwt.model.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @record
*/
function JWT() { }
if (false) {
/**
* Issuerd
* @type {?}
*/
JWT.prototype.iss;
/**
* Issued At
* @type {?}
*/
JWT.prototype.iat;
/**
* Subject
* @type {?}
*/
JWT.prototype.sub;
/**
* Expiration Time
* @type {?}
*/
JWT.prototype.exp;
/**
* Audience
* @type {?}
*/
JWT.prototype.aud;
/**
* Not Before
* @type {?}
*/
JWT.prototype.nbf;
/**
* JWT ID
* @type {?}
*/
JWT.prototype.jti;
/* Skipping unhandled member: [key: string]: any;*/
/* Skipping unhandled member: [key: number]: any;*/
}
class JWTTokenModel {
/**
* 获取载荷信息
* @return {?}
*/
get payload() {
/** @type {?} */
const parts = (this.token || '').split('.');
if (parts.length !== 3)
throw new Error('JWT must have 3 parts');
/** @type {?} */
const decoded = urlBase64Decode(parts[1]);
return JSON.parse(decoded);
}
/**
* 获取过期时间戳(单位:ms)
* @return {?}
*/
get exp() {
/** @type {?} */
const decoded = this.payload;
if (!decoded.hasOwnProperty('exp'))
return null;
/** @type {?} */
const date = new Date(0);
date.setUTCSeconds(decoded.exp);
return date.valueOf();
}
/**
* 检查Token是否过期,当`payload` 包含 `exp` 字段时有效,若无 `exp` 字段直接返回 `null`
*
* @param {?=} offsetSeconds 偏移量
* @return {?}
*/
isExpired(offsetSeconds = 0) {
/** @type {?} */
const exp = this.exp;
if (exp == null)
return null;
return !(exp > new Date().valueOf() + offsetSeconds * 1000);
}
}
if (false) {
/** @type {?} */
JWTTokenModel.prototype.token;
/* Skipping unhandled member: [key: string]: any;*/
}
/**
* @fileoverview added by tsickle
* Generated from: src/token/jwt/jwt.interceptor.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* JWT 拦截器
*
* ```
* // app.module.ts
* { provide: HTTP_INTERCEPTORS, useClass: JWTInterceptor, multi: true}
* ```
*/
class JWTInterceptor extends BaseInterceptor {
/**
* @param {?} options
* @return {?}
*/
isAuth(options) {
this.model = this.injector.get(BIXI_SERVICE_TOKEN).get(JWTTokenModel);
// tslint:disable-next-line:no-non-null-assertion
return CheckJwt((/** @type {?} */ (this.model)), (/** @type {?} */ (options.token_exp_offset)));
}
// tslint:disable-next-line:no-any
/**
* @param {?} req
* @param {?} _options
* @return {?}
*/
setReq(req, _options) {
return req.clone({
setHeaders: {
Authorization: `Bearer ${this.model.token}`
}
});
}
}
JWTInterceptor.decorators = [
{ type: Injectable }
];
/**
* @fileoverview added by tsickle
* Generated from: src/token/jwt/jwt.guard.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* JWT 路由守卫, [ACL Document](https://bixi.datagrand.com/auth/guard).
*
* ```ts
* data: {
* path: 'home',
* canActivate: [ JWTGuard ]
* },
* {
* path: 'my',
* canActivateChild: [JWTGuard],
* children: [
* { path: 'profile', component: MockComponent }
* ],
* },
* ```
*/
class JWTGuard {
/**
* @param {?} srv
* @param {?} injector
*/
constructor(srv, injector) {
this.srv = srv;
this.injector = injector;
}
/**
* @private
* @return {?}
*/
get cog() {
return this.srv.options;
}
/**
* @private
* @return {?}
*/
process() {
// tslint:disable-next-line:no-non-null-assertion
/** @type {?} */
const res = CheckJwt(this.srv.get(JWTTokenModel), (/** @type {?} */ (this.cog.token_exp_offset)));
if (!res) {
console.warn('[@bixi/auth](jwt guard): token 不存在或已过期,前往登录页');
ToLogin(this.cog, this.injector, this.url);
}
return res;
}
// lazy loading
/**
* @param {?} route
* @param {?} _segments
* @return {?}
*/
canLoad(route, _segments) {
this.url = route.path;
return this.process();
}
// all children route
/**
* @param {?} _childRoute
* @param {?} state
* @return {?}
*/
canActivateChild(_childRoute, state) {
this.url = state.url;
return this.process();
}
// route
/**
* @param {?} _route
* @param {?} state
* @return {?}
*/
canActivate(_route, state) {
this.url = state.url;
return this.process();
}
}
JWTGuard.decorators = [
{ type: Injectable, args: [{ providedIn: 'root' },] }
];
/** @nocollapse */
JWTGuard.ctorParameters = () => [
{ type: undefined, decorators: [{ type: Inject, args: [BIXI_SERVICE_TOKEN,] }] },
{ type: Injector }
];
/** @nocollapse */ JWTGuard.ɵprov = i0.ɵɵdefineInjectable({ factory: function JWTGuard_Factory() { return new JWTGuard(i0.ɵɵinject(BIXI_SERVICE_TOKEN), i0.ɵɵinject(i0.INJECTOR)); }, token: JWTGuard, providedIn: "root" });
if (false) {
/**
* @type {?}
* @private
*/
JWTGuard.prototype.url;
/**
* @type {?}
* @private
*/
JWTGuard.prototype.srv;
/**
* @type {?}
* @private
*/
JWTGuard.prototype.injector;
}
/**
* @fileoverview added by tsickle
* Generated from: src/token/simple/simple.model.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class SimpleTokenModel {
}
if (false) {
/** @type {?} */
SimpleTokenModel.prototype.token;
/* Skipping unhandled member: [key: string]: any;*/
}
/**
* @fileoverview added by tsickle
* Generated from: src/token/simple/simple.interceptor.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Simple 拦截器
*
* ```
* // app.module.ts
* { provide: HTTP_INTERCEPTORS, useClass: SimpleInterceptor, multi: true}
* ```
*/
class SimpleInterceptor extends BaseInterceptor {
/**
* @param {?} _options
* @return {?}
*/
isAuth(_options) {
this.model = (/** @type {?} */ (this.injector.get(BIXI_SERVICE_TOKEN).get()));
return CheckSimple((/** @type {?} */ (this.model)));
}
// tslint:disable-next-line:no-any
/**
* @param {?} req
* @param {?} options
* @return {?}
*/
setReq(req, options) {
const { token_send_template, token_send_key } = options;
// tslint:disable-next-line:no-non-null-assertion
/** @type {?} */
const token = (/** @type {?} */ (token_send_template)).replace(/\$\{([\w]+)\}/g, (/**
* @param {?} _
* @param {?} g
* @return {?}
*/
(_, g) => this.model[g]));
switch (options.token_send_place) {
case 'header':
// tslint:disable-next-line:no-any
/** @type {?} */
const obj = {};
// tslint:disable-next-line:no-non-null-assertion
obj[(/** @type {?} */ (token_send_key))] = token;
req = req.clone({
setHeaders: obj
});
break;
case 'body':
/** @type {?} */
const body = req.body || {};
// tslint:disable-next-line:no-non-null-assertion
body[(/** @type {?} */ (token_send_key))] = token;
req = req.clone({
body
});
break;
case 'url':
req = req.clone({
// tslint:disable-next-line:no-non-null-assertion
params: req.params.append((/** @type {?} */ (token_send_key)), token)
});
break;
}
return req;
}
}
SimpleInterceptor.decorators = [
{ type: Injectable }
];
/**
* @fileoverview added by tsickle
* Generated from: src/token/simple/simple.guard.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Simple 路由守卫, [ACL Document](https://bixi.datagrand.com/auth/guard).
*
* ```ts
* data: {
* path: 'home',
* canActivate: [ SimpleGuard ]
* },
* {
* path: 'my',
* canActivateChild: [SimpleGuard],
* children: [
* { path: 'profile', component: MockComponent }
* ],
* },
* ```
*/
class SimpleGuard {
/**
* @param {?} srv
* @param {?} injector
*/
constructor(srv, injector) {
this.srv = srv;
this.injector = injector;
}
/**
* @private
* @return {?}
*/
get cog() {
return this.srv.options;
}
/**
* @private
* @return {?}
*/
process() {
/** @type {?} */
const res = CheckSimple((/** @type {?} */ (this.srv.get())));
if (!res) {
ToLogin(this.cog, this.injector, this.url);
}
return res;
}
// lazy loading
/**
* @param {?} route
* @param {?} _segments
* @return {?}
*/
canLoad(route, _segments) {
this.url = route.path;
return this.process();
}
// all children route
/**
* @param {?} _childRoute
* @param {?} state
* @return {?}
*/
canActivateChild(_childRoute, state) {
this.url = state.url;
return this.process();
}
// route
/**
* @param {?} _route
* @param {?} state
* @return {?}
*/
canActivate(_route, state) {
this.url = state.url;
return this.process();
}
}
SimpleGuard.decorators = [
{ type: Injectable, args: [{ providedIn: 'root' },] }
];
/** @nocollapse */
SimpleGuard.ctorParameters = () => [
{ type: undefined, decorators: [{ type: Inject, args: [BIXI_SERVICE_TOKEN,] }] },
{ type: Injector }
];
/** @nocollapse */ SimpleGuard.ɵprov = i0.ɵɵdefineInjectable({ factory: function SimpleGuard_Factory() { return new SimpleGuard(i0.ɵɵinject(BIXI_SERVICE_TOKEN), i0.ɵɵinject(i0.INJECTOR)); }, token: SimpleGuard, providedIn: "root" });
if (false) {
/**
* @type {?}
* @private
*/
SimpleGuard.prototype.url;
/**
* @type {?}
* @private
*/
SimpleGuard.prototype.srv;
/**
* @type {?}
* @private
*/
SimpleGuard.prototype.injector;
}
/**
* @fileoverview added by tsickle
* Generated from: src/auth.module.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class BixiAuthModule {
}
BixiAuthModule.decorators = [
{ type: NgModule, args: [{},] }
];
/**
* @fileoverview added by tsickle
* Generated from: public_api.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* Generated from: auth.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
export { AUTH_DEFAULT_CONFIG, BIXI_AUTH_CONFIG, BIXI_SERVICE_TOKEN, BIXI_SERVICE_TOKEN_FACTORY, BIXI_STORE_TOKEN, BIXI_STORE_TOKEN_LOCAL_FACTORY, BaseInterceptor, BixiAuthModule, CookieStorageStore, JWTGuard, JWTInterceptor, JWTTokenModel, LocalStorageStore, MemoryStore, SessionStorageStore, SimpleGuard, SimpleInterceptor, SimpleTokenModel, SocialService, TokenService, mergeConfig, urlBase64Decode, BixiConfigService as ɵa };
//# sourceMappingURL=auth.js.map