Repository navigation
Commit 946a173
feat(console): the installer OAuth client form shows the deployment's redirect URI and a reconnect keeps the stored client (#29772)
<!-- claude-projects-attribution: {"github_login":"zhuangjianguo"} -->
_Requested by **Steedos** · [project
thread](https://claude.ai/code/project/chan_018ETKaNwMZCNRYD7D8Q9Ubb?thread=cmsg_018ETKaNwMZCNRYD7D8Q9UbbSYY7fbDBFK5hXog1WZFvie)_
Fixes #28869
Clause-②: yes
Metadata-protocol: none
The card's second PR (claim 6581428199 as amended by 6581522588, option
B, PR 2 leg). The card's first PR, #29496, landed the client form; this
one adds item 2 and the "keep unless replaced" half of item 3, now that
the server answers both (#29463, server PR #29701 `c779611e`; spec key
`ConnectorConnectionState.redirectUri` from #29618 `744211fc`).
## 维护者速读
- 改了什么:连接器连接页的 OAuth 客户端表单现在显示服务端给出的重定向 URI(连接状态读取里的
`redirectUri`),带「复制」按钮;服务端给不出时明确提示「此部署没有重定向
URI」,绝不自行拼接。重新连接已保存客户端的连接时,默认「沿用已存储的客户端」,发起连接请求不带请求体,由服务端复用已存的客户端和密钥;点「替换已存储的客户端」才显示
ID(预填)和空的密钥框并发送新客户端。断开连接后页面重新读取状态,下次「连接」仍能显示 URI。
- 为什么改:#28869 第 2、3 项的后半,服务端 #29463 已提供 URI 和「无请求体即复用」。
- 风险与回滚:只改控制台一页和语言包。语言包新增 8 个键,改写 `clientIntro`、`clientResend`
两个键的文案,不删键。回滚即撤掉本 PR,控制台回到第一个 PR 的行为(重新连接需重输密钥)。
-
先看:`ui/packages/app-shell/src/views/setup/ConnectorConnectionsPage.tsx`
的 `startConnect`(`replacing: !state.client` 默认沿用)、`submitClient`(沿用时
`client` 为 undefined、不带请求体)、`confirmRevoke`(断开后重新 GET)、表单里的重定向 URI 区块。
- 两分钟验证:`pnpm --dir ui exec vitest run
packages/app-shell/src/views/setup/ConnectorConnectionsPage.test.tsx`,应看到
21 条全过。
- 需要你做的:无,席位落地。
新增语言键(`connectorConnections`
下,十种语言):`redirectUriLabel`、`redirectUriCopy`、`redirectUriCopied`、`redirectUriHint`、`redirectUriMissing`、`clientKeepHint`、`clientKeep`、`clientReplace`。改写文案的已有键:`clientIntro`、`clientResend`。
## What changes
- `ConnectorConnectionsPage.tsx`:
- The installer-client form shows `state.redirectUri` exactly as `GET
/automation/connectors/:name/connection` answered it, read-only, with a
Copy button (`navigator.clipboard.writeText`; a denied clipboard leaves
the selectable text). When the read answers none, the form says the
deployment has no redirect URI and to set `OS_BASE_URL` / `OS_AUTH_URL`.
No URI is built from the page's origin or parsed from prose.
- A connection whose status carries `client` opens Reconnect in keep
mode: no client fields, and Continue begins with no body, so the server
reuses the kept client (ask 2 of #29463). "Replace the stored client"
switches to the fields (client ID prefilled, secret empty) and sends `{
clientId, clientSecret? }`; "Keep the stored client" switches back.
- Disconnect re-reads the status after the revoke, because the revoke
answer carries no `redirectUri`. The read answer is applied (the revoke
answer only if that read fails), so the next Connect still shows the
URI.
- `@object-ui/i18n`: eight new keys and two reworded values in all ten
locales. `clientIntro` now points at the URI below instead of the
documentation; `clientResend` is now the replace hint. No key is
removed.
- Changeset `.changeset/28869-connect-redirect-uri-keep-client.md`
(`@object-ui/app-shell`, `@object-ui/i18n`: patch).
## Tests
`ConnectorConnectionsPage.test.tsx`, 21 cases (10 in `an
installer-supplied OAuth client`). New or changed:
- Keep default: the stored client is shown, there are no client fields,
and the begin POST has no body.
- Replace path: the id is prefilled, the secret is empty, and the new `{
clientId, clientSecret }` is sent; the secret is absent from the DOM
afterwards.
- The URI is shown exactly as answered (deliberately on another origin
than the page), and Copy writes that value.
- An absent URI shows the "has no redirect URI" line, no URI element and
no Copy button, and the form text contains neither `/oauth/callback` nor
the page origin.
- A re-read after disconnect: one more GET after the DELETE, then the
next Connect shows the URI.
- The existing disconnect case now queues the post-revoke status read.
## Acceptance notes
- The redirect URI comes only from the status read; the begin answer and
the refusal prose are not read for it.
- Live run used a local stub for the vendor's authorize/token endpoints
on `app-crm`, not a real vendor.
## Verification
<details><summary>Page suite and ablations (head b223134; re-run on
merge c67b39c)</summary>
- Page suite: 21 passed on b223134. With `packages/i18n/` on merge head
c67b39c: Test Files 96 passed, Tests 1464 passed, 13 skipped
(os-verify-lock VERDICT 0).
- Ablations, each via `scripts/ablation-replace.mjs`, restored blob ==
HEAD with `git diff HEAD` empty:
- B1, keep default off (`replacing: true`): 2 failed / 19 passed (keep
pin, replace pin).
- B2, replace path sends nothing when a client is stored: 1 failed / 20
passed (replace pin).
- B3, URI guessed from `window.location.origin` when absent: 1 failed /
20 passed (absent-URI pin).
- B4, no re-read after disconnect (`const read = out`): 1 failed / 20
passed (re-read pin).
- ui vitest aliases `@object-ui/*` to source, so no rebuild leg was
owed.
</details>
<details><summary>Packages and gates</summary>
- `turbo run type-check --filter=@object-ui/app-shell
--filter=@object-ui/i18n` on b223134: 66 tasks successful, VERDICT 0.
- `pnpm --dir ui exec vitest run scripts/` on c67b39c: Test Files 170
passed, 2 skipped; Tests 4977 passed.
- `dispatch-gates --commands` on c67b39c: 35 families, all run, each
exit 0. `dispatch-gates --ran` reconciles 35 derived, 35 run, 0
NOT-MEASURED, 0 UNRUN.
- Main re-merged at 9b3449b: six commits, no file shared with this
branch, and the derivation gives the same 35 commands. On 9b3449b the
page and `packages/i18n/` suites pass again (96 files, 1464 passed, 13
skipped), and the `@object-ui/app-shell` type-check is clean after `pnpm
install` picked up main's new `pinyin-pro` dependency.
- `pnpm check:changeset-fixed` (roster under `.changeset/`): green.
</details>
<details><summary>Live run (app-crm, Vite source Console, head
b223134)</summary>
`objectstack dev --seed-admin --fresh` on app-crm with `OS_BASE_URL` at
the Console origin, the Vite Console proxying to it, a local vendor
stub, and an installer connector saved through `PUT
/meta/connector/vendor_docs`.
1. The status read before any connect answered `redirectUri:
http://localhost:5233/api/v1/automation/connectors/oauth/callback` with
status `not_connected`. The form showed that value, and Copy put it on
the clipboard.
2. Connect with a client sent body keys `clientId` and `clientSecret`.
3. Reconnect opened in keep mode with no inputs. Continue sent a POST
with no body. The stub saw authorize with the stored client id and a
token request authenticated as that client, and the reconnect landed
with a new `connectedAt`.
4. Replace showed the id prefilled and the secret empty.
5. After Disconnect, Connect still showed the URI. The typed secret
never appeared in the page HTML.
</details>
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QsR2jQhfprmgNtfhzNURJ6)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 5c4e752 commit 946a173
13 files changed
Lines changed: 335 additions & 93 deletions
File tree
- .changeset
- ui/packages
- app-shell/src/views/setup
- i18n/src/locales
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
28 | 31 | | |
29 | 32 | | |
30 | 33 | | |
| |||
235 | 238 | | |
236 | 239 | | |
237 | 240 | | |
| 241 | + | |
| 242 | + | |
238 | 243 | | |
239 | 244 | | |
240 | 245 | | |
| |||
263 | 268 | | |
264 | 269 | | |
265 | 270 | | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
266 | 280 | | |
267 | 281 | | |
268 | 282 | | |
269 | | - | |
| 283 | + | |
270 | 284 | | |
271 | 285 | | |
272 | 286 | | |
| |||
330 | 344 | | |
331 | 345 | | |
332 | 346 | | |
333 | | - | |
334 | | - | |
335 | | - | |
336 | | - | |
337 | | - | |
338 | | - | |
339 | | - | |
340 | | - | |
341 | | - | |
342 | | - | |
| 347 | + | |
| 348 | + | |
343 | 349 | | |
344 | 350 | | |
345 | 351 | | |
346 | 352 | | |
347 | 353 | | |
348 | | - | |
349 | | - | |
350 | | - | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
351 | 376 | | |
352 | 377 | | |
353 | | - | |
354 | | - | |
355 | | - | |
| 378 | + | |
356 | 379 | | |
357 | 380 | | |
358 | 381 | | |
359 | | - | |
| 382 | + | |
360 | 383 | | |
361 | 384 | | |
362 | 385 | | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
363 | 432 | | |
364 | 433 | | |
365 | 434 | | |
| |||
0 commit comments