dsh-webui-oauth 0.6.1 → 0.6.2

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/CHANGELOG.md CHANGED
@@ -2,6 +2,42 @@
2
2
 
3
3
  本文件记录每个版本的**用户可见**变更。破坏性变更与升级动作单独标注。
4
4
 
5
+ ## 0.6.2
6
+
7
+ 修复设置页在**切走再切回**时不回显已有配置的问题。
8
+
9
+ ### 修复:切页返回后配置项全空,须手动刷新才显示
10
+
11
+ - **现象**:在 WebUI 里切到别的页面、再切回设置 → 身份认证,用户名、OIDC 入口、
12
+ APP ID 等输入框全部为空;手动刷新整页才恢复正常。
13
+ - **原因**:回填逻辑被一个**模块级**变量 `loadedOnce` 包着("只回填一次")。
14
+ 模块变量只在整页刷新时重置;而 SPA 内切换页面时组件会重新挂载(局部 state 归零)
15
+ 却不会复位该变量,于是整块回填被跳过。
16
+ - **修复**:改为组件内的 `useRef` 记录"本次挂载是否已回填"。组件卸载即失效,
17
+ 切回来会重新回填;同一次挂载内它仍能阻止轮询把用户正在编辑的内容冲掉。
18
+
19
+ ### 回显规则(明确化)
20
+
21
+ 除**密钥**外一律预填:
22
+
23
+ | 字段 | 是否回显 |
24
+ | --- | --- |
25
+ | 用户名 | ✅ |
26
+ | OIDC 入口(issuer) | ✅ |
27
+ | OIDC APP ID(clientId) | ✅ |
28
+ | Scope | ✅ |
29
+ | Redirect Base | ✅ |
30
+ | 完整回调地址 | ✅(0.6.1 起) |
31
+ | **Client Secret** | ❌ **永不回显**(服务端不返回;输入框留空 = 保持不变) |
32
+
33
+ ### 测试
34
+
35
+ - 新增 `test/client-prefill.test.mjs`(11 项):用一个还原了关键 React 语义
36
+ (尤其是 `useRef` 在同一挂载期内返回同一对象、卸载后换新对象)的替身直接驱动
37
+ 真实组件源码,覆盖首次进入、切走切回、连续三次切换、clientSecret 永不回显。
38
+ - 已确认这些用例能抓出修复前的行为(回退旧写法时 4 项 FAIL)。
39
+ - 全量 335 项断言通过。
40
+
5
41
  ## 0.6.1
6
42
 
7
43
  修复 OIDC 配置保存被误拒、以及设置页看不到回调地址的问题。
package/lib/client.js CHANGED
@@ -61,7 +61,18 @@ window.__ModuleLoader__.load({
61
61
  }
62
62
 
63
63
  // ---------------- 设置页(settings.section) ----------------
64
- let loadedOnce = false;
64
+ //
65
+ // 变量命名说明:这里**不再**用模块级的"只回填一次"开关。
66
+ // 曾经的写法是 `let loadedOnce = false` 放在模块作用域,配合
67
+ // `if (!loadedOnce) { ...回填... }`。问题在于模块变量只在【整页刷新】
68
+ // 时重置:用户切到别的页面、再切回设置页时,React 会重新挂载组件
69
+ // (局部 state 归零),但 loadedOnce 仍是 true,于是整块回填被跳过,
70
+ // 表现为"切页回来字段全空、手动刷新才正常"。
71
+ //
72
+ // 正确做法:把"是否已回填"放进组件自身的 state 生命周期。
73
+ // 用一个 ref 记录本次挂载是否已灌过值 —— 组件卸载即失效,
74
+ // 下次挂载自然会重新回填;同时它仍然防止轮询(load 定时刷新)
75
+ // 把用户正在编辑的内容冲掉。
65
76
  function AuthSettings() {
66
77
  const [status, setStatus] = react.useState(null);
67
78
  const [username, setUsername] = react.useState('');
@@ -89,6 +100,10 @@ window.__ModuleLoader__.load({
89
100
  // 服务端算好的完整回调地址(含 scheme/host/port)。原生 OIDC 要求
90
101
  // redirect_uri 与 IdP 登记值精确匹配,少一个字符都会被拒,所以要显示全。
91
102
  const [oidcRedirectUri, setOidcRedirectUri] = react.useState('');
103
+ // 本次挂载是否已灌过初始值。放在组件内(而非模块级):
104
+ // 组件卸载即失效,切页回来会重新回填;同一次挂载内它仍然阻止
105
+ // 轮询把用户正在编辑的内容冲掉。
106
+ const prefilled = react.useRef(false);
92
107
 
93
108
  react.useEffect(() => {
94
109
  let alive = true;
@@ -97,14 +112,18 @@ window.__ModuleLoader__.load({
97
112
  if (!s || s.error) return;
98
113
  setStatus(s);
99
114
  setTtl(String(typeof s.ttl === 'number' ? s.ttl : 12));
100
- if (!loadedOnce) {
101
- loadedOnce = true;
115
+ if (!prefilled.current) {
116
+ prefilled.current = true;
117
+ // 回显规则:除了密钥,其余全部预填。
118
+ // - 用户名、OIDC 入口(issuer)、APP ID(clientId)、Scope、
119
+ // Redirect Base —— 都是非敏感且用户需要看到当前值的。
120
+ // - clientSecret 刻意【不】回显:服务端根本不回传它
121
+ // (见 status 实现),输入框留空即代表"保持不变"。
102
122
  setUsername(s.username || '');
103
123
  const o = (s && s.oidc) || null;
104
124
  setOidcEnabled(!!(o && o.enabled));
105
125
  setOidcIssuer((o && o.issuer) || '');
106
126
  setOidcTrustBrowser(!o || o.trustBrowserOrigin !== false);
107
- // clientSecret 不回传(敏感),clientId/scope/redirectBase 尽量回填
108
127
  setOidcClientId((o && o.clientId) || '');
109
128
  if (o && o.scope) setOidcScope(o.scope);
110
129
  if (o && o.redirectBase) setOidcRedirectBase(o.redirectBase);
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "dsh-webui-oauth",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "node test/redirect-scheme.test.mjs && node test/proxy-host.test.mjs && node test/trusted-origin.test.mjs && node test/oidc.test.mjs && node test/oidc-state-ttl.test.mjs && node test/set-cookie-multi.test.mjs && node test/oidc-integration.test.mjs && node test/oidc-config-store.test.mjs && node test/adopt-data-dir.test.mjs && node test/oidc-ec.test.mjs && node test/jwks-refresh.test.mjs && node test/oidc-bind.test.mjs && node test/client-bundle-id.test.mjs && node test/displace-original.test.mjs"
7
+ "test": "node test/redirect-scheme.test.mjs && node test/proxy-host.test.mjs && node test/trusted-origin.test.mjs && node test/oidc.test.mjs && node test/oidc-state-ttl.test.mjs && node test/set-cookie-multi.test.mjs && node test/oidc-integration.test.mjs && node test/oidc-config-store.test.mjs && node test/adopt-data-dir.test.mjs && node test/oidc-ec.test.mjs && node test/jwks-refresh.test.mjs && node test/oidc-bind.test.mjs && node test/client-bundle-id.test.mjs && node test/client-prefill.test.mjs && node test/displace-original.test.mjs"
8
8
  },
9
9
  "exports": {
10
10
  ".": "./index.js",