mm_api 1.1.4 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api.js +96 -2
- package/package.json +4 -2
package/lib/api.js
CHANGED
|
@@ -24,6 +24,9 @@ const Param = loadOptional("mm_param/lib/param.js"); // 是MM自带的参数机
|
|
|
24
24
|
const mm_dao = loadOptional("mm_dao");
|
|
25
25
|
const Dao = mm_dao ? mm_dao.Dao : null;
|
|
26
26
|
const Sql = loadOptional("mm_sql/lib/sql.js"); // 是MM自带的sql机制,可以不使用
|
|
27
|
+
// 登录态存储:token 解析优先走 mm_state_store(用户状态)+ mm_dict(token→user_id 映射)
|
|
28
|
+
const mm_state_store = loadOptional("mm_state_store");
|
|
29
|
+
const mm_dict = loadOptional("mm_dict");
|
|
27
30
|
|
|
28
31
|
/** param 实例缓存(模块级,替代原全局 param 模块列表) */
|
|
29
32
|
const PARAM_CACHE = new Map();
|
|
@@ -528,15 +531,37 @@ Api.prototype._getUserFromSession = function (ctx) {
|
|
|
528
531
|
return null;
|
|
529
532
|
};
|
|
530
533
|
|
|
534
|
+
/**
|
|
535
|
+
* 从上下文中提取 auth token(协议头优先,Cookie 兜底)
|
|
536
|
+
* @param {object} ctx 请求上下文
|
|
537
|
+
* @returns {string} token,无则返回空串
|
|
538
|
+
* @private
|
|
539
|
+
*/
|
|
540
|
+
Api.prototype._getToken = function (ctx) {
|
|
541
|
+
var headers = (ctx && (ctx.headers || (ctx.request && ctx.request.headers))) || {};
|
|
542
|
+
var token = headers[this.config.token_key] || "";
|
|
543
|
+
if (!token && ctx) {
|
|
544
|
+
var cookies = ctx.cookies || (ctx.request && ctx.request.cookies);
|
|
545
|
+
if (cookies) {
|
|
546
|
+
token =
|
|
547
|
+
typeof cookies.get === "function"
|
|
548
|
+
? cookies.get(this.config.token_key) || ""
|
|
549
|
+
: cookies[this.config.token_key] || "";
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
return String(token || "");
|
|
553
|
+
};
|
|
554
|
+
|
|
531
555
|
/**
|
|
532
556
|
* 从 token 中获取用户信息
|
|
557
|
+
* 解析顺序:缓存 → 用户状态存储(mm_dict 映射 / 解码 → mm_state_store)→ 数据库
|
|
533
558
|
* @param {object} ctx 请求上下文
|
|
534
559
|
* @param {object} db 数据管理器
|
|
535
560
|
* @returns {object|null} 用户信息
|
|
536
561
|
* @private
|
|
537
562
|
*/
|
|
538
563
|
Api.prototype._getUserFromToken = async function (params, ctx, options) {
|
|
539
|
-
var token =
|
|
564
|
+
var token = this._getToken(ctx);
|
|
540
565
|
if (!token) {
|
|
541
566
|
return null;
|
|
542
567
|
}
|
|
@@ -547,7 +572,76 @@ Api.prototype._getUserFromToken = async function (params, ctx, options) {
|
|
|
547
572
|
return await this._processUserFromCache(u, ctx, options, token);
|
|
548
573
|
}
|
|
549
574
|
}
|
|
550
|
-
|
|
575
|
+
var o = await this._getUserFromState(token, ctx, options);
|
|
576
|
+
if (o) {
|
|
577
|
+
return o;
|
|
578
|
+
}
|
|
579
|
+
// 数据库兜底:仅当传入的是表模型管理器(有 new 方法)时才可查询
|
|
580
|
+
if (options && typeof options.new === "function") {
|
|
581
|
+
return await this._getUserFromDb(token, ctx, options);
|
|
582
|
+
}
|
|
583
|
+
return null;
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* 从用户状态存储获取用户信息
|
|
588
|
+
* token → user_id:mm_dict 映射,或 base64(JSON) 直接解码;
|
|
589
|
+
* user_id → 用户:mm_state_store 的 stateAdmin('user') 中 user_{id} 状态的 user 字段
|
|
590
|
+
* @param {string} token token
|
|
591
|
+
* @param {object} ctx 请求上下文
|
|
592
|
+
* @param {object} options 数据管理器
|
|
593
|
+
* @returns {object|null} 用户信息,未识别或状态中无用户资料返回 null
|
|
594
|
+
* @private
|
|
595
|
+
*/
|
|
596
|
+
Api.prototype._getUserFromState = async function (token, ctx, options) {
|
|
597
|
+
if (!mm_state_store || !mm_dict) {
|
|
598
|
+
return null;
|
|
599
|
+
}
|
|
600
|
+
try {
|
|
601
|
+
// 1. token → user_id:字典映射,或 base64(JSON) 解码
|
|
602
|
+
var user_id = null;
|
|
603
|
+
try {
|
|
604
|
+
user_id = mm_dict.dictAdmin("token").get(token);
|
|
605
|
+
} catch (err) {
|
|
606
|
+
user_id = null;
|
|
607
|
+
}
|
|
608
|
+
if (!user_id) {
|
|
609
|
+
try {
|
|
610
|
+
var json = Buffer.from(token, "base64").toString("utf8");
|
|
611
|
+
if (/^\s*\{[\s\S]*\}\s*$/.test(json)) {
|
|
612
|
+
var obj = JSON.parse(json);
|
|
613
|
+
if (obj && obj.user_id !== undefined && obj.user_id !== null && obj.user_id !== "") {
|
|
614
|
+
user_id = String(obj.user_id);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
} catch (err) {
|
|
618
|
+
user_id = null;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
if (!user_id) {
|
|
622
|
+
return null;
|
|
623
|
+
}
|
|
624
|
+
// 2. user_id → 用户状态
|
|
625
|
+
var state = null;
|
|
626
|
+
try {
|
|
627
|
+
state = await mm_state_store.stateAdmin("user").get("user_" + user_id);
|
|
628
|
+
} catch (err) {
|
|
629
|
+
state = null;
|
|
630
|
+
}
|
|
631
|
+
if (!state || !state.user) {
|
|
632
|
+
return null;
|
|
633
|
+
}
|
|
634
|
+
var o = { ...state.user };
|
|
635
|
+
o.token = token;
|
|
636
|
+
o.user_id = String(user_id);
|
|
637
|
+
if (ctx && ctx.session) {
|
|
638
|
+
ctx.session.uuid = ctx.session.uuid || token;
|
|
639
|
+
ctx.session.user = o;
|
|
640
|
+
}
|
|
641
|
+
return o;
|
|
642
|
+
} catch (err) {
|
|
643
|
+
return null;
|
|
644
|
+
}
|
|
551
645
|
};
|
|
552
646
|
|
|
553
647
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mm_api",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "API框架,用于实现web api和mvc模式路由请求,负责配置路由路径、访问权限、校验机制;基于 mm_corejs,内置管理器池,无全局/原型扩展依赖",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -24,11 +24,13 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"mm_corejs": "^1.1.4",
|
|
26
26
|
"mm_dao": "^1.8.2",
|
|
27
|
+
"mm_dict": "^1.0.3",
|
|
27
28
|
"mm_helper": "^1.0.0",
|
|
28
29
|
"mm_machine": "^3.5.4",
|
|
29
30
|
"mm_param": "^1.1.0",
|
|
30
31
|
"mm_ret": "^1.4.8",
|
|
31
|
-
"mm_sql": "^1.8.0"
|
|
32
|
+
"mm_sql": "^1.8.0",
|
|
33
|
+
"mm_state_store": "^1.0.3"
|
|
32
34
|
},
|
|
33
35
|
"scripts": {
|
|
34
36
|
"test": "node test.js && node --test tests/*.test.js"
|