Skip to content

fix(ui): validate webhook fields in install-key drawers - #6866

Merged
otavio merged 1 commit into
masterfrom
fix/ui/install-keys-webhook
Aug 7, 2026
Merged

fix(ui): validate webhook fields in install-key drawers#6866
otavio merged 1 commit into
masterfrom
fix/ui/install-keys-webhook

Conversation

@luizhf42

@luizhf42 luizhf42 commented Aug 6, 2026

Copy link
Copy Markdown
Member

What

Replaced the four webhook-mode fields in the install-key drawers (Create and Edit) with purpose-built components that properly validate input and block submit on invalid values.

Why

The webhook URL only checked for an http:///https:// prefix via regex — structurally invalid URLs like https:// (no host) passed client-side validation. The signing secret was a plain InputField type="password" with no visibility toggle. The reply timeout and callback window used InputField type="number", which accepts non-numeric characters (e, +, -, .) past the browser's native spinner and rendered inconsistently across browsers. On mobile, the two-column grid-cols-2 layout overflowed the drawer.

Changes

  • URL validation (helpers.ts, ModeField.tsx): replaced the prefix regex in validateModeConfig with isWebhookUrl, which uses new URL() + protocol check. The URL field now shows an inline error on blur when the value is non-empty and structurally invalid.
  • Signing secret (ModeField.tsx): swapped InputField type="password" for PasswordField with suppressPasswordManager. In edit mode (isEditing prop), the hint tells the user to leave the field blank to keep the current secret.
  • Timeout / callback window (ModeField.tsx): swapped InputField type="number" for NumericInput (digit-only regex filter via type="text" + inputMode="numeric"). Each field shows an inline range error and eagerly syncs the parsed value to the parent on every keystroke, so validateModeConfig always sees the current typed value and disables the submit button while out of range. On blur, the value clamps to the valid range.
  • Range constants (helpers.ts): extracted TIMEOUT_MIN/MAX and WINDOW_MIN_H/MAX_H so inline errors and validateModeConfig share a single source of truth.
  • Mobile layout (ModeField.tsx): replaced grid grid-cols-2 with flex flex-wrap gap-3 so the timeout and callback fields stack when the drawer is narrow.

Testing

  • isWebhookUrl: 8 cases (valid URLs, protocol-only, wrong protocol, empty, whitespace)
  • validateModeConfig: updated to reject https:// (no host); new cases for out-of-range timeout (0, 16) and callback (0, 25h)
  • Full suite: 3023 tests green, build and lint clean

@luizhf42
luizhf42 requested a review from a team as a code owner August 6, 2026 20:08
@luizhf42 luizhf42 self-assigned this Aug 6, 2026
@luizhf42 luizhf42 added kind/bug Something isn't working area/ui labels Aug 6, 2026
@otavio

otavio commented Aug 7, 2026

Copy link
Copy Markdown
Member

/review

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

Claude finished @otavio's task in 4m 3s —— View job


Code Review Complete

Reviewed 5 files across code quality, security, testing, language patterns, and architecture. 1 inline issue posted (1 medium).

The URL/secret/numeric validation changes themselves are solid — isWebhookUrl, the shared range constants, the eager parent-sync so validateModeConfig blocks submit while out of range, and the expanded test coverage all look correct and consistent. The one concern is a state-lifecycle regression:

  • [medium] WebhookPanel now seeds timeoutStr/windowStr/urlError from props via mount-only useState. Because index.tsx reuses a single EditInstallKeyDrawer and Drawer keeps children mounted while closed, editing two webhook-mode keys back-to-back leaves the timeout/callback-window fields showing the previous key's values while the parent state (and the submitted payload) holds the new key's — see the inline comment for the repro and suggested fix.

If you've addressed the feedback and want a new review, tag @shellhub-io/admin and a team member can trigger it.
· fix/ui/install-keys-webhook

Comment thread ui/apps/console/src/pages/install-keys/ModeField.tsx
The webhook URL field only checked for an `http://` or `https://` prefix
via regex, so structurally invalid URLs like `https://` (no host) passed.
The signing secret used a plain `InputField type="password"` with no
visibility toggle. The reply timeout and callback window used
`InputField type="number"`, which accepts non-numeric characters
(`e`, `+`, `-`, `.`) and rendered browser-native spinners.

- Replace the URL regex with `new URL()` + protocol check
  (`isWebhookUrl` in `helpers.ts`); add inline blur-validation error
- Swap the secret to `PasswordField` with `suppressPasswordManager`;
  show a "leave blank to keep" hint when editing an existing webhook key
- Swap timeout and callback window to `NumericInput` with digit-only
  filtering, inline range errors, and eager parent sync so
  `validateModeConfig` always sees the current typed value and blocks
  submit while out of range
- Extract range constants (`TIMEOUT_MIN/MAX`, `WINDOW_MIN_H/MAX_H`)
  shared between inline errors and `validateModeConfig`
- Fix mobile layout: replace `grid-cols-2` with `flex flex-wrap` so the
  two numeric fields stack when the drawer is narrow
@luizhf42
luizhf42 force-pushed the fix/ui/install-keys-webhook branch from a5a1a3c to a33ac94 Compare August 7, 2026 12:27
@otavio

otavio commented Aug 7, 2026

Copy link
Copy Markdown
Member

/review

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

Claude finished @otavio's task in 4m 10s —— View job


Code Review Complete

Reviewed 5 files across code quality, security, testing, language patterns, and architecture — no new issues found. The code looks good as-is.

The previously-flagged state-lifecycle concern (stale numeric/urlError buffers when editing two webhook keys back-to-back) is correctly resolved by keying WebhookPanel on panelKey: closing the drawer drives installKey to null so panelKeyundefined (unmount), and switching keys changes the key, while useResetOnOpen's during-render reset ensures the panel always remounts against the current key's values. The isWebhookUrl validation, shared range constants, eager parent-sync that blocks submit while out of range, and expanded test coverage all check out.

If you push additional changes and want a new review, tag @shellhub-io/admin and a team member can trigger it.
· fix/ui/install-keys-webhook

@otavio
otavio merged commit a300fee into master Aug 7, 2026
38 checks passed
@otavio
otavio deleted the fix/ui/install-keys-webhook branch August 7, 2026 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ui kind/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants