@aalis/plugin-webui-server 0.15.0 → 0.17.0

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 (79) hide show
  1. package/dist/attention.d.ts +2 -2
  2. package/dist/attention.d.ts.map +1 -1
  3. package/dist/attention.js +5 -4
  4. package/dist/attention.js.map +1 -1
  5. package/dist/auth.d.ts +13 -4
  6. package/dist/auth.d.ts.map +1 -1
  7. package/dist/auth.js +77 -27
  8. package/dist/auth.js.map +1 -1
  9. package/dist/client-switch-page.d.ts +25 -3
  10. package/dist/client-switch-page.d.ts.map +1 -1
  11. package/dist/client-switch-page.js +49 -19
  12. package/dist/client-switch-page.js.map +1 -1
  13. package/dist/gate.d.ts.map +1 -1
  14. package/dist/gate.js +2 -1
  15. package/dist/gate.js.map +1 -1
  16. package/dist/html.d.ts +15 -0
  17. package/dist/html.d.ts.map +1 -0
  18. package/dist/html.js +38 -0
  19. package/dist/html.js.map +1 -0
  20. package/dist/index.d.ts +4 -1
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +223 -244
  23. package/dist/index.js.map +1 -1
  24. package/dist/layout.d.ts +4 -3
  25. package/dist/layout.d.ts.map +1 -1
  26. package/dist/layout.js +5 -3
  27. package/dist/layout.js.map +1 -1
  28. package/dist/locales/en.d.ts +192 -0
  29. package/dist/locales/en.d.ts.map +1 -0
  30. package/dist/locales/en.js +192 -0
  31. package/dist/locales/en.js.map +1 -0
  32. package/dist/localize.d.ts +24 -0
  33. package/dist/localize.d.ts.map +1 -0
  34. package/dist/localize.js +68 -0
  35. package/dist/localize.js.map +1 -0
  36. package/dist/page-check.d.ts.map +1 -1
  37. package/dist/page-check.js +32 -25
  38. package/dist/page-check.js.map +1 -1
  39. package/dist/pages.d.ts +9 -7
  40. package/dist/pages.d.ts.map +1 -1
  41. package/dist/pages.js +77 -61
  42. package/dist/pages.js.map +1 -1
  43. package/dist/route.d.ts +5 -2
  44. package/dist/route.d.ts.map +1 -1
  45. package/dist/route.js +5 -2
  46. package/dist/route.js.map +1 -1
  47. package/dist/routes/files.d.ts.map +1 -1
  48. package/dist/routes/files.js +4 -3
  49. package/dist/routes/files.js.map +1 -1
  50. package/dist/routes/frames.js +3 -3
  51. package/dist/routes/frames.js.map +1 -1
  52. package/dist/routes/i18n.d.ts +20 -0
  53. package/dist/routes/i18n.d.ts.map +1 -0
  54. package/dist/routes/i18n.js +78 -0
  55. package/dist/routes/i18n.js.map +1 -0
  56. package/dist/routes/marketplace.d.ts.map +1 -1
  57. package/dist/routes/marketplace.js +27 -29
  58. package/dist/routes/marketplace.js.map +1 -1
  59. package/dist/routes/media.d.ts +3 -0
  60. package/dist/routes/media.d.ts.map +1 -1
  61. package/dist/routes/media.js +29 -26
  62. package/dist/routes/media.js.map +1 -1
  63. package/dist/routes/pages.d.ts +4 -2
  64. package/dist/routes/pages.d.ts.map +1 -1
  65. package/dist/routes/pages.js +36 -18
  66. package/dist/routes/pages.js.map +1 -1
  67. package/dist/routes/plugins.d.ts +5 -9
  68. package/dist/routes/plugins.d.ts.map +1 -1
  69. package/dist/routes/plugins.js +114 -129
  70. package/dist/routes/plugins.js.map +1 -1
  71. package/dist/routes/proxy.d.ts +3 -2
  72. package/dist/routes/proxy.d.ts.map +1 -1
  73. package/dist/routes/proxy.js +62 -41
  74. package/dist/routes/proxy.js.map +1 -1
  75. package/dist/texts.d.ts +383 -0
  76. package/dist/texts.d.ts.map +1 -0
  77. package/dist/texts.js +195 -0
  78. package/dist/texts.js.map +1 -0
  79. package/package.json +26 -23
@@ -1,6 +1,6 @@
1
1
  import type { Approval } from '@aalis/api-approval';
2
2
  import type { HostConfig } from '@aalis/api-host-config';
3
- import type { SessionManagerService } from '@aalis/api-session-manager';
3
+ import { type SessionManagerService } from '@aalis/api-session-manager';
4
4
  import type { AttentionItem, Notice, PluginBlockers, WebuiAdminEvent } from '@aalis/api-webui';
5
5
  import type { PluginManagerService, PluginStatusEntry, ServiceSelection, Services } from '@aalis/core';
6
6
  /** 算插件没起来的原因要读的:插件状态与定义、当前有提供者的服务名、配置文档(宿主不提供时读运行态配置) */
@@ -14,7 +14,7 @@ export declare function blockedStatus({ plugins, services, doc }: BlockerSources
14
14
  interface AttentionDeps {
15
15
  /** 推出未结的审批;审批服务不在时没有 */
16
16
  approvals(): readonly Approval[];
17
- /** 会话管理:审批所在会话的标题 */
17
+ /** 会话管理:审批所在会话的标题(没有标题时是会话的显示名称) */
18
18
  sessions: Pick<ServiceSelection<Pick<SessionManagerService, 'getSession'>>, 'present' | 'use'>;
19
19
  /** 插件状态与没起来的原因;插件管理服务不在时为空 */
20
20
  plugins(): ReadonlyArray<PluginStatusEntry & PluginBlockers>;
@@ -1 +1 @@
1
- {"version":3,"file":"attention.d.ts","sourceRoot":"","sources":["../src/attention.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvG,yDAAyD;AACzD,UAAU,cAAc;IACtB,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,WAAW,GAAG,WAAW,CAAC,CAAC;IAC/D,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAClC,GAAG,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;CAC3C;AAED,0BAA0B;AAC1B,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,cAAc,GAAG,KAAK,CAAC,iBAAiB,GAAG,cAAc,CAAC,CAgBnH;AAED,UAAU,aAAa;IACrB,wBAAwB;IACxB,SAAS,IAAI,SAAS,QAAQ,EAAE,CAAC;IACjC,qBAAqB;IACrB,QAAQ,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,qBAAqB,EAAE,YAAY,CAAC,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC,CAAC;IAC/F,8BAA8B;IAC9B,OAAO,IAAI,aAAa,CAAC,iBAAiB,GAAG,cAAc,CAAC,CAAC;IAC7D,mBAAmB;IACnB,OAAO,IAAI,aAAa,CAAC,MAAM,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,IAAI,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;CACpC;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa;IA2B/C,2BAA2B;iBAChB,aAAa,EAAE;IAQ1B,eAAe;;IAEf,6BAA6B;sBACX,IAAI;EAOzB"}
1
+ {"version":3,"file":"attention.d.ts","sourceRoot":"","sources":["../src/attention.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,KAAK,qBAAqB,EAAgB,MAAM,4BAA4B,CAAC;AACtF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvG,yDAAyD;AACzD,UAAU,cAAc;IACtB,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,WAAW,GAAG,WAAW,CAAC,CAAC;IAC/D,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAClC,GAAG,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;CAC3C;AAED,0BAA0B;AAC1B,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,cAAc,GAAG,KAAK,CAAC,iBAAiB,GAAG,cAAc,CAAC,CAgBnH;AAED,UAAU,aAAa;IACrB,wBAAwB;IACxB,SAAS,IAAI,SAAS,QAAQ,EAAE,CAAC;IACjC,oCAAoC;IACpC,QAAQ,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,qBAAqB,EAAE,YAAY,CAAC,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC,CAAC;IAC/F,8BAA8B;IAC9B,OAAO,IAAI,aAAa,CAAC,iBAAiB,GAAG,cAAc,CAAC,CAAC;IAC7D,mBAAmB;IACnB,OAAO,IAAI,aAAa,CAAC,MAAM,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,IAAI,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;CACpC;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa;IA2B/C,2BAA2B;iBAChB,aAAa,EAAE;IAQ1B,eAAe;;IAEf,6BAA6B;sBACX,IAAI;EAOzB"}
package/dist/attention.js CHANGED
@@ -8,7 +8,8 @@
8
8
  // 经 GET /api/attention 给出。变了就经 /admin 推 attention.changed:审批推出或结算是变化,提示的登记与撤回由页面登记表推
9
9
  // (pages.ts);插件登记表每次重算之后比一次故障(连同链与根),变了才推(重算很频繁,多数与故障无关)。
10
10
  // ============================================================
11
- import { unmetDependencies } from '@aalis/api-doctor';
11
+ import { failureText, unmetDependencies } from '@aalis/api-doctor';
12
+ import { sessionLabel } from '@aalis/api-session-manager';
12
13
  import { validateConfig } from '@aalis/schema-config';
13
14
  /** 插件状态快照,每个实例带上没起来的原因 */
14
15
  export function blockedStatus({ plugins, services, doc }) {
@@ -29,13 +30,13 @@ export function blockedStatus({ plugins, services, doc }) {
29
30
  }));
30
31
  }
31
32
  export function createAttention(deps) {
32
- const faults = () => deps.plugins().flatMap(({ instanceId, state, error, lacking, waiting, unconfigured }) => state === 'error' || (state === 'pending' && lacking.length > 0)
33
+ const faults = () => deps.plugins().flatMap(({ instanceId, state, error, failure, lacking, waiting, unconfigured }) => state === 'error' || (state === 'pending' && lacking.length > 0)
33
34
  ? [
34
35
  {
35
36
  kind: 'plugin',
36
37
  instance: instanceId,
37
38
  state,
38
- ...(error !== undefined && { error }),
39
+ ...(error !== undefined && { error: failureText({ failure, error }) }),
39
40
  lacking,
40
41
  waiting,
41
42
  unconfigured,
@@ -44,7 +45,7 @@ export function createAttention(deps) {
44
45
  : []);
45
46
  const titleOf = (sessionId) => {
46
47
  const info = deps.sessions.present ? deps.sessions.use.getSession(sessionId) : undefined;
47
- return info && (info.title || info.name);
48
+ return info && (info.title || sessionLabel(info));
48
49
  };
49
50
  let reported = JSON.stringify(faults());
50
51
  const changed = () => deps.send({ type: 'attention.changed' });
@@ -1 +1 @@
1
- {"version":3,"file":"attention.js","sourceRoot":"","sources":["../src/attention.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,iCAAiC;AACjC,EAAE;AACF,oEAAoE;AACpE,8DAA8D;AAC9D,EAAE;AACF,+DAA+D;AAC/D,qFAAqF;AACrF,0DAA0D;AAC1D,+DAA+D;AAG/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAKtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAStD,0BAA0B;AAC1B,MAAM,UAAU,aAAa,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAkB;IACtE,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAC1D,2DAA2D;IAC3D,MAAM,YAAY,GAAG,CAAC,UAAkB,EAAE,EAAE;QAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC;QAC7E,OAAO,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,YAAY,EAAE,MAAM,CAAC;aAC1D,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC;aACzC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC,CAAC;IACF,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1B,GAAG,KAAK;QACR,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAChE,YAAY,EAAE,KAAK,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE;KAC5E,CAAC,CAAC,CAAC;AACN,CAAC;AAcD,MAAM,UAAU,eAAe,CAAC,IAAmB;IACjD,MAAM,MAAM,GAAG,GAAoB,EAAE,CACnC,IAAI,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,CACtF,KAAK,KAAK,OAAO,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QAC9D,CAAC,CAAC;YACE;gBACE,IAAI,EAAE,QAAiB;gBACvB,QAAQ,EAAE,UAAU;gBACpB,KAAK;gBACL,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,CAAC;gBACrC,OAAO;gBACP,OAAO;gBACP,YAAY;aACb;SACF;QACH,CAAC,CAAC,EAAE,CACP,CAAC;IAEJ,MAAM,OAAO,GAAG,CAAC,SAAiB,EAAE,EAAE;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACzF,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC,CAAC;IAEF,IAAI,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAE/D,OAAO;QACL,2BAA2B;QAC3B,KAAK,EAAE,GAAoB,EAAE,CAAC;YAC5B,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE;gBAClD,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;gBACnC,OAAO,EAAE,IAAI,EAAE,UAAmB,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC;YACvG,CAAC,CAAC;YACF,GAAG,MAAM,EAAE;YACX,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAiB,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;SAC1E;QACD,eAAe;QACf,OAAO;QACP,6BAA6B;QAC7B,cAAc;YACZ,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;YACrC,IAAI,GAAG,KAAK,QAAQ;gBAAE,OAAO;YAC7B,QAAQ,GAAG,GAAG,CAAC;YACf,OAAO,EAAE,CAAC;QACZ,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"attention.js","sourceRoot":"","sources":["../src/attention.ts"],"names":[],"mappings":"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"}
package/dist/auth.d.ts CHANGED
@@ -2,8 +2,14 @@ import type { IncomingMessage } from 'node:http';
2
2
  import type { UserIdentity } from '@aalis/api-authority';
3
3
  import type { ProcessService } from '@aalis/api-process';
4
4
  import type express from 'express';
5
+ import type { Localizer } from './localize.js';
5
6
  /** 失败计数表最多记这么多个地址:满了再记新地址时丢掉最早的那条,内存有界,也不因此变成全局锁定 */
6
7
  export declare const LOGIN_FAILURE_ADDRESSES_MAX = 10000;
8
+ /**
9
+ * 配置里的一项是不是主机名(allowedHosts 的写法):可带端口,不带协议、用户名、路径、查询与片段,去掉首尾空白后解析得出。
10
+ * 带协议的照 Host 头的写法拼出来会把协议名当主机名(`https://x` 成了 `https`),真正要认的主机名照旧被拒
11
+ */
12
+ export declare function isHostName(entry: string): boolean;
7
13
  /**
8
14
  * 请求的来源能不能收,WebSocket 升级与改状态的请求(非 GET)共用。浏览器发起的握手与 POST 一律带 Origin,只收与本服务同源的:
9
15
  * Origin 的主机与端口等于请求的 Host。同一主机别的端口上的网页与本服务同站,SameSite cookie 会随它的请求发出,
@@ -14,8 +20,8 @@ export declare const LOGIN_FAILURE_ADDRESSES_MAX = 10000;
14
20
  export declare function originAllowed(req: Pick<IncomingMessage, 'headers'>): boolean;
15
21
  export interface AuthSystem {
16
22
  /**
17
- * 挂上认证,要在 JSON 解析之后、其余路由之前:改状态的请求先核来源,再是登录页的脚本、`?token=` 一键登录、登录、
18
- * 登录状态与注销,其余未登录的请求一律拦下(API 回 401,GET 页面回登录页)
23
+ * 挂上认证,要在 JSON 解析之后、其余路由之前:先核 Host,再是改状态的请求核来源,然后是登录页的脚本、`?token=` 一键登录、
24
+ * 登录、登录状态与注销,其余未登录的请求一律拦下(API 回 401,GET 页面回登录页)
19
25
  */
20
26
  install(expressApp: express.Express): void;
21
27
  /** 校验 WebSocket 升级请求是否已认证(cookie 读取) */
@@ -29,15 +35,18 @@ export interface AuthSystem {
29
35
  * - token 由调用方经 getToken 提供,每次校验现取:persist 模式下 storage 晚上线时,调用方会把
30
36
  * 启动时的临时 token 换成读回的持久化 token(见 index.ts 的 token 解析)
31
37
  * - HttpOnly + SameSite=Strict cookie;`?token=` 一键登录;同源 POST /api/auth/login 提交
38
+ * - 请求的 Host 先按 {@link hostAllowed} 核对,hostNames 是 IP 地址与 localhost 之外认的主机名(监听地址与 allowedHosts);
39
+ * 不认的回 421,不进登录的比对与计数,带着 cookie 也不放行
32
40
  * - 改状态的请求(非 GET、HEAD、OPTIONS)按 {@link originAllowed} 校验来源,与 WebSocket 升级同一个判定:SameSite 按站判、
33
41
  * 不分端口,同一主机别的端口上的网页发一个简单 POST 就会带上 cookie
34
42
  * - `?token=` 与登录接口按来源地址限速:失败计数见 LOGIN_MAX_FAILURES、LOGIN_FAILURE_WINDOW_MS,成功清零。
35
- * 别的网页借 owner 的浏览器发起的登录(跨源的 POST、别的站点打开的 `?token=`)不比对也不计数,免得别人替 owner 把
43
+ * 别的网页借 owner 的浏览器发起的登录(跨源的 POST、别的站点打开的 `?token=`、DNS 重绑定)不比对也不计数,免得别人替 owner 把
36
44
  * 地址锁住。带 cookie 的请求不计数:各种模式的 token 都够长(随机生成的 24 字节,固定的至少 32 个字符),
37
45
  * 按 cookie 逐个猜猜不中;对 cookie 也锁定的话,共用一个来源地址(同一个反向代理)的已登录页面会被别人一起锁住
38
46
  * - 身份恒为 `webui:console`(owner 级,单人模式语义)
47
+ * - 登录页与回应里的文字按全局层的语言(localizer)
39
48
  */
40
- export declare function createAuthSystem(getToken: () => string): AuthSystem;
49
+ export declare function createAuthSystem(getToken: () => string, localizer: Pick<Localizer, 'render' | 'languages'>, hostNames: readonly string[]): AuthSystem;
41
50
  /**
42
51
  * 跨平台打开默认浏览器到指定 URL(无外部依赖)
43
52
  * 失败静默;此为便利功能,不影响服务启动。
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AASnC,qDAAqD;AACrD,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAclD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,GAAG,OAAO,CAO5E;AAmGD,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAC3C,wCAAwC;IACxC,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC;IAC9C,0EAA0E;IAC1E,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,GAAG,YAAY,GAAG,SAAS,CAAC;CAC3E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,MAAM,GAAG,UAAU,CA4InE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAwBnE"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGzD,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAU/C,qDAAqD;AACrD,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAiBlD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEjD;AAgBD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,GAAG,OAAO,CAO5E;AA2GD,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAC3C,wCAAwC;IACxC,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC;IAC9C,0EAA0E;IAC1E,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,GAAG,YAAY,GAAG,SAAS,CAAC;CAC3E;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,MAAM,EACtB,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,GAAG,WAAW,CAAC,EAClD,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,UAAU,CA0JZ;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAwBnE"}
package/dist/auth.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import { createHash, timingSafeEqual } from 'node:crypto';
2
+ import { isIP } from 'node:net';
2
3
  import { BUILTIN_THEMES, DEFAULT_THEMES } from '@aalis/api-webui';
4
+ import { escapeHtml, pageLanguageOf, textsBlock } from './html.js';
3
5
  import { route } from './route.js';
6
+ import { t } from './texts.js';
4
7
  const TOKEN_COOKIE = 'aalis_webui_token';
5
8
  /** 同一来源地址在一个窗口内登录失败满这么多次,到窗口结束前它的登录一律回 429(正确的 token 也不收) */
6
9
  const LOGIN_MAX_FAILURES = 10;
@@ -16,6 +19,29 @@ function tokenEquals(given, expected) {
16
19
  const digest = (s) => createHash('sha256').update(s).digest();
17
20
  return timingSafeEqual(digest(given), digest(expected));
18
21
  }
22
+ /** Host 头(或配置里同样写法)的主机名:小写,国际化域名转成 punycode,IPv6 带方括号;解析不了的没有 */
23
+ function hostnameOf(host) {
24
+ const url = `http://${host}`;
25
+ return URL.canParse(url) ? new URL(url).hostname : undefined;
26
+ }
27
+ /**
28
+ * 配置里的一项是不是主机名(allowedHosts 的写法):可带端口,不带协议、用户名、路径、查询与片段,去掉首尾空白后解析得出。
29
+ * 带协议的照 Host 头的写法拼出来会把协议名当主机名(`https://x` 成了 `https`),真正要认的主机名照旧被拒
30
+ */
31
+ export function isHostName(entry) {
32
+ return !/[/\\?#@]/.test(entry) && hostnameOf(entry.trim()) !== undefined;
33
+ }
34
+ /**
35
+ * 请求的 Host 能不能收:主机名是 IP 地址、localhost 或 names 里的一个(监听地址与 allowedHosts)。DNS 重绑定的网页把自己的
36
+ * 域名解析到本机后,借 owner 的浏览器发来的请求 Origin 与 Host 都是那个域名,同源判定拦不住,靠这一关拦下;
37
+ * IP 地址重绑定不了,局域网按 IP 访问照常。
38
+ */
39
+ function hostAllowed(req, names) {
40
+ const name = req.headers.host === undefined ? undefined : hostnameOf(req.headers.host);
41
+ if (name === undefined)
42
+ return false;
43
+ return name === 'localhost' || isIP(name.replace(/^\[(.*)\]$/, '$1')) !== 0 || names.has(name);
44
+ }
19
45
  /** 不改状态的请求方法:不校验来源 */
20
46
  const SAFE_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);
21
47
  /**
@@ -70,14 +96,15 @@ function buildClearCookie(name) {
70
96
  }
71
97
  /** 登录页的脚本:文档级 CSP 只许同源脚本,不内联,由这个地址给出(不需登录) */
72
98
  const LOGIN_SCRIPT_PATH = '/api/auth/login.js';
73
- /** 提交 POST /api/auth/login,成功后刷新到 / */
74
- const LOGIN_SCRIPT = `const f=document.getElementById('f'),t=document.getElementById('t'),b=document.getElementById('b'),e=document.getElementById('e');
99
+ /** 提交 POST /api/auth/login,成功后刷新到 /;给人看的文字取自页面的 texts 块 */
100
+ const LOGIN_SCRIPT = `const T=JSON.parse(document.getElementById('texts').textContent);
101
+ const f=document.getElementById('f'),t=document.getElementById('t'),b=document.getElementById('b'),e=document.getElementById('e');
75
102
  f.addEventListener('submit',async ev=>{
76
103
  ev.preventDefault();e.textContent='';b.disabled=true;
77
104
  try{
78
105
  const r=await fetch('/api/auth/login',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({token:t.value.trim()})});
79
- if(r.ok){location.replace('/');}else{const j=await r.json().catch(()=>({}));e.textContent=j.error||'token 不正确';b.disabled=false;t.select();}
80
- }catch(err){e.textContent='网络错误';b.disabled=false;}
106
+ if(r.ok){location.replace('/');}else{const j=await r.json().catch(()=>({}));e.textContent=j.error||T.tokenWrong;b.disabled=false;t.select();}
107
+ }catch(err){e.textContent=T.networkError;b.disabled=false;}
81
108
  });
82
109
  `;
83
110
  /** 一个内置主题的颜色令牌,写成 CSS 自定义属性的声明 */
@@ -102,44 +129,55 @@ button{height:2.25rem;font:inherit;font-weight:500;color:var(--color-on-accent);
102
129
  button:hover{background:var(--color-accent-hover)}
103
130
  button:disabled{opacity:0.6;cursor:wait}
104
131
  .err{min-height:1.375rem;color:var(--color-danger-text)}`;
105
- /** 登录页:只引用同源的登录脚本,不引入别的资源 */
106
- function loginPageHtml(reason) {
107
- const note = reason ? `<p class="note">${escapeHtml(reason)}</p>` : '';
108
- return `<!DOCTYPE html><html lang="zh-CN"><head>
109
- <meta charset="utf-8"><title>Aalis WebUI 登录</title>
132
+ /** 登录页的文字;pageLanguage 是渲染时实际用的语言,写进 <html lang> */
133
+ const LOGIN_TEXTS = {
134
+ lang: t('pageLanguage'),
135
+ title: t('loginTitle'),
136
+ hint: t('loginHint'),
137
+ placeholder: t('tokenPlaceholder'),
138
+ button: t('loginButton'),
139
+ script: { tokenWrong: t('tokenWrong'), networkError: t('networkError') },
140
+ };
141
+ /** 登录页:只引用同源的登录脚本,不引入别的资源。text 是渲染过的文字,note 是这次要说明的一句 */
142
+ function loginPageHtml(text) {
143
+ const note = text.note ? `<p class="note">${escapeHtml(text.note)}</p>` : '';
144
+ return `<!DOCTYPE html><html lang="${escapeHtml(text.lang)}"><head>
145
+ <meta charset="utf-8"><title>${escapeHtml(text.title)}</title>
110
146
  <meta name="viewport" content="width=device-width,initial-scale=1">
111
147
  <style>
112
148
  ${LOGIN_STYLE}
113
149
  </style></head>
114
150
  <body><form id="f">
115
151
  <h1>Aalis WebUI</h1>
116
- <p>访问 token 在家目录的 state/webui/access.txt 里,启动日志「访问凭据已写入」那行给出它的完整路径;tokenMode 为 fixed 时它是配置项 fixedToken,启动后值存在家目录的 secrets.yaml 里(配置文件里是引用)。</p>
152
+ <p>${escapeHtml(text.hint)}</p>
117
153
  ${note}
118
- <input id="t" type="password" autocomplete="off" placeholder="访问 token" autofocus required>
119
- <button type="submit" id="b">登录</button>
154
+ <input id="t" type="password" autocomplete="off" placeholder="${escapeHtml(text.placeholder)}" autofocus required>
155
+ <button type="submit" id="b">${escapeHtml(text.button)}</button>
120
156
  <div class="err" id="e"></div>
121
157
  </form>
158
+ ${textsBlock(text.script)}
122
159
  <script src="${LOGIN_SCRIPT_PATH}"></script></body></html>`;
123
160
  }
124
- function escapeHtml(s) {
125
- return s.replace(/[&<>"']/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[c]);
126
- }
127
161
  /**
128
162
  * 创建单 token 认证系统(单 owner)。
129
163
  *
130
164
  * - token 由调用方经 getToken 提供,每次校验现取:persist 模式下 storage 晚上线时,调用方会把
131
165
  * 启动时的临时 token 换成读回的持久化 token(见 index.ts 的 token 解析)
132
166
  * - HttpOnly + SameSite=Strict cookie;`?token=` 一键登录;同源 POST /api/auth/login 提交
167
+ * - 请求的 Host 先按 {@link hostAllowed} 核对,hostNames 是 IP 地址与 localhost 之外认的主机名(监听地址与 allowedHosts);
168
+ * 不认的回 421,不进登录的比对与计数,带着 cookie 也不放行
133
169
  * - 改状态的请求(非 GET、HEAD、OPTIONS)按 {@link originAllowed} 校验来源,与 WebSocket 升级同一个判定:SameSite 按站判、
134
170
  * 不分端口,同一主机别的端口上的网页发一个简单 POST 就会带上 cookie
135
171
  * - `?token=` 与登录接口按来源地址限速:失败计数见 LOGIN_MAX_FAILURES、LOGIN_FAILURE_WINDOW_MS,成功清零。
136
- * 别的网页借 owner 的浏览器发起的登录(跨源的 POST、别的站点打开的 `?token=`)不比对也不计数,免得别人替 owner 把
172
+ * 别的网页借 owner 的浏览器发起的登录(跨源的 POST、别的站点打开的 `?token=`、DNS 重绑定)不比对也不计数,免得别人替 owner 把
137
173
  * 地址锁住。带 cookie 的请求不计数:各种模式的 token 都够长(随机生成的 24 字节,固定的至少 32 个字符),
138
174
  * 按 cookie 逐个猜猜不中;对 cookie 也锁定的话,共用一个来源地址(同一个反向代理)的已登录页面会被别人一起锁住
139
175
  * - 身份恒为 `webui:console`(owner 级,单人模式语义)
176
+ * - 登录页与回应里的文字按全局层的语言(localizer)
140
177
  */
141
- export function createAuthSystem(getToken) {
178
+ export function createAuthSystem(getToken, localizer, hostNames) {
142
179
  const cookieMaxAge = 30 * 24 * 3600; // 30d;进程重启 token 轮换后无效
180
+ const names = new Set(hostNames.flatMap(name => hostnameOf(name.trim()) ?? []));
143
181
  // 登录失败按来源地址计数。本机回环也计数:经同机反向代理来的请求全是回环地址,豁免回环等于不限速;
144
182
  // owner 自己输错满额也只等到窗口结束,已登录的页面不受影响。
145
183
  // 时间取单调时钟,键的插入顺序就是窗口结束的先后,过期的从表头剪掉;表满时也从表头丢,最多 LOGIN_FAILURE_ADDRESSES_MAX 条。
@@ -170,7 +208,12 @@ export function createAuthSystem(getToken) {
170
208
  function rejectLocked(res, waitMs) {
171
209
  res.status(429);
172
210
  res.setHeader('Retry-After', String(Math.ceil(waitMs / 1000)));
173
- return `登录失败次数过多,请 ${Math.ceil(waitMs / 60_000)} 分钟后再试。`;
211
+ return t('tooManyFailures', { minutes: Math.ceil(waitMs / 60_000) });
212
+ }
213
+ /** 登录页,note 是要说明的一句 */
214
+ function loginPage(note) {
215
+ const text = localizer.render({ ...LOGIN_TEXTS, note });
216
+ return loginPageHtml({ ...text, lang: pageLanguageOf(text.lang, localizer.languages()) });
174
217
  }
175
218
  function tokenAuthed(req) {
176
219
  const cookieToken = parseCookieValue(req.headers.cookie, TOKEN_COOKIE);
@@ -181,13 +224,17 @@ export function createAuthSystem(getToken) {
181
224
  }
182
225
  const addressOf = (req) => req.socket.remoteAddress ?? '';
183
226
  function install(expressApp) {
184
- // 改状态的请求先看来源:别的网页借 owner 的浏览器发来的(带着 cookie)一律拒,登录与注销也一样
227
+ // 先核 Host:DNS 重绑定的网页发来的请求在这里拦下
228
+ expressApp.use((req, res, next) => {
229
+ if (hostAllowed(req, names))
230
+ return next();
231
+ res.status(421).json({ error: t('hostNotAllowed') });
232
+ });
233
+ // 改状态的请求再看来源:别的网页借 owner 的浏览器发来的(带着 cookie)一律拒,登录与注销也一样
185
234
  expressApp.use((req, res, next) => {
186
235
  if (SAFE_METHODS.has(req.method) || originAllowed(req))
187
236
  return next();
188
- res
189
- .status(403)
190
- .json({ error: '请求来源与本服务不同源(经反向代理访问时,代理要转发原始的 Host)' });
237
+ res.status(403).json({ error: t('crossOrigin') });
191
238
  });
192
239
  // 登录页的脚本不需登录
193
240
  route(expressApp, 'GET /api/auth/login.js', (_req, res) => {
@@ -203,7 +250,7 @@ export function createAuthSystem(getToken) {
203
250
  const waitMs = lockedFor(address);
204
251
  if (waitMs > 0) {
205
252
  const note = rejectLocked(res, waitMs);
206
- res.type('html').send(loginPageHtml(note));
253
+ res.type('html').send(loginPage(note));
207
254
  return;
208
255
  }
209
256
  const token = getToken();
@@ -217,7 +264,10 @@ export function createAuthSystem(getToken) {
217
264
  return;
218
265
  }
219
266
  recordFailure(address);
220
- res.status(401).type('html').send(loginPageHtml('URL 中的 token 不正确,请手动输入。'));
267
+ res
268
+ .status(401)
269
+ .type('html')
270
+ .send(loginPage(t('urlTokenWrong')));
221
271
  });
222
272
  // 登录:{ token }。跨源的已在上面拒掉,不计数
223
273
  route(expressApp, 'POST /api/auth/login', (req, res) => {
@@ -236,7 +286,7 @@ export function createAuthSystem(getToken) {
236
286
  }
237
287
  else {
238
288
  recordFailure(address);
239
- res.status(401).json({ error: 'token 不正确' });
289
+ res.status(401).json({ error: t('tokenWrong') });
240
290
  }
241
291
  });
242
292
  // 登录状态(含当前身份,供前端顶栏展示)
@@ -254,11 +304,11 @@ export function createAuthSystem(getToken) {
254
304
  if (tokenAuthed(req))
255
305
  return next();
256
306
  if (req.path.startsWith('/api/')) {
257
- res.status(401).json({ error: 'unauthenticated' });
307
+ res.status(401).json({ error: t('unauthenticated') });
258
308
  return;
259
309
  }
260
310
  if (req.method === 'GET') {
261
- res.status(401).type('html').send(loginPageHtml());
311
+ res.status(401).type('html').send(loginPage());
262
312
  return;
263
313
  }
264
314
  res.status(401).end();
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,27 @@
1
+ import type { Localized } from '@aalis/schema-i18n';
1
2
  /** 前端切换恢复页的脚本:文档级 CSP 只许同源脚本,由 `/__clients.js` 给出 */
2
- export declare const CLIENT_SWITCH_SCRIPT = "(function () {\n var SVC = 'webui-client';\n var PREFER = '/api/services/' + SVC + '/prefer';\n var sel = document.getElementById('client');\n var btn = document.getElementById('go');\n var msg = document.getElementById('msg');\n function setMsg(t, err) { msg.textContent = t; msg.className = err ? 'err' : 'ok'; }\n function load() {\n fetch('/api/services', { headers: { Accept: 'application/json' } })\n .then(function (r) {\n if (!r.ok) throw new Error('\u8BFB\u53D6\u670D\u52A1\u5217\u8868\u5931\u8D25\uFF08HTTP ' + r.status + '\uFF09');\n return r.json();\n })\n .then(function (data) {\n var svc = data && data.services && data.services[SVC];\n var providers = (svc && svc.providers) || [];\n if (!providers.length) {\n setMsg('\u672A\u53D1\u73B0\u4EFB\u4F55\u524D\u7AEF\uFF08webui-client provider\uFF09\u3002\u8BF7\u5148\u5B89\u88C5\u4E00\u4E2A aalis.client \u5305\u3002', true);\n btn.disabled = true;\n sel.innerHTML = '';\n return;\n }\n var active = (svc && svc.preferred) || providers[0].contextId;\n sel.innerHTML = '';\n providers.forEach(function (p) {\n var o = document.createElement('option');\n o.value = p.contextId;\n o.textContent = (p.displayName || p.label || p.contextId) + (p.contextId === active ? '\uFF08\u5F53\u524D\uFF09' : '');\n if (p.contextId === active) o.selected = true;\n sel.appendChild(o);\n });\n })\n .catch(function (e) { setMsg(String((e && e.message) || e), true); });\n }\n btn.addEventListener('click', function () {\n var contextId = sel.value;\n if (!contextId) return;\n btn.disabled = true;\n setMsg('\u5207\u6362\u4E2D\u2026', false);\n fetch(PREFER, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ contextId: contextId })\n })\n .then(function (r) {\n if (r.ok) { setMsg('\u5DF2\u5207\u6362\uFF0C\u6B63\u5728\u8DF3\u8F6C\u2026', false); location.href = '/'; return; }\n return r.json().catch(function () { return {}; }).then(function (j) {\n var detail = (j && j.error) || ('HTTP ' + r.status);\n var hint = (r.status === 401 || r.status === 403) ? '\uFF08\u9700\u8981 owner \u6743\u9650\uFF1A\u8BF7\u7528\u4E00\u952E\u767B\u5F55\u94FE\u63A5\u6253\u5F00 WebUI \u540E\u518D\u8BD5\uFF09' : '';\n setMsg('\u5207\u6362\u5931\u8D25\uFF1A' + detail + hint, true);\n btn.disabled = false;\n });\n })\n .catch(function (e) { setMsg('\u5207\u6362\u8BF7\u6C42\u51FA\u9519\uFF1A' + String((e && e.message) || e), true); btn.disabled = false; });\n });\n load();\n})();\n";
3
- /** 渲染前端切换恢复页的完整 HTML 文档(无运行时入参,数据由页面自身 fetch)。 */
4
- export declare function renderClientSwitchPage(): string;
3
+ export declare const CLIENT_SWITCH_SCRIPT = "(function () {\n var SVC = 'webui-client';\n var PREFER = '/api/services/' + SVC + '/prefer';\n var T = JSON.parse(document.getElementById('texts').textContent);\n var sel = document.getElementById('client');\n var btn = document.getElementById('go');\n var msg = document.getElementById('msg');\n function fill(text, values) {\n return text.replace(/\\{(\\w+)\\}/g, function (m, k) { return k in values ? String(values[k]) : m; });\n }\n function setMsg(t, err) { msg.textContent = t; msg.className = err ? 'err' : 'ok'; }\n function load() {\n fetch('/api/services', { headers: { Accept: 'application/json' } })\n .then(function (r) {\n if (!r.ok) throw new Error(fill(T.listFailed, { status: r.status }));\n return r.json();\n })\n .then(function (data) {\n var svc = data && data.services && data.services[SVC];\n var providers = (svc && svc.providers) || [];\n if (!providers.length) {\n setMsg(T.noClients, true);\n btn.disabled = true;\n sel.innerHTML = '';\n return;\n }\n var active = (svc && svc.preferred) || providers[0].contextId;\n sel.innerHTML = '';\n providers.forEach(function (p) {\n var o = document.createElement('option');\n var name = p.displayName || p.label || p.contextId;\n o.value = p.contextId;\n o.textContent = p.contextId === active ? fill(T.current, { name: name }) : name;\n if (p.contextId === active) o.selected = true;\n sel.appendChild(o);\n });\n })\n .catch(function (e) { setMsg(String((e && e.message) || e), true); });\n }\n btn.addEventListener('click', function () {\n var contextId = sel.value;\n if (!contextId) return;\n btn.disabled = true;\n setMsg(T.switching, false);\n fetch(PREFER, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ contextId: contextId })\n })\n .then(function (r) {\n if (r.ok) { setMsg(T.switched, false); location.href = '/'; return; }\n return r.json().catch(function () { return {}; }).then(function (j) {\n var detail = (j && j.error) || ('HTTP ' + r.status);\n var hint = (r.status === 401 || r.status === 403) ? T.ownerHint : '';\n setMsg(fill(T.failed, { detail: detail, hint: hint }), true);\n btn.disabled = false;\n });\n })\n .catch(function (e) { setMsg(fill(T.error, { error: String((e && e.message) || e) }), true); btn.disabled = false; });\n });\n load();\n})();\n";
4
+ /** 恢复页的文字;带参数的以 {名} 占位交给脚本填。pageLanguage 是渲染时实际用的语言,写进 <html lang> */
5
+ export declare const CLIENT_SWITCH_TEXTS: {
6
+ lang: import("@aalis/schema-i18n").TextRef;
7
+ title: import("@aalis/schema-i18n").TextRef;
8
+ heading: import("@aalis/schema-i18n").TextRef;
9
+ intro: import("@aalis/schema-i18n").TextRef;
10
+ label: import("@aalis/schema-i18n").TextRef;
11
+ loading: import("@aalis/schema-i18n").TextRef;
12
+ button: import("@aalis/schema-i18n").TextRef;
13
+ back: import("@aalis/schema-i18n").TextRef;
14
+ script: {
15
+ listFailed: import("@aalis/schema-i18n").TextRef;
16
+ noClients: import("@aalis/schema-i18n").TextRef;
17
+ current: import("@aalis/schema-i18n").TextRef;
18
+ switching: import("@aalis/schema-i18n").TextRef;
19
+ switched: import("@aalis/schema-i18n").TextRef;
20
+ ownerHint: import("@aalis/schema-i18n").TextRef;
21
+ failed: import("@aalis/schema-i18n").TextRef;
22
+ error: import("@aalis/schema-i18n").TextRef;
23
+ };
24
+ };
25
+ /** 渲染前端切换恢复页的完整 HTML 文档:text 是渲染过的文字,数据由页面自身 fetch */
26
+ export declare function renderClientSwitchPage(text: Localized<typeof CLIENT_SWITCH_TEXTS>): string;
5
27
  //# sourceMappingURL=client-switch-page.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client-switch-page.d.ts","sourceRoot":"","sources":["../src/client-switch-page.ts"],"names":[],"mappings":"AAYA,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,ysFAyDhC,CAAC;AAEF,kDAAkD;AAClD,wBAAgB,sBAAsB,IAAI,MAAM,CAkC/C"}
1
+ {"version":3,"file":"client-switch-page.d.ts","sourceRoot":"","sources":["../src/client-switch-page.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAIpD,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,sjFA8DhC,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;CAmB/B,CAAC;AAEF,sDAAsD;AACtD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,CAAC,OAAO,mBAAmB,CAAC,GAAG,MAAM,CAmC1F"}
@@ -8,26 +8,33 @@
8
8
  // · 列表:GET /api/services (取 webui-client 服务的 providers + preferred)
9
9
  // · 切换:POST /api/services/webui-client/prefer (owner 闸,body {contextId})
10
10
  // 全局 auth 中间件已要求登录方可到达本路由(未认证 GET 直接回登录页),故本页无需自加 gate;
11
- // 切换动作仍受既有 owner 闸约束。抽成纯函数仅为便于单测——route 只 res.type('html').send(它)。
11
+ // 切换动作仍受既有 owner 闸约束。抽成纯函数仅为便于单测——route 按全局层的语言渲染文字后交给它。
12
+ // 文字按全局层的语言:页面上的在服务端写进 HTML,脚本要的放进 texts 块,带参数的留着 {名} 占位,由脚本填(见 html.ts)。
13
+ import { escapeHtml, textsBlock } from './html.js';
14
+ import { t } from './texts.js';
12
15
  /** 前端切换恢复页的脚本:文档级 CSP 只许同源脚本,由 `/__clients.js` 给出 */
13
16
  export const CLIENT_SWITCH_SCRIPT = `(function () {
14
17
  var SVC = 'webui-client';
15
18
  var PREFER = '/api/services/' + SVC + '/prefer';
19
+ var T = JSON.parse(document.getElementById('texts').textContent);
16
20
  var sel = document.getElementById('client');
17
21
  var btn = document.getElementById('go');
18
22
  var msg = document.getElementById('msg');
23
+ function fill(text, values) {
24
+ return text.replace(/\\{(\\w+)\\}/g, function (m, k) { return k in values ? String(values[k]) : m; });
25
+ }
19
26
  function setMsg(t, err) { msg.textContent = t; msg.className = err ? 'err' : 'ok'; }
20
27
  function load() {
21
28
  fetch('/api/services', { headers: { Accept: 'application/json' } })
22
29
  .then(function (r) {
23
- if (!r.ok) throw new Error('读取服务列表失败(HTTP ' + r.status + ')');
30
+ if (!r.ok) throw new Error(fill(T.listFailed, { status: r.status }));
24
31
  return r.json();
25
32
  })
26
33
  .then(function (data) {
27
34
  var svc = data && data.services && data.services[SVC];
28
35
  var providers = (svc && svc.providers) || [];
29
36
  if (!providers.length) {
30
- setMsg('未发现任何前端(webui-client provider)。请先安装一个 aalis.client 包。', true);
37
+ setMsg(T.noClients, true);
31
38
  btn.disabled = true;
32
39
  sel.innerHTML = '';
33
40
  return;
@@ -36,8 +43,9 @@ export const CLIENT_SWITCH_SCRIPT = `(function () {
36
43
  sel.innerHTML = '';
37
44
  providers.forEach(function (p) {
38
45
  var o = document.createElement('option');
46
+ var name = p.displayName || p.label || p.contextId;
39
47
  o.value = p.contextId;
40
- o.textContent = (p.displayName || p.label || p.contextId) + (p.contextId === active ? '(当前)' : '');
48
+ o.textContent = p.contextId === active ? fill(T.current, { name: name }) : name;
41
49
  if (p.contextId === active) o.selected = true;
42
50
  sel.appendChild(o);
43
51
  });
@@ -48,34 +56,55 @@ export const CLIENT_SWITCH_SCRIPT = `(function () {
48
56
  var contextId = sel.value;
49
57
  if (!contextId) return;
50
58
  btn.disabled = true;
51
- setMsg('切换中…', false);
59
+ setMsg(T.switching, false);
52
60
  fetch(PREFER, {
53
61
  method: 'POST',
54
62
  headers: { 'Content-Type': 'application/json' },
55
63
  body: JSON.stringify({ contextId: contextId })
56
64
  })
57
65
  .then(function (r) {
58
- if (r.ok) { setMsg('已切换,正在跳转…', false); location.href = '/'; return; }
66
+ if (r.ok) { setMsg(T.switched, false); location.href = '/'; return; }
59
67
  return r.json().catch(function () { return {}; }).then(function (j) {
60
68
  var detail = (j && j.error) || ('HTTP ' + r.status);
61
- var hint = (r.status === 401 || r.status === 403) ? '(需要 owner 权限:请用一键登录链接打开 WebUI 后再试)' : '';
62
- setMsg('切换失败:' + detail + hint, true);
69
+ var hint = (r.status === 401 || r.status === 403) ? T.ownerHint : '';
70
+ setMsg(fill(T.failed, { detail: detail, hint: hint }), true);
63
71
  btn.disabled = false;
64
72
  });
65
73
  })
66
- .catch(function (e) { setMsg('切换请求出错:' + String((e && e.message) || e), true); btn.disabled = false; });
74
+ .catch(function (e) { setMsg(fill(T.error, { error: String((e && e.message) || e) }), true); btn.disabled = false; });
67
75
  });
68
76
  load();
69
77
  })();
70
78
  `;
71
- /** 渲染前端切换恢复页的完整 HTML 文档(无运行时入参,数据由页面自身 fetch)。 */
72
- export function renderClientSwitchPage() {
79
+ /** 恢复页的文字;带参数的以 {名} 占位交给脚本填。pageLanguage 是渲染时实际用的语言,写进 <html lang> */
80
+ export const CLIENT_SWITCH_TEXTS = {
81
+ lang: t('pageLanguage'),
82
+ title: t('switchTitle'),
83
+ heading: t('switchHeading'),
84
+ intro: t('switchIntro'),
85
+ label: t('switchLabel'),
86
+ loading: t('switchLoading'),
87
+ button: t('switchButton'),
88
+ back: t('switchBack'),
89
+ script: {
90
+ listFailed: t('switchListFailed', { status: '{status}' }),
91
+ noClients: t('switchNoClients'),
92
+ current: t('switchCurrent', { name: '{name}' }),
93
+ switching: t('switching'),
94
+ switched: t('switched'),
95
+ ownerHint: t('switchOwnerHint'),
96
+ failed: t('switchFailed', { detail: '{detail}', hint: '{hint}' }),
97
+ error: t('switchError', { error: '{error}' }),
98
+ },
99
+ };
100
+ /** 渲染前端切换恢复页的完整 HTML 文档:text 是渲染过的文字,数据由页面自身 fetch */
101
+ export function renderClientSwitchPage(text) {
73
102
  return `<!doctype html>
74
- <html lang="zh-CN">
103
+ <html lang="${escapeHtml(text.lang)}">
75
104
  <head>
76
105
  <meta charset="utf-8" />
77
106
  <meta name="viewport" content="width=device-width, initial-scale=1" />
78
- <title>切换前端 · Aalis</title>
107
+ <title>${escapeHtml(text.title)}</title>
79
108
  <style>
80
109
  :root { color-scheme: light dark; }
81
110
  body { font: 15px/1.6 system-ui, -apple-system, sans-serif; max-width: 32rem; margin: 8vh auto; padding: 0 1.2rem; }
@@ -93,13 +122,14 @@ export function renderClientSwitchPage() {
93
122
  </style>
94
123
  </head>
95
124
  <body>
96
- <h1>切换前端</h1>
97
- <p class="hint">这是 Aalis 的前端恢复入口,由 webui-server 直接提供、独立于当前前端——即使当前前端没有切换界面,你也能在这里切回去。</p>
98
- <label for="client">可用前端(webui-client)</label>
99
- <select id="client"><option>加载中…</option></select>
100
- <button id="go" type="button">切换并刷新</button>
125
+ <h1>${escapeHtml(text.heading)}</h1>
126
+ <p class="hint">${escapeHtml(text.intro)}</p>
127
+ <label for="client">${escapeHtml(text.label)}</label>
128
+ <select id="client"><option>${escapeHtml(text.loading)}</option></select>
129
+ <button id="go" type="button">${escapeHtml(text.button)}</button>
101
130
  <div id="msg"></div>
102
- <p class="hint">切回原来的前端:在上面选中它,再点「切换并刷新」。</p>
131
+ <p class="hint">${escapeHtml(text.back)}</p>
132
+ ${textsBlock(text.script)}
103
133
  <script src="/__clients.js"></script>
104
134
  </body>
105
135
  </html>`;
@@ -1 +1 @@
1
- {"version":3,"file":"client-switch-page.js","sourceRoot":"","sources":["../src/client-switch-page.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,gDAAgD;AAChD,wDAAwD;AACxD,8DAA8D;AAC9D,EAAE;AACF,yEAAyE;AACzE,6FAA6F;AAC7F,8EAA8E;AAC9E,wDAAwD;AACxD,oEAAoE;AAEpE,qDAAqD;AACrD,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyDnC,CAAC;AAEF,kDAAkD;AAClD,MAAM,UAAU,sBAAsB;IACpC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAgCD,CAAC;AACT,CAAC"}
1
+ {"version":3,"file":"client-switch-page.js","sourceRoot":"","sources":["../src/client-switch-page.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,gDAAgD;AAChD,wDAAwD;AACxD,8DAA8D;AAC9D,EAAE;AACF,yEAAyE;AACzE,6FAA6F;AAC7F,8EAA8E;AAC9E,wDAAwD;AACxD,yDAAyD;AACzD,0EAA0E;AAG1E,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC;AAE/B,qDAAqD;AACrD,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8DnC,CAAC;AAEF,sEAAsE;AACtE,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,CAAC,CAAC,cAAc,CAAC;IACvB,KAAK,EAAE,CAAC,CAAC,aAAa,CAAC;IACvB,OAAO,EAAE,CAAC,CAAC,eAAe,CAAC;IAC3B,KAAK,EAAE,CAAC,CAAC,aAAa,CAAC;IACvB,KAAK,EAAE,CAAC,CAAC,aAAa,CAAC;IACvB,OAAO,EAAE,CAAC,CAAC,eAAe,CAAC;IAC3B,MAAM,EAAE,CAAC,CAAC,cAAc,CAAC;IACzB,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC;IACrB,MAAM,EAAE;QACN,UAAU,EAAE,CAAC,CAAC,kBAAkB,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QACzD,SAAS,EAAE,CAAC,CAAC,iBAAiB,CAAC;QAC/B,OAAO,EAAE,CAAC,CAAC,eAAe,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAC/C,SAAS,EAAE,CAAC,CAAC,WAAW,CAAC;QACzB,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC;QACvB,SAAS,EAAE,CAAC,CAAC,iBAAiB,CAAC;QAC/B,MAAM,EAAE,CAAC,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QACjE,KAAK,EAAE,CAAC,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;KAC9C;CACF,CAAC;AAEF,sDAAsD;AACtD,MAAM,UAAU,sBAAsB,CAAC,IAA2C;IAChF,OAAO;cACK,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;;;;SAI1B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;QAkBvB,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;oBACZ,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;wBAClB,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;gCACd,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;kCACtB,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;;oBAErC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;EACvC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;;;QAGjB,CAAC;AACT,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,gDAAgD;AAChD,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE;IAAE,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,KAAK,YAAY,GAAG,SAAS,CAAC;AAKtF,UAAU,WAAW;IACnB,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9B;AACD,UAAU,YAAY;IACpB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAA;KAAE,CAAC;CACxD;AACD,KAAK,cAAc,GAAG,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;AAEtF;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,UAAU,SACvC,cAAc,CAO1B;AAED,kDAAkD;AAClD,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC"}
1
+ {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGzD,gDAAgD;AAChD,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE;IAAE,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,KAAK,YAAY,GAAG,SAAS,CAAC;AAKtF,UAAU,WAAW;IACnB,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9B;AACD,UAAU,YAAY;IACpB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAA;KAAE,CAAC;CACxD;AACD,KAAK,cAAc,GAAG,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;AAEtF;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,UAAU,SACvC,cAAc,CAO1B;AAED,kDAAkD;AAClD,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC"}
package/dist/gate.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { t } from './texts.js';
1
2
  /**
2
3
  * REST 路由 owner 闸工厂(单 owner 终态)。
3
4
  *
@@ -12,7 +13,7 @@
12
13
  export function createRouteGate(identify) {
13
14
  return () => (req, res, next) => {
14
15
  if (!identify(req)) {
15
- res.status(403).json({ error: '需要 owner 权限' });
16
+ res.status(403).json({ error: t('ownerRequired') });
16
17
  return;
17
18
  }
18
19
  next();