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.
Files changed (2) hide show
  1. package/lib/api.js +96 -2
  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 = ctx.headers[this.config.token_key];
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
- return await this._getUserFromDb(token, ctx, options);
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.4",
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"