@undefineds.co/xpod 0.2.29 → 0.2.31
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/config/cli.json +1 -1
- package/config/local.json +8 -8
- package/config/resolver.json +2 -2
- package/config/xpod.json +8 -8
- package/dist/api/container/index.js +1 -1
- package/dist/api/container/index.js.map +1 -1
- package/dist/cli/commands/start.js +8 -8
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/components/context.jsonld +8 -8
- package/dist/identity/oidc/AutoDetectIdentityProviderHandler.d.ts +4 -4
- package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js +7 -7
- package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js.map +1 -1
- package/dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld +6 -6
- package/dist/identity/oidc/AutoDetectOidcHandler.d.ts +4 -4
- package/dist/identity/oidc/AutoDetectOidcHandler.js +6 -6
- package/dist/identity/oidc/AutoDetectOidcHandler.js.map +1 -1
- package/dist/identity/oidc/AutoDetectOidcHandler.jsonld +6 -6
- package/dist/runtime/bootstrap.js +1 -1
- package/dist/runtime/bootstrap.js.map +1 -1
- package/package.json +1 -1
- package/static/app/assets/index.css +1 -1
- package/static/app/assets/main.js +27 -27
package/config/cli.json
CHANGED
package/config/local.json
CHANGED
|
@@ -21,16 +21,16 @@
|
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
|
-
"comment": "定义
|
|
25
|
-
"@id": "urn:solid-server:default:variable:
|
|
24
|
+
"comment": "定义 oidcIssuer 变量(外部 IdP 基础 URL),设置后启用 SP 模式",
|
|
25
|
+
"@id": "urn:solid-server:default:variable:oidcIssuer",
|
|
26
26
|
"@type": "Variable"
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
|
-
"comment": "Auto-detect OIDC Handler - 有
|
|
29
|
+
"comment": "Auto-detect OIDC Handler - 有 oidcIssuer 时启用 SP 模式,代理 JWKS",
|
|
30
30
|
"@id": "urn:undefineds:xpod:AutoDetectOidcHandler",
|
|
31
31
|
"@type": "AutoDetectOidcHandler",
|
|
32
|
-
"AutoDetectOidcHandler:
|
|
33
|
-
"@id": "urn:solid-server:default:variable:
|
|
32
|
+
"AutoDetectOidcHandler:_options_oidcIssuer": {
|
|
33
|
+
"@id": "urn:solid-server:default:variable:oidcIssuer"
|
|
34
34
|
},
|
|
35
35
|
"AutoDetectOidcHandler:_options_cacheMs": 300000
|
|
36
36
|
},
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
|
-
"comment": "Auto-detect Identity Provider Handler - 有
|
|
55
|
+
"comment": "Auto-detect Identity Provider Handler - 有 oidcIssuer 时禁用本地账户管理",
|
|
56
56
|
"@id": "urn:undefineds:xpod:AutoDetectIdentityProviderHandler",
|
|
57
57
|
"@type": "AutoDetectIdentityProviderHandler",
|
|
58
|
-
"AutoDetectIdentityProviderHandler:
|
|
59
|
-
"@id": "urn:solid-server:default:variable:
|
|
58
|
+
"AutoDetectIdentityProviderHandler:_options_oidcIssuer": {
|
|
59
|
+
"@id": "urn:solid-server:default:variable:oidcIssuer"
|
|
60
60
|
},
|
|
61
61
|
"AutoDetectIdentityProviderHandler:_options_source": {
|
|
62
62
|
"@id": "urn:undefineds:xpod:SourceIdentityProviderHandler"
|
package/config/resolver.json
CHANGED
|
@@ -288,10 +288,10 @@
|
|
|
288
288
|
}
|
|
289
289
|
},
|
|
290
290
|
{
|
|
291
|
-
"CombinedShorthandResolver:_resolvers_key": "urn:solid-server:default:variable:
|
|
291
|
+
"CombinedShorthandResolver:_resolvers_key": "urn:solid-server:default:variable:oidcIssuer",
|
|
292
292
|
"CombinedShorthandResolver:_resolvers_value": {
|
|
293
293
|
"@type": "KeyExtractor",
|
|
294
|
-
"key": "
|
|
294
|
+
"key": "oidcIssuer",
|
|
295
295
|
"defaultValue": ""
|
|
296
296
|
}
|
|
297
297
|
},
|
package/config/xpod.json
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"@type": "Void"
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
|
-
"comment": "定义
|
|
20
|
-
"@id": "urn:solid-server:default:variable:
|
|
19
|
+
"comment": "定义 oidcIssuer 变量(外部 IdP 基础 URL)- SP 模式必填",
|
|
20
|
+
"@id": "urn:solid-server:default:variable:oidcIssuer",
|
|
21
21
|
"@type": "Variable"
|
|
22
22
|
},
|
|
23
23
|
{
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
},
|
|
30
30
|
"additionalBaseUrls": [
|
|
31
31
|
{
|
|
32
|
-
"@id": "urn:solid-server:default:variable:
|
|
32
|
+
"@id": "urn:solid-server:default:variable:oidcIssuer"
|
|
33
33
|
}
|
|
34
34
|
]
|
|
35
35
|
},
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
|
-
"comment": "Auto-detect OIDC Handler - 有
|
|
55
|
+
"comment": "Auto-detect OIDC Handler - 有 oidcIssuer 时启用 SP 模式",
|
|
56
56
|
"@id": "urn:undefineds:xpod:AutoDetectOidcHandler",
|
|
57
57
|
"@type": "AutoDetectOidcHandler",
|
|
58
|
-
"
|
|
59
|
-
"@id": "urn:solid-server:default:variable:
|
|
58
|
+
"options_oidcIssuer": {
|
|
59
|
+
"@id": "urn:solid-server:default:variable:oidcIssuer"
|
|
60
60
|
},
|
|
61
61
|
"options_cacheMs": 300000
|
|
62
62
|
},
|
|
@@ -74,8 +74,8 @@
|
|
|
74
74
|
"comment": "Auto-detect Identity Provider Handler",
|
|
75
75
|
"@id": "urn:undefineds:xpod:AutoDetectIdentityProviderHandler",
|
|
76
76
|
"@type": "AutoDetectIdentityProviderHandler",
|
|
77
|
-
"
|
|
78
|
-
"@id": "urn:solid-server:default:variable:
|
|
77
|
+
"options_oidcIssuer": {
|
|
78
|
+
"@id": "urn:solid-server:default:variable:oidcIssuer"
|
|
79
79
|
}
|
|
80
80
|
},
|
|
81
81
|
{
|
|
@@ -109,7 +109,7 @@ function loadConfigFromEnv() {
|
|
|
109
109
|
nodeToken: process.env.XPOD_NODE_TOKEN,
|
|
110
110
|
// OIDC Issuer (Local 托管式使用 Cloud IdP)
|
|
111
111
|
// 如果配置了 XPOD_NODE_TOKEN,默认使用 Cloud IdP
|
|
112
|
-
oidcIssuer: process.env.
|
|
112
|
+
oidcIssuer: process.env.CSS_OIDC_ISSUER ?? (process.env.XPOD_NODE_TOKEN
|
|
113
113
|
? OFFICIAL_CLOUD_IDENTITY_ORIGIN
|
|
114
114
|
: undefined),
|
|
115
115
|
// 隧道配置
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/api/container/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;;;;;;;;;AAoCH,gDAyBC;AAKD,8CAgDC;AAhHD,mCAAuF;AACvF,6CAAqD;AACrD,4CAA8B;AAC9B,4CAA8B;AAC9B,gDAAkC;AAElC,qCAAkD;AAClD,mCAAgD;AAChD,mCAAgD;AAChD,qDAAyD;AAIzD,MAAM,8BAA8B,GAAG,0BAA0B,CAAC;AAElE,SAAS,mBAAmB,CAAC,GAAW;IACtC,OAAO,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC;AAC7C,CAAC;AAED,SAAS,uBAAuB;IAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC;QACnC,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IACxC,CAAC;IAED,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC7B,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,aAAa,CAAC;IACvE,CAAC;IAED,OAAO,mCAAmC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,MAA0B;IAC3D,MAAM,SAAS,GAAG,IAAA,wBAAe,EAAqB;QACpD,aAAa,EAAE,sBAAa,CAAC,KAAK;QAClC,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;IAEH,OAAO;IACP,SAAS,CAAC,QAAQ,CAAC;QACjB,MAAM,EAAE,IAAA,gBAAO,EAAC,MAAM,CAAC;KACxB,CAAC,CAAC;IAEH,SAAS;IACT,IAAA,+BAAsB,EAAC,SAAS,CAAC,CAAC;IAElC,oBAAoB;IACpB,IAAI,MAAM,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;QAC/B,IAAA,6BAAqB,EAAC,SAAS,CAAC,CAAC;IACnC,CAAC;SAAM,CAAC;QACN,IAAA,6BAAqB,EAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAED,gDAAgD;IAChD,IAAA,sCAAqB,EAAC,SAAS,CAAC,CAAC;IAEjC,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB;IAC/B,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,OAAO,CAAsB,CAAC;IAE3E,qEAAqE;IACrE,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ;QAClC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;QACpC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC;IAEhB,OAAO;QACL,OAAO;QACP,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,SAAS;QACvC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe;QACvC,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE;QAC9E,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;QAC7E,gBAAgB,EAAE,uBAAuB,EAAE;QAE3C,mBAAmB;QACnB,SAAS,EAAE;YACT,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB;YACtD,mBAAmB,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;YACtD,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB;YACpD,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;YACrD,mBAAmB,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB;SACxD;QAED,qBAAqB;QACrB,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB;QACrD,MAAM,EAAE,sBAAsB,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QACxD,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe;QAEtC,sCAAsC;QACtC,uCAAuC;QACvC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/api/container/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * API Container 入口\n *\n * 使用 Awilix 进行依赖注入,根据 edition 注册不同服务\n */\n\nimport { createContainer, asValue, InjectionMode, type AwilixContainer } from 'awilix';\nimport { randomUUID, createHash } from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { ApiContainerCradle, ApiContainerConfig } from './types';\nimport { registerCommonServices } from './common';\nimport { registerCloudServices } from './cloud';\nimport { registerLocalServices } from './local';\nimport { registerBusinessToken } from './business-token';\n\nexport type { ApiContainerCradle, ApiContainerConfig } from './types';\n\nconst OFFICIAL_CLOUD_IDENTITY_ORIGIN = 'https://id.undefineds.co';\n\nfunction ensureTrailingSlash(url: string): string {\n return url.endsWith('/') ? url : `${url}/`;\n}\n\nfunction resolveCssTokenEndpoint(): string {\n if (process.env.CSS_TOKEN_ENDPOINT) {\n return process.env.CSS_TOKEN_ENDPOINT;\n }\n\n if (process.env.CSS_BASE_URL) {\n return `${ensureTrailingSlash(process.env.CSS_BASE_URL)}.oidc/token`;\n }\n\n return 'http://localhost:3000/.oidc/token';\n}\n\n/**\n * 创建 API 容器\n */\nexport function createApiContainer(config: ApiContainerConfig): AwilixContainer<ApiContainerCradle> {\n const container = createContainer<ApiContainerCradle>({\n injectionMode: InjectionMode.PROXY,\n strict: true,\n });\n\n // 注册配置\n container.register({\n config: asValue(config),\n });\n\n // 注册共享服务\n registerCommonServices(container);\n\n // 根据 edition 注册专属服务\n if (config.edition === 'cloud') {\n registerCloudServices(container);\n } else {\n registerLocalServices(container);\n }\n\n // 注册 Business Token (如果配置了 XPOD_BUSINESS_TOKEN)\n registerBusinessToken(container);\n\n return container;\n}\n\n/**\n * 从环境变量读取配置\n */\nexport function loadConfigFromEnv(): ApiContainerConfig {\n const edition = (process.env.XPOD_EDITION ?? 'local') as 'cloud' | 'local';\n\n // Port auto-increment: API_PORT = CSS_PORT + 1 if not explicitly set\n const cssPort = parseInt(process.env.CSS_PORT ?? '3000', 10);\n const apiPort = process.env.API_PORT\n ? parseInt(process.env.API_PORT, 10)\n : cssPort + 1;\n\n return {\n edition,\n port: apiPort,\n host: process.env.API_HOST ?? '0.0.0.0',\n socketPath: process.env.API_SOCKET_PATH,\n databaseUrl: process.env.CSS_IDENTITY_DB_URL ?? process.env.DATABASE_URL ?? '',\n corsOrigins: process.env.CORS_ORIGINS?.split(',').map(s => s.trim()) ?? ['*'],\n cssTokenEndpoint: resolveCssTokenEndpoint(),\n\n // 子域名配置 (cloud 模式)\n subdomain: {\n baseStorageDomain: process.env.CSS_BASE_STORAGE_DOMAIN,\n cloudflareAccountId: process.env.CLOUDFLARE_ACCOUNT_ID,\n cloudflareApiToken: process.env.CLOUDFLARE_API_TOKEN,\n tencentDnsSecretId: process.env.TENCENT_DNS_SECRET_ID,\n tencentDnsSecretKey: process.env.TENCENT_DNS_SECRET_KEY,\n },\n\n // Local 托管式:连接 Cloud\n cloudApiEndpoint: process.env.XPOD_CLOUD_API_ENDPOINT,\n nodeId: loadOrGenerateDeviceId(process.env.XPOD_NODE_ID),\n nodeToken: process.env.XPOD_NODE_TOKEN,\n\n // OIDC Issuer (Local 托管式使用 Cloud IdP)\n // 如果配置了 XPOD_NODE_TOKEN,默认使用 Cloud IdP\n oidcIssuer: process.env.CSS_OIDC_ISSUER ?? (\n process.env.XPOD_NODE_TOKEN\n ? OFFICIAL_CLOUD_IDENTITY_ORIGIN\n : undefined\n ),\n\n // 隧道配置\n cloudflareTunnelToken: process.env.CLOUDFLARE_TUNNEL_TOKEN,\n // Prefer SAKURA_TUNNEL_TOKEN; keep SAKURA_TOKEN for backward compatibility.\n sakuraTunnelToken: process.env.SAKURA_TUNNEL_TOKEN ?? process.env.SAKURA_TOKEN,\n\n // Edge 节点管理 (cloud 模式)\n edgeNodesEnabled: process.env.XPOD_EDGE_NODES_ENABLED === 'true',\n };\n}\n\n/**\n * 获取设备首个非内部网卡的 MAC 地址。\n * 返回小写冒号分隔格式,如 \"aa:bb:cc:dd:ee:ff\"。\n * 容器/虚拟机中可能拿不到稳定 MAC,此时返回 undefined。\n */\nfunction getFirstMacAddress(): string | undefined {\n const interfaces = os.networkInterfaces();\n for (const name of Object.keys(interfaces)) {\n for (const iface of interfaces[name] ?? []) {\n if (!iface.internal && iface.mac && iface.mac !== '00:00:00:00:00:00') {\n return iface.mac.toLowerCase();\n }\n }\n }\n return undefined;\n}\n\n/**\n * 读取或生成设备 ID(持久化到 data/.device-id)。\n *\n * 优先级:\n * 1. 环境变量 XPOD_NODE_ID\n * 2. 已持久化的 data/.device-id\n * 3. 基于 MAC 地址的 SHA-256 哈希(截取前 32 位 hex)\n * 4. 随机 UUID(容器/虚拟机无稳定 MAC 时兜底)\n *\n * 生成后写入 data/.device-id,后续启动直接读取,保证同一设备 ID 稳定。\n */\nfunction loadOrGenerateDeviceId(envNodeId?: string): string | undefined {\n if (envNodeId) {\n return envNodeId;\n }\n\n const rootDir = process.env.CSS_ROOT_FILE_PATH || './data';\n const deviceIdPath = path.join(rootDir, '.device-id');\n\n // 尝试从文件读取\n try {\n if (fs.existsSync(deviceIdPath)) {\n const content = fs.readFileSync(deviceIdPath, 'utf-8').trim();\n if (content) {\n return content;\n }\n }\n } catch {\n // 读取失败,继续生成\n }\n\n // 优先用 MAC 哈希,拿不到则 UUID 兜底\n const mac = getFirstMacAddress();\n const deviceId = mac\n ? createHash('sha256').update(mac).digest('hex').slice(0, 32)\n : randomUUID();\n\n try {\n if (!fs.existsSync(rootDir)) {\n fs.mkdirSync(rootDir, { recursive: true });\n }\n fs.writeFileSync(deviceIdPath, deviceId, 'utf-8');\n } catch {\n // 写入失败不阻塞启动\n }\n\n return deviceId;\n}\n"]}
|
|
@@ -87,20 +87,20 @@ exports.startCommand = {
|
|
|
87
87
|
const apiPort = await (0, runtime_1.getFreePort)(cssPort + 1, argv.host);
|
|
88
88
|
const baseUrl = process.env.CSS_BASE_URL || `http://${argv.host}:${mainPort}/`;
|
|
89
89
|
// SP 模式:全部通过环境变量配置(.env.local 或 --env 参数)
|
|
90
|
-
// XPOD_SERVICE_TOKEN, XPOD_NODE_ID, XPOD_NODE_TOKEN, XPOD_CLOUD_API_ENDPOINT,
|
|
91
|
-
const
|
|
90
|
+
// XPOD_SERVICE_TOKEN, XPOD_NODE_ID, XPOD_NODE_TOKEN, XPOD_CLOUD_API_ENDPOINT, CSS_OIDC_ISSUER
|
|
91
|
+
const oidcIssuer = process.env.CSS_OIDC_ISSUER;
|
|
92
92
|
console.log('Starting xpod...');
|
|
93
93
|
console.log(` Gateway: ${baseUrl} (${argv.host}:${mainPort})`);
|
|
94
94
|
console.log(` CSS (internal): http://localhost:${cssPort}`);
|
|
95
95
|
console.log(` API (internal): http://localhost:${apiPort}`);
|
|
96
|
-
if (
|
|
97
|
-
console.log(` SP mode: Cloud IdP = ${
|
|
96
|
+
if (oidcIssuer) {
|
|
97
|
+
console.log(` SP mode: Cloud IdP = ${oidcIssuer}`);
|
|
98
98
|
}
|
|
99
99
|
const supervisor = new supervisor_1.Supervisor();
|
|
100
100
|
const cssBinary = require.resolve('@solid/community-server/bin/server.js');
|
|
101
101
|
const cssArgs = [cssBinary, '-c', configPath, '-m', runtime_1.PACKAGE_ROOT, '-p', cssPort.toString(), '-b', baseUrl];
|
|
102
|
-
if (
|
|
103
|
-
cssArgs.push('--
|
|
102
|
+
if (oidcIssuer) {
|
|
103
|
+
cssArgs.push('--oidcIssuer', oidcIssuer);
|
|
104
104
|
}
|
|
105
105
|
supervisor.register({
|
|
106
106
|
name: 'css',
|
|
@@ -130,8 +130,8 @@ exports.startCommand = {
|
|
|
130
130
|
XPOD_MAIN_PORT: mainPort.toString(),
|
|
131
131
|
CSS_INTERNAL_URL: `http://localhost:${cssPort}`,
|
|
132
132
|
CSS_BASE_URL: baseUrl,
|
|
133
|
-
CSS_TOKEN_ENDPOINT:
|
|
134
|
-
? `${
|
|
133
|
+
CSS_TOKEN_ENDPOINT: oidcIssuer
|
|
134
|
+
? `${oidcIssuer.replace(/\/$/, '')}/.oidc/token`
|
|
135
135
|
: `${baseUrl}.oidc/token`,
|
|
136
136
|
},
|
|
137
137
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CommandModule } from 'yargs';\nimport path from 'path';\nimport fs from 'fs';\nimport { Supervisor } from '../../supervisor';\nimport { GatewayProxy, getFreePort, PACKAGE_ROOT } from '../../runtime';\n\ninterface StartArgs {\n mode?: string;\n config?: string;\n env?: string;\n port: number;\n host: string;\n}\n\nconst childJsRuntime = typeof (globalThis as { Bun?: unknown }).Bun !== 'undefined'\n ? (process.env.XPOD_NODE_BINARY ?? 'node')\n : process.execPath;\n\nfunction loadEnvFile(envPath: string): void {\n if (!fs.existsSync(envPath)) {\n console.warn(`Env file not found: ${envPath}`);\n return;\n }\n const content = fs.readFileSync(envPath, 'utf-8');\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex === -1) continue;\n const key = trimmed.slice(0, eqIndex).trim();\n let value = trimmed.slice(eqIndex + 1).trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n if (!process.env[key]) {\n process.env[key] = value;\n }\n }\n}\n\nexport const startCommand: CommandModule<object, StartArgs> = {\n command: 'start',\n describe: 'Start xpod services',\n builder: (yargs) =>\n yargs\n .option('mode', {\n alias: 'm',\n type: 'string',\n choices: ['local', 'cloud'],\n description: 'Run mode',\n })\n .option('config', {\n alias: 'c',\n type: 'string',\n description: 'Path to config file (overrides --mode)',\n })\n .option('env', {\n alias: 'e',\n type: 'string',\n description: 'Path to .env file',\n })\n .option('port', {\n alias: 'p',\n type: 'number',\n description: 'Gateway port',\n default: 3000,\n })\n .option('host', {\n type: 'string',\n description: 'Gateway host',\n default: 'localhost',\n }),\n handler: async (argv) => {\n if (argv.env) {\n loadEnvFile(argv.env);\n }\n\n const mainPort =\n argv.port !== 3000\n ? argv.port\n : parseInt(process.env.XPOD_PORT ?? process.env.PORT ?? '3000', 10);\n\n let configPath: string;\n if (argv.config) {\n configPath = argv.config;\n } else if (argv.mode) {\n configPath = path.join(PACKAGE_ROOT, `config/${argv.mode}.json`);\n } else {\n configPath = path.join(PACKAGE_ROOT, 'config/local.json');\n }\n\n const cssPort = await getFreePort(mainPort + 1, argv.host);\n const apiPort = await getFreePort(cssPort + 1, argv.host);\n\n const baseUrl = process.env.CSS_BASE_URL || `http://${argv.host}:${mainPort}/`;\n\n // SP 模式:全部通过环境变量配置(.env.local 或 --env 参数)\n // XPOD_SERVICE_TOKEN, XPOD_NODE_ID, XPOD_NODE_TOKEN, XPOD_CLOUD_API_ENDPOINT, CSS_IDP_URL\n const idpUrl = process.env.CSS_IDP_URL || process.env.XPOD_CLOUD_API_ENDPOINT;\n\n console.log('Starting xpod...');\n console.log(` Gateway: ${baseUrl} (${argv.host}:${mainPort})`);\n console.log(` CSS (internal): http://localhost:${cssPort}`);\n console.log(` API (internal): http://localhost:${apiPort}`);\n if (idpUrl) {\n console.log(` SP mode: Cloud IdP = ${idpUrl}`);\n }\n\n const supervisor = new Supervisor();\n const cssBinary = require.resolve('@solid/community-server/bin/server.js');\n const cssArgs = [cssBinary, '-c', configPath, '-m', PACKAGE_ROOT, '-p', cssPort.toString(), '-b', baseUrl];\n if (idpUrl) {\n cssArgs.push('--idpUrl', idpUrl);\n }\n\n supervisor.register({\n name: 'css',\n command: childJsRuntime,\n args: cssArgs,\n env: {\n ...process.env as Record<string, string>,\n CSS_PORT: cssPort.toString(),\n CSS_BASE_URL: baseUrl,\n },\n });\n\n const isDevMode = __filename.endsWith('.ts');\n const apiArgs = isDevMode\n ? [\n '-r',\n require.resolve('ts-node/register/transpile-only'),\n path.resolve(__dirname, '..', '..', 'api', 'main.ts'),\n ]\n : [path.resolve(__dirname, '..', '..', 'api', 'main.js')];\n\n supervisor.register({\n name: 'api',\n command: childJsRuntime,\n args: apiArgs,\n env: {\n ...process.env as Record<string, string>,\n API_PORT: apiPort.toString(),\n XPOD_MAIN_PORT: mainPort.toString(),\n CSS_INTERNAL_URL: `http://localhost:${cssPort}`,\n CSS_BASE_URL: baseUrl,\n CSS_TOKEN_ENDPOINT: idpUrl\n ? `${idpUrl.replace(/\\/$/, '')}/.oidc/token`\n : `${baseUrl}.oidc/token`,\n },\n });\n\n const proxy = new GatewayProxy(mainPort, supervisor, '0.0.0.0', {\n exitOnStop: true,\n baseUrl,\n });\n proxy.setTargets({\n css: `http://localhost:${cssPort}`,\n api: `http://localhost:${apiPort}`,\n });\n\n await supervisor.startAll();\n await proxy.start();\n\n const shutdown = async (signal: string): Promise<void> => {\n console.log(`\\nReceived ${signal}, shutting down...`);\n await supervisor.stopAll();\n process.exit(0);\n };\n\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n },\n};\n"]}
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CommandModule } from 'yargs';\nimport path from 'path';\nimport fs from 'fs';\nimport { Supervisor } from '../../supervisor';\nimport { GatewayProxy, getFreePort, PACKAGE_ROOT } from '../../runtime';\n\ninterface StartArgs {\n mode?: string;\n config?: string;\n env?: string;\n port: number;\n host: string;\n}\n\nconst childJsRuntime = typeof (globalThis as { Bun?: unknown }).Bun !== 'undefined'\n ? (process.env.XPOD_NODE_BINARY ?? 'node')\n : process.execPath;\n\nfunction loadEnvFile(envPath: string): void {\n if (!fs.existsSync(envPath)) {\n console.warn(`Env file not found: ${envPath}`);\n return;\n }\n const content = fs.readFileSync(envPath, 'utf-8');\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex === -1) continue;\n const key = trimmed.slice(0, eqIndex).trim();\n let value = trimmed.slice(eqIndex + 1).trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n if (!process.env[key]) {\n process.env[key] = value;\n }\n }\n}\n\nexport const startCommand: CommandModule<object, StartArgs> = {\n command: 'start',\n describe: 'Start xpod services',\n builder: (yargs) =>\n yargs\n .option('mode', {\n alias: 'm',\n type: 'string',\n choices: ['local', 'cloud'],\n description: 'Run mode',\n })\n .option('config', {\n alias: 'c',\n type: 'string',\n description: 'Path to config file (overrides --mode)',\n })\n .option('env', {\n alias: 'e',\n type: 'string',\n description: 'Path to .env file',\n })\n .option('port', {\n alias: 'p',\n type: 'number',\n description: 'Gateway port',\n default: 3000,\n })\n .option('host', {\n type: 'string',\n description: 'Gateway host',\n default: 'localhost',\n }),\n handler: async (argv) => {\n if (argv.env) {\n loadEnvFile(argv.env);\n }\n\n const mainPort =\n argv.port !== 3000\n ? argv.port\n : parseInt(process.env.XPOD_PORT ?? process.env.PORT ?? '3000', 10);\n\n let configPath: string;\n if (argv.config) {\n configPath = argv.config;\n } else if (argv.mode) {\n configPath = path.join(PACKAGE_ROOT, `config/${argv.mode}.json`);\n } else {\n configPath = path.join(PACKAGE_ROOT, 'config/local.json');\n }\n\n const cssPort = await getFreePort(mainPort + 1, argv.host);\n const apiPort = await getFreePort(cssPort + 1, argv.host);\n\n const baseUrl = process.env.CSS_BASE_URL || `http://${argv.host}:${mainPort}/`;\n\n // SP 模式:全部通过环境变量配置(.env.local 或 --env 参数)\n // XPOD_SERVICE_TOKEN, XPOD_NODE_ID, XPOD_NODE_TOKEN, XPOD_CLOUD_API_ENDPOINT, CSS_OIDC_ISSUER\n const oidcIssuer = process.env.CSS_OIDC_ISSUER;\n\n console.log('Starting xpod...');\n console.log(` Gateway: ${baseUrl} (${argv.host}:${mainPort})`);\n console.log(` CSS (internal): http://localhost:${cssPort}`);\n console.log(` API (internal): http://localhost:${apiPort}`);\n if (oidcIssuer) {\n console.log(` SP mode: Cloud IdP = ${oidcIssuer}`);\n }\n\n const supervisor = new Supervisor();\n const cssBinary = require.resolve('@solid/community-server/bin/server.js');\n const cssArgs = [cssBinary, '-c', configPath, '-m', PACKAGE_ROOT, '-p', cssPort.toString(), '-b', baseUrl];\n if (oidcIssuer) {\n cssArgs.push('--oidcIssuer', oidcIssuer);\n }\n\n supervisor.register({\n name: 'css',\n command: childJsRuntime,\n args: cssArgs,\n env: {\n ...process.env as Record<string, string>,\n CSS_PORT: cssPort.toString(),\n CSS_BASE_URL: baseUrl,\n },\n });\n\n const isDevMode = __filename.endsWith('.ts');\n const apiArgs = isDevMode\n ? [\n '-r',\n require.resolve('ts-node/register/transpile-only'),\n path.resolve(__dirname, '..', '..', 'api', 'main.ts'),\n ]\n : [path.resolve(__dirname, '..', '..', 'api', 'main.js')];\n\n supervisor.register({\n name: 'api',\n command: childJsRuntime,\n args: apiArgs,\n env: {\n ...process.env as Record<string, string>,\n API_PORT: apiPort.toString(),\n XPOD_MAIN_PORT: mainPort.toString(),\n CSS_INTERNAL_URL: `http://localhost:${cssPort}`,\n CSS_BASE_URL: baseUrl,\n CSS_TOKEN_ENDPOINT: oidcIssuer\n ? `${oidcIssuer.replace(/\\/$/, '')}/.oidc/token`\n : `${baseUrl}.oidc/token`,\n },\n });\n\n const proxy = new GatewayProxy(mainPort, supervisor, '0.0.0.0', {\n exitOnStop: true,\n baseUrl,\n });\n proxy.setTargets({\n css: `http://localhost:${cssPort}`,\n api: `http://localhost:${apiPort}`,\n });\n\n await supervisor.startAll();\n await proxy.start();\n\n const shutdown = async (signal: string): Promise<void> => {\n console.log(`\\nReceived ${signal}, shutting down...`);\n await supervisor.stopAll();\n process.exit(0);\n };\n\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n },\n};\n"]}
|
|
@@ -1762,8 +1762,8 @@
|
|
|
1762
1762
|
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#AutoDetectOidcHandler",
|
|
1763
1763
|
"@prefix": true,
|
|
1764
1764
|
"@context": {
|
|
1765
|
-
"
|
|
1766
|
-
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#
|
|
1765
|
+
"options_oidcIssuer": {
|
|
1766
|
+
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#AutoDetectOidcHandler_options_oidcIssuer"
|
|
1767
1767
|
},
|
|
1768
1768
|
"options_message": {
|
|
1769
1769
|
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#AutoDetectOidcHandler_options_message"
|
|
@@ -1771,8 +1771,8 @@
|
|
|
1771
1771
|
"options_cacheMs": {
|
|
1772
1772
|
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#AutoDetectOidcHandler_options_cacheMs"
|
|
1773
1773
|
},
|
|
1774
|
-
"
|
|
1775
|
-
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#
|
|
1774
|
+
"oidcIssuer": {
|
|
1775
|
+
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#AutoDetectOidcHandler_options_oidcIssuer"
|
|
1776
1776
|
},
|
|
1777
1777
|
"message": {
|
|
1778
1778
|
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#AutoDetectOidcHandler_options_message"
|
|
@@ -1786,8 +1786,8 @@
|
|
|
1786
1786
|
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#AutoDetectIdentityProviderHandler",
|
|
1787
1787
|
"@prefix": true,
|
|
1788
1788
|
"@context": {
|
|
1789
|
-
"
|
|
1790
|
-
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#
|
|
1789
|
+
"options_oidcIssuer": {
|
|
1790
|
+
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#AutoDetectIdentityProviderHandler_options_oidcIssuer"
|
|
1791
1791
|
},
|
|
1792
1792
|
"options_message": {
|
|
1793
1793
|
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#AutoDetectIdentityProviderHandler_options_message"
|
|
@@ -1795,8 +1795,8 @@
|
|
|
1795
1795
|
"options_source": {
|
|
1796
1796
|
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#AutoDetectIdentityProviderHandler_options_source"
|
|
1797
1797
|
},
|
|
1798
|
-
"
|
|
1799
|
-
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#
|
|
1798
|
+
"oidcIssuer": {
|
|
1799
|
+
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#AutoDetectIdentityProviderHandler_options_oidcIssuer"
|
|
1800
1800
|
},
|
|
1801
1801
|
"message": {
|
|
1802
1802
|
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#AutoDetectIdentityProviderHandler_options_message"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { HttpHandler, type HttpHandlerInput } from '@solid/community-server';
|
|
2
2
|
export interface AutoDetectIdentityProviderHandlerOptions {
|
|
3
3
|
/** 外部 IdP 的基础 URL,如果提供则启用 SP 模式 */
|
|
4
|
-
|
|
4
|
+
oidcIssuer?: string;
|
|
5
5
|
/** 禁用时的消息 */
|
|
6
6
|
message?: string;
|
|
7
7
|
/** CSS 默认的 IdentityProviderHandler,标准模式下委托给它 */
|
|
@@ -11,12 +11,12 @@ export interface AutoDetectIdentityProviderHandlerOptions {
|
|
|
11
11
|
* Auto-detect Identity Provider Handler
|
|
12
12
|
*
|
|
13
13
|
* 自动检测运行模式:
|
|
14
|
-
* - 如果配置了
|
|
15
|
-
* - 如果没有配置
|
|
14
|
+
* - 如果配置了 oidcIssuer -> SP 模式:禁用本地账户管理
|
|
15
|
+
* - 如果没有配置 oidcIssuer -> 标准模式:委托给 CSS 默认 Handler
|
|
16
16
|
*/
|
|
17
17
|
export declare class AutoDetectIdentityProviderHandler extends HttpHandler {
|
|
18
18
|
private readonly logger;
|
|
19
|
-
private readonly
|
|
19
|
+
private readonly oidcIssuer?;
|
|
20
20
|
private readonly message;
|
|
21
21
|
private readonly source?;
|
|
22
22
|
constructor(options?: AutoDetectIdentityProviderHandlerOptions);
|
|
@@ -7,18 +7,18 @@ const community_server_1 = require("@solid/community-server");
|
|
|
7
7
|
* Auto-detect Identity Provider Handler
|
|
8
8
|
*
|
|
9
9
|
* 自动检测运行模式:
|
|
10
|
-
* - 如果配置了
|
|
11
|
-
* - 如果没有配置
|
|
10
|
+
* - 如果配置了 oidcIssuer -> SP 模式:禁用本地账户管理
|
|
11
|
+
* - 如果没有配置 oidcIssuer -> 标准模式:委托给 CSS 默认 Handler
|
|
12
12
|
*/
|
|
13
13
|
class AutoDetectIdentityProviderHandler extends community_server_1.HttpHandler {
|
|
14
14
|
constructor(options = {}) {
|
|
15
15
|
super();
|
|
16
16
|
this.logger = (0, global_logger_factory_1.getLoggerFor)(this);
|
|
17
|
-
this.
|
|
17
|
+
this.oidcIssuer = options.oidcIssuer;
|
|
18
18
|
this.message = options.message ?? 'Account management handled by external IdP';
|
|
19
19
|
this.source = options.source;
|
|
20
|
-
if (this.
|
|
21
|
-
this.logger.info(`SP mode enabled: ${this.message}, external IdP: ${this.
|
|
20
|
+
if (this.oidcIssuer) {
|
|
21
|
+
this.logger.info(`SP mode enabled: ${this.message}, external IdP: ${this.oidcIssuer}`);
|
|
22
22
|
}
|
|
23
23
|
else {
|
|
24
24
|
this.logger.info('Standard mode enabled, delegating to source IdentityProviderHandler');
|
|
@@ -36,7 +36,7 @@ class AutoDetectIdentityProviderHandler extends community_server_1.HttpHandler {
|
|
|
36
36
|
throw new community_server_1.NotImplementedHttpError('Not an IdP request');
|
|
37
37
|
}
|
|
38
38
|
// SP 模式:接受 IdP 路径请求,在 handle 中返回 404
|
|
39
|
-
if (this.
|
|
39
|
+
if (this.oidcIssuer) {
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
42
|
// 标准模式:委托给 source Handler
|
|
@@ -53,7 +53,7 @@ class AutoDetectIdentityProviderHandler extends community_server_1.HttpHandler {
|
|
|
53
53
|
* - 标准模式:委托给 source Handler
|
|
54
54
|
*/
|
|
55
55
|
async handle(input) {
|
|
56
|
-
if (this.
|
|
56
|
+
if (this.oidcIssuer) {
|
|
57
57
|
const { response } = input;
|
|
58
58
|
response.writeHead(404, { 'Content-Type': 'application/json' });
|
|
59
59
|
response.end(JSON.stringify({ error: this.message }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutoDetectIdentityProviderHandler.js","sourceRoot":"","sources":["../../../src/identity/oidc/AutoDetectIdentityProviderHandler.ts"],"names":[],"mappings":";;;AAAA,iEAAqD;AACrD,8DAIiC;AAWjC;;;;;;GAMG;AACH,MAAa,iCAAkC,SAAQ,8BAAW;IAMhE,YAAY,UAAoD,EAAE;QAChE,KAAK,EAAE,CAAC;QANO,WAAM,GAAG,IAAA,oCAAY,EAAC,IAAI,CAAC,CAAC;QAO3C,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"AutoDetectIdentityProviderHandler.js","sourceRoot":"","sources":["../../../src/identity/oidc/AutoDetectIdentityProviderHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { getLoggerFor } from 'global-logger-factory';\nimport {\n HttpHandler,\n type HttpHandlerInput,\n NotImplementedHttpError,\n} from '@solid/community-server';\n\nexport interface AutoDetectIdentityProviderHandlerOptions {\n /** 外部 IdP 的基础 URL,如果提供则启用 SP 模式 */\n oidcIssuer?: string;\n /** 禁用时的消息 */\n message?: string;\n /** CSS 默认的 IdentityProviderHandler,标准模式下委托给它 */\n source?: HttpHandler;\n}\n\n/**\n * Auto-detect Identity Provider Handler\n *\n * 自动检测运行模式:\n * - 如果配置了 oidcIssuer -> SP 模式:禁用本地账户管理\n * - 如果没有配置 oidcIssuer -> 标准模式:委托给 CSS 默认 Handler\n */\nexport class AutoDetectIdentityProviderHandler extends HttpHandler {\n private readonly logger = getLoggerFor(this);\n private readonly oidcIssuer?: string;\n private readonly message: string;\n private readonly source?: HttpHandler;\n\n constructor(options: AutoDetectIdentityProviderHandlerOptions = {}) {\n super();\n this.oidcIssuer = options.oidcIssuer;\n this.message = options.message ?? 'Account management handled by external IdP';\n this.source = options.source;\n\n if (this.oidcIssuer) {\n this.logger.info(`SP mode enabled: ${this.message}, external IdP: ${this.oidcIssuer}`);\n } else {\n this.logger.info('Standard mode enabled, delegating to source IdentityProviderHandler');\n }\n }\n\n /**\n * 判断是否处理请求\n * - SP 模式:拒绝所有 IdP 请求\n * - 标准模式:委托给 source Handler\n */\n public override async canHandle(input: HttpHandlerInput): Promise<void> {\n const url = input.request.url ?? '';\n\n // 检查是否是 IdP 路径\n if (!this.isIdpPath(url)) {\n throw new NotImplementedHttpError('Not an IdP request');\n }\n\n // SP 模式:接受 IdP 路径请求,在 handle 中返回 404\n if (this.oidcIssuer) {\n return;\n }\n\n // 标准模式:委托给 source Handler\n if (this.source) {\n await this.source.canHandle(input);\n } else {\n throw new NotImplementedHttpError('No source IdentityProviderHandler configured');\n }\n }\n\n /**\n * 处理请求\n * - SP 模式:不应该到达这里\n * - 标准模式:委托给 source Handler\n */\n public override async handle(input: HttpHandlerInput): Promise<void> {\n if (this.oidcIssuer) {\n const { response } = input;\n response.writeHead(404, { 'Content-Type': 'application/json' });\n response.end(JSON.stringify({ error: this.message }));\n return;\n }\n\n // 标准模式:委托给 source Handler\n if (this.source) {\n await this.source.handle(input);\n } else {\n throw new NotImplementedHttpError('No source IdentityProviderHandler configured');\n }\n }\n\n /**\n * 检查是否是 IdP 路径\n */\n private isIdpPath(url: string): boolean {\n const pathname = this.getPathname(url);\n return (\n pathname.startsWith('/idp/') ||\n pathname.startsWith('/.account/') ||\n pathname === '/register' ||\n pathname === '/login' ||\n pathname === '/logout'\n );\n }\n\n /**\n * 从 URL 提取 pathname\n */\n private getPathname(url: string): string {\n try {\n return new URL(url, 'http://localhost').pathname;\n } catch {\n return url.split('?')[0];\n }\n }\n}\n"]}
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
"extends": [
|
|
13
13
|
"css:dist/server/HttpHandler.jsonld#HttpHandler"
|
|
14
14
|
],
|
|
15
|
-
"comment": "Auto-detect Identity Provider Handler 自动检测运行模式: - 如果配置了
|
|
15
|
+
"comment": "Auto-detect Identity Provider Handler 自动检测运行模式: - 如果配置了 oidcIssuer -> SP 模式:禁用本地账户管理 - 如果没有配置 oidcIssuer -> 标准模式:委托给 CSS 默认 Handler",
|
|
16
16
|
"parameters": [
|
|
17
17
|
{
|
|
18
|
-
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#
|
|
18
|
+
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#AutoDetectIdentityProviderHandler_options_oidcIssuer",
|
|
19
19
|
"range": {
|
|
20
20
|
"@type": "ParameterRangeUnion",
|
|
21
21
|
"parameterRangeElements": [
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
"memberFieldName": "logger"
|
|
61
61
|
},
|
|
62
62
|
{
|
|
63
|
-
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#
|
|
64
|
-
"memberFieldName": "
|
|
63
|
+
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#AutoDetectIdentityProviderHandler__member_oidcIssuer",
|
|
64
|
+
"memberFieldName": "oidcIssuer"
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
67
|
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#AutoDetectIdentityProviderHandler__member_message",
|
|
@@ -97,9 +97,9 @@
|
|
|
97
97
|
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#AutoDetectIdentityProviderHandler_options__constructorArgument",
|
|
98
98
|
"fields": [
|
|
99
99
|
{
|
|
100
|
-
"keyRaw": "
|
|
100
|
+
"keyRaw": "oidcIssuer",
|
|
101
101
|
"value": {
|
|
102
|
-
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#
|
|
102
|
+
"@id": "undefineds:dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld#AutoDetectIdentityProviderHandler_options_oidcIssuer"
|
|
103
103
|
}
|
|
104
104
|
},
|
|
105
105
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { HttpHandler, type HttpHandlerInput } from '@solid/community-server';
|
|
2
2
|
export interface AutoDetectOidcHandlerOptions {
|
|
3
3
|
/** 外部 IdP 的基础 URL,如果提供则启用 SP 模式 */
|
|
4
|
-
|
|
4
|
+
oidcIssuer?: string;
|
|
5
5
|
/** 禁用原因说明 */
|
|
6
6
|
message?: string;
|
|
7
7
|
/** JWKS 缓存时间 (ms) */
|
|
@@ -11,14 +11,14 @@ export interface AutoDetectOidcHandlerOptions {
|
|
|
11
11
|
* Auto-detect OIDC Handler
|
|
12
12
|
*
|
|
13
13
|
* 自动检测运行模式:
|
|
14
|
-
* - 如果配置了
|
|
15
|
-
* - 如果没有配置
|
|
14
|
+
* - 如果配置了 oidcIssuer -> SP 模式:禁用本地 OIDC,代理外部 IdP 的 JWKS
|
|
15
|
+
* - 如果没有配置 oidcIssuer -> 标准模式:所有 OIDC 请求透传(由 CSS 默认 Handler 处理)
|
|
16
16
|
*
|
|
17
17
|
* 使用方式:在 HTTP pipeline 中替换默认的 OidcHandler
|
|
18
18
|
*/
|
|
19
19
|
export declare class AutoDetectOidcHandler extends HttpHandler {
|
|
20
20
|
private readonly logger;
|
|
21
|
-
private readonly
|
|
21
|
+
private readonly oidcIssuer?;
|
|
22
22
|
private readonly jwksUrl?;
|
|
23
23
|
private readonly message;
|
|
24
24
|
private readonly cacheMs;
|
|
@@ -8,8 +8,8 @@ const community_server_1 = require("@solid/community-server");
|
|
|
8
8
|
* Auto-detect OIDC Handler
|
|
9
9
|
*
|
|
10
10
|
* 自动检测运行模式:
|
|
11
|
-
* - 如果配置了
|
|
12
|
-
* - 如果没有配置
|
|
11
|
+
* - 如果配置了 oidcIssuer -> SP 模式:禁用本地 OIDC,代理外部 IdP 的 JWKS
|
|
12
|
+
* - 如果没有配置 oidcIssuer -> 标准模式:所有 OIDC 请求透传(由 CSS 默认 Handler 处理)
|
|
13
13
|
*
|
|
14
14
|
* 使用方式:在 HTTP pipeline 中替换默认的 OidcHandler
|
|
15
15
|
*/
|
|
@@ -17,12 +17,12 @@ class AutoDetectOidcHandler extends community_server_1.HttpHandler {
|
|
|
17
17
|
constructor(options = {}) {
|
|
18
18
|
super();
|
|
19
19
|
this.logger = (0, global_logger_factory_1.getLoggerFor)(this);
|
|
20
|
-
this.
|
|
21
|
-
this.jwksUrl = this.
|
|
20
|
+
this.oidcIssuer = options.oidcIssuer;
|
|
21
|
+
this.jwksUrl = this.oidcIssuer ? `${this.oidcIssuer.replace(/\/$/, '')}/.oidc/jwks` : undefined;
|
|
22
22
|
this.message = options.message ?? 'OIDC disabled in storage provider mode';
|
|
23
23
|
this.cacheMs = options.cacheMs ?? 300000; // 默认 5 分钟
|
|
24
|
-
if (this.
|
|
25
|
-
this.logger.info(`SP mode enabled, external IdP: ${this.
|
|
24
|
+
if (this.oidcIssuer) {
|
|
25
|
+
this.logger.info(`SP mode enabled, external IdP: ${this.oidcIssuer}, JWKS: ${this.jwksUrl}`);
|
|
26
26
|
}
|
|
27
27
|
else {
|
|
28
28
|
this.logger.info('Standard mode enabled, OIDC requests will pass through');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutoDetectOidcHandler.js","sourceRoot":"","sources":["../../../src/identity/oidc/AutoDetectOidcHandler.ts"],"names":[],"mappings":";;;AAAA,uCAA+B;AAC/B,iEAAqD;AACrD,8DAKiC;AAgBjC;;;;;;;;GAQG;AACH,MAAa,qBAAsB,SAAQ,8BAAW;IAQpD,YAAY,UAAwC,EAAE;QACpD,KAAK,EAAE,CAAC;QARO,WAAM,GAAG,IAAA,oCAAY,EAAC,IAAI,CAAC,CAAC;QAS3C,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"AutoDetectOidcHandler.js","sourceRoot":"","sources":["../../../src/identity/oidc/AutoDetectOidcHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { URL } from 'node:url';\nimport { getLoggerFor } from 'global-logger-factory';\nimport {\n HttpHandler,\n type HttpHandlerInput,\n NotImplementedHttpError,\n InternalServerError,\n} from '@solid/community-server';\n\nexport interface AutoDetectOidcHandlerOptions {\n /** 外部 IdP 的基础 URL,如果提供则启用 SP 模式 */\n oidcIssuer?: string;\n /** 禁用原因说明 */\n message?: string;\n /** JWKS 缓存时间 (ms) */\n cacheMs?: number;\n}\n\ninterface JwksCache {\n keys: unknown[];\n expiresAt: number;\n}\n\n/**\n * Auto-detect OIDC Handler\n *\n * 自动检测运行模式:\n * - 如果配置了 oidcIssuer -> SP 模式:禁用本地 OIDC,代理外部 IdP 的 JWKS\n * - 如果没有配置 oidcIssuer -> 标准模式:所有 OIDC 请求透传(由 CSS 默认 Handler 处理)\n *\n * 使用方式:在 HTTP pipeline 中替换默认的 OidcHandler\n */\nexport class AutoDetectOidcHandler extends HttpHandler {\n private readonly logger = getLoggerFor(this);\n private readonly oidcIssuer?: string;\n private readonly jwksUrl?: string;\n private readonly message: string;\n private readonly cacheMs: number;\n private jwksCache?: JwksCache;\n\n constructor(options: AutoDetectOidcHandlerOptions = {}) {\n super();\n this.oidcIssuer = options.oidcIssuer;\n this.jwksUrl = this.oidcIssuer ? `${this.oidcIssuer.replace(/\\/$/, '')}/.oidc/jwks` : undefined;\n this.message = options.message ?? 'OIDC disabled in storage provider mode';\n this.cacheMs = options.cacheMs ?? 300000; // 默认 5 分钟\n\n if (this.oidcIssuer) {\n this.logger.info(`SP mode enabled, external IdP: ${this.oidcIssuer}, JWKS: ${this.jwksUrl}`);\n } else {\n this.logger.info('Standard mode enabled, OIDC requests will pass through');\n }\n }\n\n /**\n * 判断是否处理请求\n * - SP 模式:只处理 JWKS 请求,其他 OIDC 请求返回 501\n * - 标准模式:不处理任何请求(透传给 CSS 默认 Handler)\n */\n public override async canHandle({ request }: HttpHandlerInput): Promise<void> {\n const url = request.url ?? '';\n\n // 检查是否是 OIDC 路径\n if (!this.isOidcPath(url)) {\n throw new NotImplementedHttpError('Not an OIDC request');\n }\n\n // 标准模式:不处理,透传给 CSS 默认 Handler\n if (!this.jwksUrl) {\n throw new NotImplementedHttpError('Pass through to default OIDC handler');\n }\n\n // SP 模式:只有 JWKS 请求可以处理\n if (!this.isJwksPath(url)) {\n throw new NotImplementedHttpError(\n `External IdP mode: ${this.message}. Authentication handled by external IdP.`\n );\n }\n }\n\n /**\n * 处理请求\n * - SP 模式:代理 JWKS\n * - 标准模式:不应该到达这里\n */\n public override async handle({ response }: HttpHandlerInput): Promise<void> {\n // 标准模式:不应该到达这里\n if (!this.jwksUrl) {\n throw new InternalServerError('AutoDetectOidcHandler should not handle requests in standard mode');\n }\n\n try {\n const jwks = await this.fetchJwks();\n\n response.statusCode = 200;\n response.setHeader('Content-Type', 'application/json');\n response.setHeader('Cache-Control', `public, max-age=${Math.floor(this.cacheMs / 1000)}`);\n response.end(JSON.stringify(jwks));\n\n this.logger.debug('JWKS proxy successful');\n } catch (error) {\n this.logger.error(`JWKS proxy failed: ${(error as Error).message}`);\n throw new InternalServerError('Failed to proxy JWKS request', { cause: error });\n }\n }\n\n /**\n * 获取并缓存 JWKS\n */\n private async fetchJwks(): Promise<{ keys: unknown[] }> {\n // 检查缓存\n if (this.jwksCache && this.jwksCache.expiresAt > Date.now()) {\n this.logger.debug('Returning cached JWKS');\n return { keys: this.jwksCache.keys };\n }\n\n if (!this.jwksUrl) {\n throw new Error('External JWKS URL not configured');\n }\n\n this.logger.debug(`Fetching JWKS from ${this.jwksUrl}`);\n\n const res = await fetch(this.jwksUrl, {\n headers: { Accept: 'application/json' },\n });\n\n if (!res.ok) {\n throw new Error(`Failed to fetch JWKS: ${res.status} ${res.statusText}`);\n }\n\n const jwks = await res.json() as { keys: unknown[] };\n\n // 验证 JWKS 格式\n if (!Array.isArray(jwks.keys)) {\n throw new Error('Invalid JWKS format: missing keys array');\n }\n\n // 更新缓存\n this.jwksCache = {\n keys: jwks.keys,\n expiresAt: Date.now() + this.cacheMs,\n };\n\n this.logger.debug(`JWKS cached with ${jwks.keys.length} keys`);\n return jwks;\n }\n\n /**\n * 检查是否是 OIDC 路径\n */\n private isOidcPath(url: string): boolean {\n const pathname = this.getPathname(url);\n return (\n pathname.startsWith('/.oidc/') ||\n pathname === '/.well-known/openid-configuration' ||\n pathname === '/.well-known/oauth-authorization-server' ||\n pathname.startsWith('/idp/')\n );\n }\n\n /**\n * 检查是否是 JWKS 路径\n */\n private isJwksPath(url: string): boolean {\n const pathname = this.getPathname(url);\n return pathname === '/.oidc/jwks' || pathname === '/.oidc/jwks.json';\n }\n\n /**\n * 从 URL 提取 pathname\n */\n private getPathname(url: string): string {\n try {\n return new URL(url, 'http://localhost').pathname;\n } catch {\n // 如果解析失败,直接返回 url(可能是相对路径)\n return url.split('?')[0];\n }\n }\n}\n"]}
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
"extends": [
|
|
13
13
|
"css:dist/server/HttpHandler.jsonld#HttpHandler"
|
|
14
14
|
],
|
|
15
|
-
"comment": "Auto-detect OIDC Handler 自动检测运行模式: - 如果配置了
|
|
15
|
+
"comment": "Auto-detect OIDC Handler 自动检测运行模式: - 如果配置了 oidcIssuer -> SP 模式:禁用本地 OIDC,代理外部 IdP 的 JWKS - 如果没有配置 oidcIssuer -> 标准模式:所有 OIDC 请求透传(由 CSS 默认 Handler 处理) 使用方式:在 HTTP pipeline 中替换默认的 OidcHandler",
|
|
16
16
|
"parameters": [
|
|
17
17
|
{
|
|
18
|
-
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#
|
|
18
|
+
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#AutoDetectOidcHandler_options_oidcIssuer",
|
|
19
19
|
"range": {
|
|
20
20
|
"@type": "ParameterRangeUnion",
|
|
21
21
|
"parameterRangeElements": [
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
"memberFieldName": "logger"
|
|
61
61
|
},
|
|
62
62
|
{
|
|
63
|
-
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#
|
|
64
|
-
"memberFieldName": "
|
|
63
|
+
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#AutoDetectOidcHandler__member_oidcIssuer",
|
|
64
|
+
"memberFieldName": "oidcIssuer"
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
67
|
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#AutoDetectOidcHandler__member_jwksUrl",
|
|
@@ -113,9 +113,9 @@
|
|
|
113
113
|
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#AutoDetectOidcHandler_options__constructorArgument",
|
|
114
114
|
"fields": [
|
|
115
115
|
{
|
|
116
|
-
"keyRaw": "
|
|
116
|
+
"keyRaw": "oidcIssuer",
|
|
117
117
|
"value": {
|
|
118
|
-
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#
|
|
118
|
+
"@id": "undefineds:dist/identity/oidc/AutoDetectOidcHandler.jsonld#AutoDetectOidcHandler_options_oidcIssuer"
|
|
119
119
|
}
|
|
120
120
|
},
|
|
121
121
|
{
|
|
@@ -160,7 +160,7 @@ function buildRuntimeShorthand(runtimeEnv, options, state, baseEnv = NodeRuntime
|
|
|
160
160
|
['emailConfigPort', envValue('CSS_EMAIL_CONFIG_PORT') ?? '587'],
|
|
161
161
|
['emailConfigAuthUser', envValue('CSS_EMAIL_CONFIG_AUTH_USER') ?? ''],
|
|
162
162
|
['emailConfigAuthPass', envValue('CSS_EMAIL_CONFIG_AUTH_PASS') ?? ''],
|
|
163
|
-
['
|
|
163
|
+
['oidcIssuer', envValue('CSS_OIDC_ISSUER')],
|
|
164
164
|
['allowedHosts', envValue('CSS_ALLOWED_HOSTS')],
|
|
165
165
|
['nodeId', envValue('XPOD_NODE_ID')],
|
|
166
166
|
['nodeToken', envValue('XPOD_NODE_TOKEN')],
|