mm_api 1.1.3 → 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 +100 -3
- 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();
|
|
@@ -322,7 +325,10 @@ Api.prototype._loadSql = function (file_path) {
|
|
|
322
325
|
if (!cfg) {
|
|
323
326
|
return null;
|
|
324
327
|
}
|
|
325
|
-
|
|
328
|
+
// 实例名必须唯一:mm_mod 的 config 按类名+名称存入共享配置存储,
|
|
329
|
+
// 不同接口的 dao.json 可能同名(如多个 "cms_article"),直接沿用会互相覆盖,
|
|
330
|
+
// 因此强制以接口名命名 Dao 实例
|
|
331
|
+
cfg.name = this.config.name || cfg.name;
|
|
326
332
|
cfg.config_file = p;
|
|
327
333
|
cfg.dir = path.dirname(p);
|
|
328
334
|
if (Dao) {
|
|
@@ -525,15 +531,37 @@ Api.prototype._getUserFromSession = function (ctx) {
|
|
|
525
531
|
return null;
|
|
526
532
|
};
|
|
527
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
|
+
|
|
528
555
|
/**
|
|
529
556
|
* 从 token 中获取用户信息
|
|
557
|
+
* 解析顺序:缓存 → 用户状态存储(mm_dict 映射 / 解码 → mm_state_store)→ 数据库
|
|
530
558
|
* @param {object} ctx 请求上下文
|
|
531
559
|
* @param {object} db 数据管理器
|
|
532
560
|
* @returns {object|null} 用户信息
|
|
533
561
|
* @private
|
|
534
562
|
*/
|
|
535
563
|
Api.prototype._getUserFromToken = async function (params, ctx, options) {
|
|
536
|
-
var token =
|
|
564
|
+
var token = this._getToken(ctx);
|
|
537
565
|
if (!token) {
|
|
538
566
|
return null;
|
|
539
567
|
}
|
|
@@ -544,7 +572,76 @@ Api.prototype._getUserFromToken = async function (params, ctx, options) {
|
|
|
544
572
|
return await this._processUserFromCache(u, ctx, options, token);
|
|
545
573
|
}
|
|
546
574
|
}
|
|
547
|
-
|
|
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
|
+
}
|
|
548
645
|
};
|
|
549
646
|
|
|
550
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"
|