Skip to content

fix(admin-ui): Use typescript generated client for Webhooks pages#2488

Merged
duttarnab merged 21 commits intomainfrom
admin-ui-2433
Dec 5, 2025
Merged

fix(admin-ui): Use typescript generated client for Webhooks pages#2488
duttarnab merged 21 commits intomainfrom
admin-ui-2433

Conversation

@syntrydy
Copy link
Contributor

@syntrydy syntrydy commented Dec 1, 2025

#2433
Closes #2433

Summary by CodeRabbit

  • New Features

    • Complete webhook UI: list, add, edit, form with commit confirmations, search/filter/sort, results-per-page, shortcode popovers, JSON body editor, and URL validation/checker.
    • Audit-enabled webhook create/update/delete hooks and automatic webhook triggering on scope create/update/delete.
  • Bug Fixes / Improvements

    • Stricter HTTPS URL validation and exposed validation utilities.
    • UI components improved typing, optional class/style props, and memoization for better performance.
  • Internationalization

    • Added EN/ES/FR/PT translations for webhook-related UI strings and messages.

✏️ Tip: You can customize this high-level summary in your review settings.

@syntrydy syntrydy self-assigned this Dec 1, 2025
@syntrydy syntrydy requested a review from duttarnab as a code owner December 1, 2025 05:15
@syntrydy syntrydy added comp-admin-ui Component affected by issue or PR comp-docker-admin-ui Component affected by issue or PR labels Dec 1, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 1, 2025

Warning

Rate limit exceeded

@syntrydy has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 7 minutes and 52 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 88ed430 and 1d5b6f7.

📒 Files selected for processing (1)
  • admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1 hunks)
📝 Walkthrough

Walkthrough

Replaces legacy JavaScript webhook UI with TypeScript implementations; adds typed hooks and audit logging for webhook mutations, a Redux slice, URL validation, new locale keys, ShortCodesIcon prop relaxations, centralized webhook exports, and dispatches webhook triggers on scope create/update/delete.

Changes

Cohort / File(s) Summary
Localization
admin-ui/app/locales/en/translation.json, admin-ui/app/locales/es/translation.json, admin-ui/app/locales/fr/translation.json, admin-ui/app/locales/pt/translation.json
Added results_per_page and webhook-related keys: webhook_form_description, no_webhooks_found, create_first_webhook, and invalid_url_error.
SVG icon
admin-ui/app/components/SVG/menu/ShortCodesIcon.tsx
Made className and style optional on props; defaulted style = {}; pass className to <svg> and merge incoming style with fixed width.
Shortcode UI
admin-ui/plugins/admin/components/Webhook/ShortcodePopover.tsx
Rewrote as typed, memoized React component with internal Label; removed PropTypes; tightened types, anchor handling, imports, and merged wrapper styles.
Pages removed (JS)
admin-ui/plugins/admin/components/Webhook/WebhookAddPage.js, .../WebhookEditPage.js, .../WebhookListPage.js, .../WebhookForm.js
Deleted legacy JavaScript webhook pages/components and their exports.
Pages added (TS)
admin-ui/plugins/admin/components/Webhook/WebhookAddPage.tsx, .../WebhookEditPage.tsx, .../WebhookListPage.tsx
Added TypeScript page components; Add/Edit render WebhookForm; List page includes permissions, search, sorting, pagination, actions and audit-aware delete flow.
Form added (TS)
admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx
New Formik-based WebhookForm implementing validation, feature selection, JSON body editor, shortcode helpers, commit dialog, create/update flows, navigation and change tracking.
Search UI
admin-ui/plugins/admin/components/Webhook/WebhookSearch.tsx
New WebhookSearch component (pattern input, sort-by, sort-order toggle, results-per-page) and exported WebhookSortBy type.
URL validation
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts
Added isAllowed and isValid(url) with blocked-schemes, private/localhost detection and regex validation.
Audit & mutation hooks
admin-ui/plugins/admin/components/Webhook/hooks/*
Added useWebhookAudit (initAudit, logAction) and mutation hooks useCreateWebhookWithAudit, useUpdateWebhookWithAudit, useDeleteWebhookWithAudit performing API mutations, audit logging, toasts, and query invalidation; added hooks index re-export.
Types
admin-ui/plugins/admin/components/Webhook/types/*
New TypeScript types and re-exports (WebhookFormValues, HttpHeader, shortcode-related types, PagedWebhookResult, etc.) and a barrel export.
Component & hooks barrel
admin-ui/plugins/admin/components/Webhook/index.ts, .../hooks/index.ts
New central re-exports for webhook components, utilities (isValid, isAllowed), types and hooks.
Redux slice
admin-ui/plugins/admin/redux/features/WebhookSlice.ts
New Redux Toolkit slice webhook with state, reducers/actions for CRUD, features, modal and trigger flows; runtime registers reducer as webhookReducer.
Sagas / Types update
admin-ui/plugins/admin/redux/sagas/types/state.ts
Replaced inline webhook reducer shape with WebhookSliceState type reference.
Theme context export
admin-ui/app/context/theme/themeContext.tsx
Exported ThemeContextType interface.
Scopes integration
admin-ui/plugins/auth-server/components/Scopes/ScopeAddPage.tsx, .../ScopeEditPage.tsx, .../ScopeListPage.tsx
Import and dispatch triggerWebhook(...) after scope create/update/delete success to emit webhook events.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI as Webhook UI (List/Form/Scopes)
    participant Hooks as useCreate/Update/DeleteWithAudit
    participant API as JansConfigApi
    participant Audit as useWebhookAudit
    participant Cache as QueryCache

    User->>UI: submit create/update/delete or perform scope action
    UI->>Hooks: call mutation(payload)
    Hooks->>API: POST / PUT / DELETE request
    API-->>Hooks: response (success / error)
    Hooks->>Audit: logAction(actionType, resource, payload)
    Hooks->>Cache: invalidate getAllWebhooks query
    Hooks-->>UI: return result
    UI->>User: show toast / navigate / show error
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Files needing extra attention:
    • admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx — Formik lifecycle, validation, shortcode insertion, cursor handling, submission and navigation.
    • admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts — API error extraction, audit integration, toast UX, and query invalidation.
    • admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx — permissions gating, pagination, search/sort interactions, and action wiring.
    • admin-ui/plugins/admin/redux/features/WebhookSlice.ts — reducer logic, actions, and runtime registration.
    • admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts — compatibility with generated client types.

Possibly related PRs

Suggested reviewers

  • duttarnab
  • moabu

Poem

"I hopped through code with nimble paws,
Types and hooks and shiny laws,
Webhooks whisper, locales cheer,
Shortcodes nestle, events appear,
A rabbit grins — the build draws near!" 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes out-of-scope changes: it adds webhook triggering calls in ScopeAddPage, ScopeEditPage, and ScopeListPage, which extends webhook functionality beyond the stated objective of migrating to TypeScript-generated types and removing redundant code. Separate the scope webhook integration changes into a distinct PR focused on webhook event triggering for feature creation/update/deletion, keeping this PR focused solely on the client migration.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: migrating Webhooks pages to use the TypeScript generated client instead of manual types, which is the core objective of this PR.
Linked Issues check ✅ Passed The PR successfully implements all three objectives from issue #2433: (1) replaces manually created types with TypeScript generated client types, (2) removes redux-related Webhooks code (WebhookSlice, hooks, mutations), and (3) eliminates manually added types.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@mo-auto mo-auto added the kind-bug Issue or PR is a bug in existing functionality label Dec 1, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fe2881e and a281d12.

📒 Files selected for processing (23)
  • admin-ui/app/components/SVG/menu/ShortCodesIcon.tsx (1 hunks)
  • admin-ui/app/locales/en/translation.json (2 hunks)
  • admin-ui/app/locales/es/translation.json (2 hunks)
  • admin-ui/app/locales/fr/translation.json (2 hunks)
  • admin-ui/app/locales/pt/translation.json (2 hunks)
  • admin-ui/plugins/admin/components/Webhook/ShortcodePopover.tsx (4 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookAddPage.js (0 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookAddPage.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookEditPage.js (0 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookEditPage.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookForm.js (0 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookListPage.js (0 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookSearch.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (2 hunks)
  • admin-ui/plugins/admin/components/Webhook/hooks/index.ts (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/hooks/useWebhookAudit.ts (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/index.ts (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/types/index.ts (1 hunks)
  • admin-ui/plugins/admin/redux/features/WebhookSlice.ts (1 hunks)
💤 Files with no reviewable changes (4)
  • admin-ui/plugins/admin/components/Webhook/WebhookEditPage.js
  • admin-ui/plugins/admin/components/Webhook/WebhookAddPage.js
  • admin-ui/plugins/admin/components/Webhook/WebhookListPage.js
  • admin-ui/plugins/admin/components/Webhook/WebhookForm.js
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-07T12:55:26.241Z
Learnt from: kdhttps
Repo: GluuFederation/flex PR: 2378
File: admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx:93-104
Timestamp: 2025-11-07T12:55:26.241Z
Learning: In the Cedarling configuration feature (admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx), the sync role to scopes mappings operation depends on the `auiPolicyStoreUrl`. The backend fetches content from this URL and syncs roles based on the response. Therefore, the audit log for the sync operation should include the `auiPolicyStoreUrl` in its payload to provide proper audit context.

Applied to files:

  • admin-ui/plugins/admin/components/Webhook/hooks/useWebhookAudit.ts
🧬 Code graph analysis (7)
admin-ui/plugins/admin/components/Webhook/WebhookEditPage.tsx (1)
admin-ui/app/components/Card/Card.tsx (1)
  • Card (27-27)
admin-ui/plugins/admin/components/Webhook/WebhookAddPage.tsx (1)
admin-ui/app/components/Card/Card.tsx (1)
  • Card (27-27)
admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (2)
admin-ui/plugins/admin/components/Webhook/hooks/useWebhookAudit.ts (4)
  • useWebhookAudit (21-56)
  • CREATE (58-58)
  • UPDATE (58-58)
  • DELETION (58-58)
admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (1)
  • WebhookEntry (5-5)
admin-ui/plugins/admin/redux/features/WebhookSlice.ts (2)
admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (4)
  • TriggerPayload (87-90)
  • WebhookSliceState (64-85)
  • WebhookEntry (5-5)
  • AuiFeature (5-5)
admin-ui/plugins/admin/redux/sagas/types/userAction.ts (1)
  • ActionPayload (7-9)
admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (6)
admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (3)
  • WebhookEntry (5-5)
  • WebhookFormValues (7-15)
  • CursorPosition (59-62)
admin-ui/plugins/admin/helper/webhook.ts (1)
  • buildWebhookInitialValues (29-41)
admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (2)
  • useCreateWebhookWithAudit (19-57)
  • useUpdateWebhookWithAudit (59-97)
admin-ui/plugins/admin/helper/validations/webhookValidation.ts (1)
  • getWebhookValidationSchema (4-38)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)
  • isValid (26-31)
admin-ui/plugins/admin/components/Webhook/index.ts (1)
  • isValid (7-7)
admin-ui/plugins/admin/components/Webhook/ShortcodePopover.tsx (1)
admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (2)
  • ShortcodeLabelProps (42-46)
  • ShortcodePopoverProps (36-40)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)
admin-ui/plugins/admin/components/Webhook/index.ts (2)
  • isAllowed (7-7)
  • isValid (7-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (18)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)

1-33: LGTM! Clean TypeScript migration with improved structure.

The refactoring introduces explicit typing, extracts the isAllowed helper for better separation of concerns, and properly handles null/undefined cases. The early-return pattern improves readability while preserving the original validation logic.

admin-ui/app/locales/es/translation.json (1)

442-442: LGTM! Spanish translations added for webhook UI.

The new translation keys support pagination and webhook management features. The Spanish text appears grammatically correct and aligns with the webhook UI requirements described in the PR objectives.

Also applies to: 740-742

admin-ui/plugins/admin/components/Webhook/types/index.ts (1)

1-1: LGTM! Standard barrel export pattern.

This centralizes webhook type exports, providing a clean public API surface for the webhook module. Consumers can now import types via import { ... } from '.../Webhook/types'.

admin-ui/app/locales/pt/translation.json (1)

332-332: LGTM! Portuguese translations added for webhook UI.

The translations mirror the structure in other locale files and support the new webhook management features. The Portuguese text appears grammatically correct.

Also applies to: 697-699

admin-ui/plugins/admin/components/Webhook/WebhookEditPage.tsx (1)

6-12: No action required—WebhookForm correctly handles edit mode and webhook loading.

The component retrieves the webhook ID from URL parameters via useParams() (line 55) and loads the webhook data from Redux state, which is populated by WebhookListPage before navigation. The form detects edit mode by checking if both id and selectedWebhook exist (line 166), and queries webhook features conditionally based on the presence of an ID (line 66-68). No props are needed because the component relies on routing context and Redux state, which is the intended design pattern.

admin-ui/plugins/admin/components/Webhook/WebhookAddPage.tsx (1)

6-12: Routing and form mode differentiation are correctly implemented.

The webhook pages are properly distinguished:

  • WebhookAddPage routes to /webhook/add (no ID parameter)
  • WebhookEditPage routes to /webhook/edit/:id (with ID parameter)

WebhookForm uses useParams() to extract the id from the route, enabling it to differentiate between modes: when id is present, it loads webhook features for editing and uses updateWebhook; when absent, it uses createWebhook. The conditional rendering {id && selectedWebhook?.inum && ...} further confirms mode-specific logic.

admin-ui/app/locales/fr/translation.json (1)

365-365: Webhook & pagination translations are consistent with EN locale

fields.results_per_page and the three webhook message keys are correctly namespaced and align with the English originals; no issues from an i18n/usage perspective.

Also applies to: 676-678

admin-ui/plugins/admin/components/Webhook/hooks/index.ts (1)

1-6: Barrel exports for webhook hooks look good

Centralizing useWebhookAudit and the audited mutation hooks here simplifies imports and keeps the public surface clear.

admin-ui/app/locales/en/translation.json (1)

442-442: New webhook and pagination messages are well‑integrated

fields.results_per_page and the three webhook messages read clearly and match how WebhookSearch and WebhookListPage consume them; no changes needed.

Also applies to: 740-742

admin-ui/plugins/admin/components/Webhook/hooks/useWebhookAudit.ts (1)

8-56: Audit hook correctly centralizes webhook audit context

Using initAudit to encapsulate token/client/IP/userinfo and logAction to attach WebhookEntry / { inum } payloads keeps webhook auditing consistent and reusable. Only consideration: if postUserAction failures should never block the calling operation, you may want to wrap the await postUserAction(audit) in a try/catch or make it fire‑and‑forget so audit failures don’t influence business logic.

admin-ui/plugins/admin/components/Webhook/index.ts (1)

1-9: Webhook barrel module cleanly aggregates the public surface

Exporting pages, form/search components, URL helpers, and types/hooks from a single entry point will simplify consumers and keep the Webhook module cohesive.

admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (1)

1-131: Webhook type definitions are cohesive and align with usage

Centralizing Webhook‑related types (form values, slice state, audit payloads, table actions, shortcode config) and re‑exporting JansConfigApi types gives a clear, type‑safe contract for all Webhook UI code. The shapes for WebhookActionPayload and PagedWebhookResult in particular line up with how auditing and listing are implemented elsewhere.

admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (1)

150-167: Server‑side pagination & sorting look correct; confirm API params and delete‑refetch behavior

The list page wires server‑side pagination and sorting cleanly via useGetAllWebhooks (limit, pattern, startIndex, sortBy, sortOrder) and a custom TablePaginationComponent, and uses useDeleteWebhookWithAudit for audited deletions. Two things worth double‑checking:

  • The sortBy (displayName|url|httpMethod|jansEnabled) and sortOrder ('ascending' | 'descending') values passed from this page and WebhookSearch should match exactly what the JansConfigApi GetAllWebhooks endpoint expects.
  • useDeleteWebhookWithAudit should invalidate or refetch the GetAllWebhooks query so that the list updates automatically after a deletion without relying solely on the manual Refresh button.

Functionally the rest of the table rendering (columns, permission‑gated actions, empty/loading states) looks solid.

Also applies to: 222-241, 348-398

admin-ui/plugins/admin/components/Webhook/ShortcodePopover.tsx (2)

17-42: Consider memoizing the Label component or moving it outside the module.

The Label component is recreated on each render of the parent module. While it doesn't cause immediate issues since it's defined at module level (not inside ShortcodePopover), if it were ever moved inside the main component, it would cause unnecessary re-renders of list items.

The current placement is acceptable, but adding memo would make it consistent with the parent component.


91-116: LGTM!

The list rendering with proper key usage, conditional dividers, and type-safe props is well-implemented. The TypeScript conversion from PropTypes is clean and the component correctly handles empty state.

admin-ui/plugins/admin/redux/features/WebhookSlice.ts (1)

72-173: Slice implementation is well-structured.

The Redux slice follows standard patterns with proper initial state, typed payloads, and clear reducer logic. The separation of request/response actions enables saga integration cleanly.

admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (2)

112-119: LGTM!

The feature selection state management correctly handles the async loading of webhook features. The baseline tracking for change detection is a good pattern for enabling/disabling form controls.


248-506: Form implementation is comprehensive and well-structured.

The form correctly handles:

  • Lazy loading of the JSON editor with Suspense
  • Cursor position tracking for shortcode insertion
  • Change detection for enabling/disabling controls
  • Conditional body editor based on HTTP method
  • Proper cleanup on unmount

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (1)
admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (1)

113-131: Re‑validate payload in submitForm to avoid uncaught JSON.parse exceptions.

onSubmit correctly uses validatePayload (with a guarded JSON.parse) before opening the commit dialog, but submitForm later does:

if (formikValues.httpMethod !== 'GET' && formikValues.httpMethod !== 'DELETE') {
  payload.httpRequestBody = JSON.parse(formikValues.httpRequestBody)
}

If the user edits httpRequestBody after the initial validation but before confirming the commit dialog, this JSON.parse can throw and break the component.

You can re‑use validatePayload inside submitForm with current values and Formik’s setFieldError to ensure the body is still valid before parsing, eliminating the unguarded exception risk:

-  const { values: formikValues, resetForm, setFieldValue, dirty: formikDirty } = formik
+  const {
+    values: formikValues,
+    resetForm,
+    setFieldValue,
+    setFieldError,
+    dirty: formikDirty,
+  } = formik
@@
-  const submitForm = useCallback(
-    async (userMessage: string) => {
-      closeCommitDialog()
-
-      const payload: WebhookEntry = {
+  const submitForm = useCallback(
+    async (userMessage: string) => {
+      const hasError = validatePayload(formikValues, setFieldError)
+      closeCommitDialog()
+
+      if (hasError) {
+        return
+      }
+
+      const payload: WebhookEntry = {
         displayName: formikValues.displayName,
         url: formikValues.url,
         httpMethod: formikValues.httpMethod,
         description: formikValues.description,
         jansEnabled: formikValues.jansEnabled,
@@
-      if (formikValues.httpMethod !== 'GET' && formikValues.httpMethod !== 'DELETE') {
-        payload.httpRequestBody = JSON.parse(formikValues.httpRequestBody)
-      }
+      if (formikValues.httpMethod !== 'GET' && formikValues.httpMethod !== 'DELETE') {
+        payload.httpRequestBody = JSON.parse(formikValues.httpRequestBody)
+      }
@@
-    [
-      closeCommitDialog,
-      formikValues,
-      resetForm,
-      selectedFeatures,
-      id,
-      selectedWebhook,
-      createWebhook,
-      updateWebhook,
-    ],
+    [
+      closeCommitDialog,
+      formikValues,
+      resetForm,
+      selectedFeatures,
+      id,
+      selectedWebhook,
+      createWebhook,
+      updateWebhook,
+      validatePayload,
+      setFieldError,
+    ],
   )

This keeps the single source of truth for validation (validatePayload), ensures the body is still valid at the moment of submission, and prevents an unhandled JSON.parse exception.

Also applies to: 133-178, 153-155

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a281d12 and d2906a7.

📒 Files selected for processing (12)
  • admin-ui/app/components/SVG/menu/ShortCodesIcon.tsx (1 hunks)
  • admin-ui/app/locales/en/translation.json (3 hunks)
  • admin-ui/app/locales/es/translation.json (3 hunks)
  • admin-ui/app/locales/fr/translation.json (3 hunks)
  • admin-ui/app/locales/pt/translation.json (2 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookSearch.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (1 hunks)
  • admin-ui/plugins/admin/redux/features/WebhookSlice.ts (1 hunks)
  • admin-ui/plugins/admin/redux/sagas/types/state.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-10T14:18:58.310Z
Learnt from: kdhttps
Repo: GluuFederation/flex PR: 2378
File: admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx:107-109
Timestamp: 2025-11-10T14:18:58.310Z
Learning: In the Cedarling configuration page (admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx), console.error calls should be kept in catch blocks when there are multiple operations in the try block, as they help print the whole error object with details for debugging unexpected errors.

Applied to files:

  • admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts
  • admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx
📚 Learning: 2025-11-07T12:55:26.241Z
Learnt from: kdhttps
Repo: GluuFederation/flex PR: 2378
File: admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx:93-104
Timestamp: 2025-11-07T12:55:26.241Z
Learning: In the Cedarling configuration feature (admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx), the sync role to scopes mappings operation depends on the `auiPolicyStoreUrl`. The backend fetches content from this URL and syncs roles based on the response. Therefore, the audit log for the sync operation should include the `auiPolicyStoreUrl` in its payload to provide proper audit context.

Applied to files:

  • admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts
🧬 Code graph analysis (5)
admin-ui/plugins/admin/redux/sagas/types/state.ts (1)
admin-ui/plugins/admin/redux/features/WebhookSlice.ts (1)
  • WebhookSliceState (6-27)
admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (4)
admin-ui/plugins/schema/utils/errorHandler.ts (1)
  • extractErrorMessage (25-30)
admin-ui/plugins/admin/components/Webhook/hooks/index.ts (2)
  • useCreateWebhookWithAudit (3-3)
  • useWebhookAudit (1-1)
admin-ui/plugins/admin/components/Webhook/hooks/useWebhookAudit.ts (1)
  • useWebhookAudit (21-56)
admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (1)
  • WebhookEntry (5-5)
admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (8)
admin-ui/plugins/admin/redux/sagas/types/state.ts (1)
  • RootState (5-27)
admin-ui/plugins/admin/helper/webhook.ts (1)
  • buildWebhookInitialValues (29-41)
admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (2)
  • useCreateWebhookWithAudit (25-60)
  • useUpdateWebhookWithAudit (62-97)
admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (4)
  • WebhookFormValues (7-15)
  • CursorPosition (59-62)
  • AuiFeature (5-5)
  • WebhookEntry (5-5)
admin-ui/plugins/admin/helper/validations/webhookValidation.ts (1)
  • getWebhookValidationSchema (4-38)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)
  • isValid (26-31)
admin-ui/plugins/admin/components/Webhook/index.ts (1)
  • isValid (7-7)
admin-ui/app/components/Card/Card.tsx (1)
  • Card (27-27)
admin-ui/plugins/admin/redux/features/WebhookSlice.ts (1)
admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (3)
  • WebhookEntry (5-5)
  • TriggerPayload (64-68)
  • WebhookActionPayload (70-78)
admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (6)
admin-ui/plugins/schema/components/types/AttributeListPage.types.ts (1)
  • ThemeState (20-22)
admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (2)
  • WebhookEntry (5-5)
  • TableAction (86-93)
admin-ui/plugins/user-management/types/CommonTypes.ts (1)
  • ThemeContext (13-17)
admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (1)
  • useDeleteWebhookWithAudit (99-134)
admin-ui/plugins/admin/redux/sagas/WebhookSaga.ts (1)
  • deleteWebhook (120-150)
admin-ui/app/customColors.ts (1)
  • customColors (4-25)
🔇 Additional comments (16)
admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (3)

25-60: LGTM - Previous review concerns have been addressed.

The implementation correctly addresses the previous review comments:

  • Callback stability is handled via useRef pattern (lines 30-31)
  • Audit logging failures are now fire-and-forget with .catch() (line 40), preventing them from masking successful mutations
  • Error message extraction uses the shared helper function

The hook properly orchestrates mutation, audit logging, toast notifications, query invalidation, and callbacks.


62-97: LGTM - Consistent implementation.

The update hook follows the same pattern as the create hook, maintaining consistency across all webhook mutation operations. All the fixes from previous reviews are applied here as well.


99-134: LGTM - Consistent implementation.

The delete hook follows the same reliable pattern as create and update, appropriately accepting an inum string parameter instead of a full WebhookEntry object. All review fixes are consistently applied.

admin-ui/app/locales/fr/translation.json (3)

365-365: Localization key placement consistent with related fields.

The results_per_page key is appropriately positioned near sort_by in the fields section, and the French translation is grammatically correct and consistent with UI pagination patterns.


676-678: Webhook UI localizations properly placed and translated.

The three new webhook message keys are correctly positioned within the messages section near existing webhook entries, and the French translations are grammatically accurate and contextually appropriate for the webhook form UI.


724-724: URL validation message appropriately placed with related error messages.

The invalid_url_error key is logically positioned adjacent to other URL/validation errors, and the French translation accurately conveys the validation intent with proper grammar and punctuation.

admin-ui/app/locales/pt/translation.json (3)

332-332: Consistent pagination localization across locales.

The Portuguese results_per_page translation mirrors the French placement and structure, maintaining consistency in UI localization across language variants. The Brazilian Portuguese translation is grammatically correct.


697-699: Webhook UI localizations consistent with other locales and grammatically correct.

The three Portuguese webhook messages are properly positioned and accurately translated, with correct Brazilian Portuguese grammar, verb conjugations, and punctuation. Placement and structure mirror the French localization file, maintaining consistency across language variants.


705-705: URL validation message consistent across locales with correct Portuguese grammar.

The invalid_url_error message in Portuguese is correctly positioned adjacent to related validation errors and uses appropriate vocabulary and grammar. Placement and structure mirror the French localization, maintaining cross-locale consistency.

admin-ui/app/locales/en/translation.json (1)

442-442: Webhook & pagination i18n additions are consistent and correctly keyed

The new results_per_page and webhook-related message keys are well named, grammatically sound, and align with their usages in the new webhook components. No changes needed.

Also applies to: 740-743, 756-756

admin-ui/plugins/admin/redux/sagas/types/state.ts (1)

3-3: RootState now correctly reuses WebhookSliceState

Switching webhookReducer to the imported WebhookSliceState removes duplicated state shape and keeps saga typing in sync with the slice definition. This is the right direction.

Also applies to: 26-26

admin-ui/app/locales/es/translation.json (1)

442-442: Spanish webhook & pagination translations are accurate

The new Spanish entries mirror the English intent and fit existing tone (“Agregar…”, “Cree su primer webhook…”). Keys match the usages in the webhook UI. No issues.

Also applies to: 740-743, 756-756

admin-ui/app/components/SVG/menu/ShortCodesIcon.tsx (1)

3-5: ShortCodesIcon now correctly forwards styling props

className and style are optional and properly applied to the SVG, with a sensible default for style and a fixed width. This resolves the earlier “unused props” concern cleanly.

Also applies to: 8-8, 16-17

admin-ui/plugins/admin/components/Webhook/WebhookSearch.tsx (1)

17-147: WebhookSearch behavior and typing look solid

State sync with pattern, keyboard handling on Enter, sorting/limit controls, and i18n integration are all correctly wired with appropriate memoization. I don’t see any issues here.

admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (1)

69-83: Row actions, icons, and table wiring are correctly implemented

  • EditIcon/DeleteIcon now forward props to MUI icons, so iconProps (id, color, style) from rowActions are honored.
  • rowActions correctly gates edit/delete by canWriteWebhooks/canDeleteWebhooks and uses inum-based IDs for testing and targeting.
  • MaterialTable is fed with server-side data, custom pagination, and theming in a consistent way.

No further issues spotted in this part of the list page.

Also applies to: 245-278, 360-387

admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (1)

1-109: Centralized webhook types look coherent and match UI usage.

The re-exports from JansConfigApi and the locally defined form/UI types (WebhookFormValues, HttpHeader, TriggerPayload, WebhookActionPayload, etc.) are consistent with how they’re consumed in the form and slice code. Having this as a single source of truth for webhook UI types is a good direction.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (1)

159-161: Still safer to guard JSON.parse in submitForm (or avoid double-parsing)

validatePayload now does a JSON.parse with try/catch, which is a solid improvement, but Line 160 in submitForm still performs an unguarded JSON.parse(formikValues.httpRequestBody). If validation is ever bypassed or the body changes between validation and accepting the commit dialog, this can still throw synchronously inside the submit handler.

To make this robust:

  • Either wrap this JSON.parse in a try/catch and surface a field error / toast and return early on failure, or
  • Refactor validatePayload to return the parsed body (e.g. { hasError, parsedBody }) and reuse that instead of parsing again here.

This keeps the submit path resilient even if future refactors change how validation is wired.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d2906a7 and a2ca1eb.

📒 Files selected for processing (5)
  • admin-ui/app/context/theme/themeContext.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (1 hunks)
  • admin-ui/plugins/admin/redux/features/WebhookSlice.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-10T14:18:58.310Z
Learnt from: kdhttps
Repo: GluuFederation/flex PR: 2378
File: admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx:107-109
Timestamp: 2025-11-10T14:18:58.310Z
Learning: In the Cedarling configuration page (admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx), console.error calls should be kept in catch blocks when there are multiple operations in the try block, as they help print the whole error object with details for debugging unexpected errors.

Applied to files:

  • admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts
  • admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx
🧬 Code graph analysis (3)
admin-ui/plugins/admin/redux/features/WebhookSlice.ts (1)
admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (4)
  • WebhookEntry (5-5)
  • AuiFeature (5-5)
  • TriggerPayload (64-68)
  • WebhookActionPayload (70-78)
admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (4)
admin-ui/plugins/schema/utils/errorHandler.ts (1)
  • extractErrorMessage (25-30)
admin-ui/plugins/admin/components/Webhook/hooks/useWebhookAudit.ts (4)
  • useWebhookAudit (21-56)
  • CREATE (58-58)
  • UPDATE (58-58)
  • DELETION (58-58)
admin-ui/plugins/admin/redux/sagas/WebhookSaga.ts (3)
  • createWebhook (89-118)
  • updateWebhook (152-182)
  • deleteWebhook (120-150)
admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (1)
  • WebhookEntry (5-5)
admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (6)
admin-ui/plugins/admin/helper/webhook.ts (1)
  • buildWebhookInitialValues (29-41)
admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (2)
  • useCreateWebhookWithAudit (31-66)
  • useUpdateWebhookWithAudit (68-103)
admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (3)
  • WebhookFormValues (7-15)
  • CursorPosition (59-62)
  • WebhookEntry (5-5)
admin-ui/plugins/admin/helper/validations/webhookValidation.ts (1)
  • getWebhookValidationSchema (4-38)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)
  • isValid (26-31)
admin-ui/plugins/admin/redux/sagas/WebhookSaga.ts (2)
  • updateWebhook (152-182)
  • createWebhook (89-118)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (7)
admin-ui/app/context/theme/themeContext.tsx (1)

14-17: Exporting ThemeContextType looks good and is type-safe

Making ThemeContextType exported on Line 14 cleanly exposes the context shape for consumers (e.g., custom hooks or components using useContext(ThemeContext)) without changing runtime behavior. The internal ThemeState / ThemeAction aliases can safely remain non-exported since consumers only need the ThemeContextType surface.

admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (4)

19-29: LGTM! Well-documented error extraction.

The documentation clearly explains why this implementation differs from the general error utility, and the extraction logic correctly handles the webhook API's response structure with appropriate fallbacks.


31-66: LGTM! Solid implementation with proper error handling.

The hook correctly implements the mutation flow with:

  • Stable callback references using useRef
  • Fire-and-forget audit logging to avoid masking successful mutations
  • Appropriate error handling with user feedback
  • Query invalidation and callback execution

All concerns from previous reviews have been addressed.


68-103: LGTM! Consistent implementation.

The update hook follows the same robust pattern as the create hook, with appropriate changes for the UPDATE action type. The structural similarity across hooks improves maintainability and reduces cognitive load.


105-140: LGTM! Consistent deletion implementation.

The delete hook correctly adapts the pattern for deletion operations, appropriately handling the different parameter structure (inum vs data) and logging only the necessary information ({ inum }) in the audit trail.

admin-ui/plugins/admin/redux/features/WebhookSlice.ts (1)

1-61: Good consolidation on webhook slice typing

The slice now pulls WebhookEntry/AuiFeature from JansConfigApi and TriggerPayload/WebhookActionPayload from the shared webhook types module, which removes the earlier duplicated/ divergent interfaces. The initial state and reducers line up with those shapes cleanly; no issues spotted here.

admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (1)

321-337: Confirm GluuInputRow still updates Formik state when handleChange is provided

In Lines 321–327, the handleChange passed to GluuInputRow only updates cursorPosition and does not call formik.handleChange. This is fine only if GluuInputRow internally wires Formik’s change handler and treats handleChange as an additional side-effect.

If handleChange is an override rather than a hook, form values for url will no longer update. Please confirm the component’s contract; if it overrides, adjust the callback to:

handleChange={(event: React.ChangeEvent<HTMLInputElement>) => {
  formik.handleChange(event)
  const currentPosition = event.target.selectionStart || 0
  setCursorPosition((prev) => ({ ...prev, url: currentPosition }))
}}

so both Formik and cursor tracking work correctly.

Comment on lines +279 to +287
render: (rowData: WebhookEntry) => (
<Typography
variant="body2"
fontWeight={500}
color={rowData.jansEnabled ? 'black !important' : 'gray !important'}
>
{rowData.displayName}
</Typography>
),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's locate and read the WebhookListPage.tsx file
find . -name "WebhookListPage.tsx" -type f

Repository: GluuFederation/flex

Length of output: 126


🏁 Script executed:

# Get an overview of the file size
wc -l admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx

Repository: GluuFederation/flex

Length of output: 128


🏁 Script executed:

# Read the specific lines mentioned (279-287) with context
sed -n '270,300p' admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx

Repository: GluuFederation/flex

Length of output: 953


🏁 Script executed:

# Find MUI type definitions or check package.json for MUI version
find . -name "package.json" -type f | head -5

Repository: GluuFederation/flex

Length of output: 86


🏁 Script executed:

# Check the imports and MUI version being used
grep -r "@mui/material" admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx

Repository: GluuFederation/flex

Length of output: 85


🏁 Script executed:

# Look for other usages of Typography in the codebase to see patterns
rg "Typography" admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx -A 3 -B 1

Repository: GluuFederation/flex

Length of output: 1054


🏁 Script executed:

# Check MUI version in package.json
cat admin-ui/package.json | grep -A 2 -B 2 "@mui/material"

Repository: GluuFederation/flex

Length of output: 241


🏁 Script executed:

# Check if there's TypeScript compilation configured
find admin-ui -name "tsconfig.json" -type f

Repository: GluuFederation/flex

Length of output: 85


🏁 Script executed:

# Search for other color prop usages with non-semantic values
rg "color\s*=\s*\{" admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx -A 1

Repository: GluuFederation/flex

Length of output: 387


🏁 Script executed:

# Check tsconfig.json to see strictness settings
cat admin-ui/tsconfig.json

Repository: GluuFederation/flex

Length of output: 1379


🏁 Script executed:

# Verify MUI Typography color prop type definition expectations
web_search
MUI Material-UI Typography color prop TypeScript type v5

Repository: GluuFederation/flex

Length of output: 155


Use sx prop for custom colors instead of Typography's typed color prop

On line 283, the Typography component's color prop is set to 'black !important' / 'gray !important', which violates MUI's TypeScript type constraints (the prop expects semantic values like 'primary' or 'textSecondary'). With strict TypeScript enabled in this project, this produces type errors. The URL column already uses sx for styling; apply the same approach here:

-        render: (rowData: WebhookEntry) => (
-          <Typography
-            variant="body2"
-            fontWeight={500}
-            color={rowData.jansEnabled ? 'black !important' : 'gray !important'}
-          >
+        render: (rowData: WebhookEntry) => (
+          <Typography
+            variant="body2"
+            fontWeight={500}
+            sx={{ color: rowData.jansEnabled ? 'black' : 'gray' }}
+          >

This aligns with MUI's API, satisfies TypeScript's strict type checking, and removes unnecessary !important.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
render: (rowData: WebhookEntry) => (
<Typography
variant="body2"
fontWeight={500}
color={rowData.jansEnabled ? 'black !important' : 'gray !important'}
>
{rowData.displayName}
</Typography>
),
render: (rowData: WebhookEntry) => (
<Typography
variant="body2"
fontWeight={500}
sx={{ color: rowData.jansEnabled ? 'black' : 'gray' }}
>
{rowData.displayName}
</Typography>
),
🤖 Prompt for AI Agents
In admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx around lines
279–287, the Typography uses the typed color prop with raw values ('black
!important' / 'gray !important') which breaks strict TypeScript; remove the
color prop and instead apply the styling via the sx prop (matching the URL
column pattern) — e.g. set sx={{ color: rowData.jansEnabled ? 'text.primary' :
'text.secondary', fontWeight: 500 }} or use literal colors if needed (without
!important) so the type-safe MUI API is respected.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (1)

279-306: Use theme-aware colors in sx and drop !important in Typography styles

The name and URL columns now use sx (good), but they still hard-code 'black !important' / 'gray !important':

sx={{ color: rowData.jansEnabled ? 'black !important' : 'gray !important' }}
...
sx={{
  color: rowData.jansEnabled ? 'black !important' : 'gray !important',
  ...
}}

This bypasses theme palettes and keeps !important in play unnecessarily, making it harder to maintain dark/light themes.

Consider moving to palette-based colors without !important, e.g.:

-            sx={{ color: rowData.jansEnabled ? 'black !important' : 'gray !important' }}
+            sx={{ color: rowData.jansEnabled ? 'text.primary' : 'text.secondary' }}
@@
-            sx={{
-              color: rowData.jansEnabled ? 'black !important' : 'gray !important',
+            sx={{
+              color: rowData.jansEnabled ? 'text.primary' : 'text.secondary',
               wordBreak: 'break-all',
               maxWidth: '350px',
               fontFamily: 'monospace',
               fontSize: '0.8rem',
             }}

This keeps the styling consistent with the active MUI theme and avoids hard-coded CSS overrides.

Please double-check against your MUI v5 typings/docs that 'text.primary' / 'text.secondary' are the palette keys you want for enabled vs disabled states, and that no other parts of the design system rely on the previous hard-coded colors.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a2ca1eb and 5bbbbc4.

📒 Files selected for processing (3)
  • admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/hooks/index.ts (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-10T14:18:58.310Z
Learnt from: kdhttps
Repo: GluuFederation/flex PR: 2378
File: admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx:107-109
Timestamp: 2025-11-10T14:18:58.310Z
Learning: In the Cedarling configuration page (admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx), console.error calls should be kept in catch blocks when there are multiple operations in the try block, as they help print the whole error object with details for debugging unexpected errors.

Applied to files:

  • admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts
🧬 Code graph analysis (1)
admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (4)
admin-ui/plugins/schema/utils/errorHandler.ts (1)
  • extractErrorMessage (25-30)
admin-ui/plugins/admin/components/Webhook/hooks/useWebhookAudit.ts (3)
  • useWebhookAudit (21-56)
  • CREATE (58-58)
  • UPDATE (58-58)
admin-ui/plugins/admin/redux/sagas/WebhookSaga.ts (2)
  • createWebhook (89-118)
  • updateWebhook (152-182)
admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (1)
  • WebhookEntry (5-5)
🔇 Additional comments (6)
admin-ui/plugins/admin/components/Webhook/hooks/index.ts (1)

1-7: LGTM! Clean barrel export pattern.

The centralized exports provide a clean public API for webhook hooks and improve maintainability.

admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (4)

1-17: LGTM! Imports and interface are well-structured.

The imports are appropriate, and the MutationCallbacks interface is now properly exported, addressing the previous feedback.


19-29: LGTM! Error extraction with clear documentation.

The extractErrorMessage helper properly addresses previous concerns about duplication by documenting the intentional difference between webhook API responses (responseMessage) and other APIs (message). The implementation correctly handles the webhook-specific error structure.


31-66: LGTM! Well-implemented create hook with proper error handling.

The hook correctly implements:

  • useRef pattern to prevent callback dependency issues (previously addressed)
  • Fire-and-forget audit logging that won't mask successful mutations (previously addressed)
  • Proper error extraction and user feedback via toasts
  • Query cache invalidation on success
  • Error propagation for caller handling

The console.error in the audit catch block is appropriate for debugging as per coding guidelines.


68-140: LGTM! Update and delete hooks follow consistent patterns.

Both useUpdateWebhookWithAudit and useDeleteWebhookWithAudit correctly mirror the create hook's implementation:

  • Proper useRef pattern for stable callbacks
  • Fire-and-forget audit logging
  • Appropriate mutation hooks and parameters
  • Consistent error handling and user feedback
  • Proper action constants (UPDATE, DELETION)

The consistency across all three hooks enhances maintainability.

admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (1)

74-77: Row action icons now correctly forward iconProps

EditIcon / DeleteIcon now accept props and spread them into the underlying MUI icons, so iconProps (including id, style, color, etc.) from rowActions will be honored. This fixes the previous issue where action icon styling and ids were ignored.

You may want to quickly verify in the UI that id="editWebhook{inum}" / id="deleteWebhook{inum}" are present on the rendered <svg> elements and that the custom style.color overrides the default red on delete.

Also applies to: 239-272

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (2)

161-170: Pagination clamp logic correctly fixes the empty-last-page issue

The totalItems-aware clamp:

if (totalItems > 0 && pageNumber * limit >= totalItems) {
  const lastPage = Math.max(0, Math.ceil(totalItems / limit) - 1)
  setPageNumber(lastPage)
}

prevents the “stranded on an empty page after deleting the last row” problem and converges safely without loops. Combined with the updated empty-state condition (totalItems === 0), this addresses the earlier pagination bug.


282-305: Avoid !important in sx colors for better theming and override control

You’re now using sx (good), but the values still include !important:

sx={{ color: rowData.jansEnabled ? 'black !important' : 'gray !important' }}
...
sx={{ color: rowData.jansEnabled ? 'black !important' : 'gray !important', ... }}

!important here is unnecessary and makes future overrides harder. Plain colors (or theme tokens) are enough:

-            sx={{ color: rowData.jansEnabled ? 'black !important' : 'gray !important' }}
+            sx={{ color: rowData.jansEnabled ? 'black' : 'gray' }}
@@
-            sx={{
-              color: rowData.jansEnabled ? 'black !important' : 'gray !important',
+            sx={{
+              color: rowData.jansEnabled ? 'black' : 'gray',
               wordBreak: 'break-all',
               maxWidth: '350px',
               fontFamily: 'monospace',
               fontSize: '0.8rem',
             }}

If you want to stay fully theme-aware, you could also use theme.palette.text.primary/secondary via a function form of sx.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5bbbbc4 and ddfe715.

📒 Files selected for processing (1)
  • admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (1 hunks)
🔇 Additional comments (1)
admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (1)

182-189: Confirm that delete mutation invalidates/refetches the list query

submitForm awaits deleteWebhook(deleteData.inum, userMessage) but doesn’t call refetch or otherwise update the list. If useDeleteWebhookWithAudit doesn’t invalidate the useGetAllWebhooks cache under the hood, the table could show stale data until the user manually hits Refresh.

If invalidation isn’t wired, consider:

-      if (deleteData?.inum) {
-        await deleteWebhook(deleteData.inum, userMessage)
-      }
+      if (deleteData?.inum) {
+        await deleteWebhook(deleteData.inum, userMessage)
+        await refetch()
+      }

(or doing this inside the mutation hook’s onSuccess).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (1)
admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (1)

166-172: Pagination clamping and empty-state condition now handle last-page deletions correctly

The useEffect that clamps pageNumber when pageNumber * limit >= totalItems, combined with the !pattern && totalItems === 0 empty-state check, resolves the “delete last item on last page shows misleading empty state” issue while there are still earlier pages.

Also applies to: 359-361

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ddfe715 and 56a4d48.

📒 Files selected for processing (3)
  • admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookSearch.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-10T14:18:58.310Z
Learnt from: kdhttps
Repo: GluuFederation/flex PR: 2378
File: admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx:107-109
Timestamp: 2025-11-10T14:18:58.310Z
Learning: In the Cedarling configuration page (admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx), console.error calls should be kept in catch blocks when there are multiple operations in the try block, as they help print the whole error object with details for debugging unexpected errors.

Applied to files:

  • admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx
🔇 Additional comments (4)
admin-ui/plugins/admin/components/Webhook/WebhookSearch.tsx (1)

48-62: Pattern/input synchronization is correct and avoids stale UI state

Using inputValue plus the useEffect that syncs it from pattern ensures the textbox reflects external resets (e.g., URL/query changes) while only committing on Enter via onPatternChange. This is a solid, predictable pattern for a search box.

admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (1)

76-82: Icon components now correctly forward iconProps to MUI icons

Wrapping Edit/DeleteOutlined as components that accept and spread props (including style and id) fixes the earlier issue where MaterialTable’s iconProps were ignored. The style={{ color: 'red', ...props.style }} merge on DeleteIcon also lets callers override the default color if needed.

admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (2)

119-137: Inline payload validation is consistent and localized

validatePayload combining JSON validation with isValid URL checks and localized error messages (invalid_json_error, invalid_url_error) is a good complement to the schema. Keeping this in a dedicated callback keeps onSubmit lean and makes the extra checks easy to maintain.


193-208: Feature selection change tracking is correctly separated from Formik dirtiness

Using selectedFeatures/baselineSelectedFeatures with isEqual and then combining that with formikDirty for isFormChanged cleanly captures both field edits and feature selection changes. This ensures Cancel/Apply enablement matches real user changes, not just Formik field state.

Comment on lines +65 to +74
const getHttpMethodColor = (
method: string,
): 'info' | 'success' | 'error' | 'warning' | 'default' => {
const colorMap: Record<string, 'info' | 'success' | 'error' | 'warning'> = {
GET: 'info',
POST: 'success',
DELETE: 'error',
}
return colorMap[method] || 'warning'
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Map colors for all HTTP methods you support

getHttpMethodColor only defines colors for GET, POST, and DELETE, defaulting everything else to 'warning'. Since the form exposes PUT and PATCH as valid methods, those will currently render with a warning color. If that’s not intentional, add explicit entries, e.g.:

const colorMap: Record<string, 'info' | 'success' | 'error' | 'warning'> = {
  GET: 'info',
  POST: 'success',
  PUT: 'success',
  PATCH: 'success',
  DELETE: 'error',
}

so visual semantics match your HTTP methods.

🤖 Prompt for AI Agents
In admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx around lines 65
to 74, the getHttpMethodColor function currently maps only GET, POST and DELETE
and falls back to 'warning' for other methods; add explicit mappings for PUT and
PATCH (and any other supported HTTP verbs) to the desired color (e.g., 'success'
for PUT and PATCH) by extending the colorMap so all methods exposed by the form
have an explicit color and avoid unintentionally showing 'warning'.

Comment on lines +284 to +317
const columns = useMemo(
() => [
{
title: t('fields.name'),
field: 'displayName',
render: (rowData: WebhookEntry) => (
<Typography
variant="body2"
fontWeight={500}
sx={{ color: rowData.jansEnabled ? 'black !important' : 'gray !important' }}
>
{rowData.displayName}
</Typography>
),
},
{
title: t('fields.url'),
field: 'url',
width: '35%',
render: (rowData: WebhookEntry) => (
<Typography
variant="body2"
sx={{
color: rowData.jansEnabled ? 'black !important' : 'gray !important',
wordBreak: 'break-all',
maxWidth: '350px',
fontFamily: 'monospace',
fontSize: '0.8rem',
}}
>
{rowData.url}
</Typography>
),
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Avoid literal 'black !important' / 'gray !important' in sx; prefer theme-aware colors

Using sx={{ color: rowData.jansEnabled ? 'black !important' : 'gray !important' }} (and the same pattern for the URL column) hard-codes colors and relies on !important, which is brittle against theme changes and unnecessary with MUI.

Consider switching to theme-aware tokens without !important, e.g.:

sx={{
  color: rowData.jansEnabled ? 'text.primary' : 'text.secondary',
}}

and similarly for the URL column. This keeps the table aligned with the active theme and avoids specificity hacks.

🤖 Prompt for AI Agents
In admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx around lines
284 to 317, the cells set literal colors with '!important' (e.g. 'black
!important' / 'gray !important'), which hardcodes colors and breaks theme
compatibility; replace those literal strings with theme-aware color tokens (e.g.
use text.primary for enabled and text.secondary for disabled) and remove the
'!important' usage so MUI's styling and theme can control color; update both the
displayName and url column sx objects to use the theme color tokens and drop
'!important'.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 56a4d48 and 251411f.

📒 Files selected for processing (3)
  • admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (1 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookSearch.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-10T14:18:58.310Z
Learnt from: kdhttps
Repo: GluuFederation/flex PR: 2378
File: admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx:107-109
Timestamp: 2025-11-10T14:18:58.310Z
Learning: In the Cedarling configuration page (admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx), console.error calls should be kept in catch blocks when there are multiple operations in the try block, as they help print the whole error object with details for debugging unexpected errors.

Applied to files:

  • admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx
🧬 Code graph analysis (1)
admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (6)
admin-ui/plugins/admin/redux/sagas/types/state.ts (1)
  • RootState (5-27)
admin-ui/plugins/admin/helper/webhook.ts (1)
  • buildWebhookInitialValues (29-41)
admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (2)
  • useCreateWebhookWithAudit (31-66)
  • useUpdateWebhookWithAudit (68-103)
admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (3)
  • WebhookFormValues (7-15)
  • WebhookEntry (5-5)
  • ShortCodesConfig (105-109)
admin-ui/plugins/admin/helper/validations/webhookValidation.ts (1)
  • getWebhookValidationSchema (4-38)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)
  • isValid (26-31)
🔇 Additional comments (3)
admin-ui/plugins/admin/components/Webhook/WebhookListPage.tsx (1)

1-457: Strong implementation with past review feedback incorporated

The webhook list page demonstrates solid React and TypeScript practices:

  • Permission-gated UI: Cedar permissions properly control read/write/delete actions
  • Pagination clamping: The useEffect on lines 169-174 correctly handles the edge case when deleting the last item on a page
  • Empty state logic: Now properly checks totalItems === 0 instead of webhooks.length === 0 (line 361)
  • Icon prop forwarding: EditIcon and DeleteIcon (lines 78-81) correctly forward props to underlying MUI components
  • Translation best practices: Uses i18next defaultValue option instead of || fallback pattern (lines 46, 49-50)
  • Memoization: Appropriate use of useMemo and useCallback prevents unnecessary re-renders

The code is production-ready and addresses the PR objective of migrating to the TypeScript generated client.

admin-ui/plugins/admin/components/Webhook/WebhookSearch.tsx (1)

1-149: Clean, type-safe search component

This component demonstrates excellent TypeScript practices:

  • Type safety: WebhookSortBy union type (line 17) constrains sortBy to valid fields, preventing runtime errors from unsupported field names
  • Controlled input pattern: Lines 50-55 properly sync internal input state with external pattern prop
  • Proper event handling: Enter-to-search pattern (lines 57-64) provides good UX
  • Memoization: All callbacks properly memoized to prevent unnecessary child re-renders
  • i18n best practices: Consistently uses defaultValue option for translations (lines 88, 121-122)

The component is well-structured and addresses the past review feedback on type constraints.

admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (1)

259-519: Overall Webhook form structure and TS integration look solid.

Data loading, Formik setup (with reinitialization, schema + extra payload validation), commit dialog flow, and shortcode handling are all cohesive and type-safe. The move to WebhookEntry and the generated hooks from JansConfigApi is cleanly integrated with the existing Gluu UI components and change-tracking logic.

Copy link
Contributor

@duttarnab duttarnab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Can I check webhook implementation on all features when testing this PR.
    I have checked for FIDO, it is not calling configured webhook on editing FIDO configuration.

@syntrydy syntrydy changed the title fix(admin-ui): Use typescript generated client for Webhooks pages #2433 fix(admin-ui): Use typescript generated client for Webhooks pages Dec 2, 2025
@syntrydy
Copy link
Contributor Author

syntrydy commented Dec 2, 2025

Conclusion for the 14 Missing Components

Component Had webhook before? Status
FIDO DynamicConfiguration ❌ NEVER HAD IT Never implemented
JansLockConfiguration ❌ NEVER HAD IT Never implemented
SqlForm, LdapForm, CachePage ❌ NEVER HAD IT Never implemented
AuthNForm, DefaultAcr, MessageForm ❌ NEVER HAD IT Never implemented
Assets (JansAssetListPage, AssetForm) ❌ NEVER HAD IT Never implemented
TrustRelationForm (SAML) ❌ NEVER HAD IT Never implemented
PasswordChangeModal ❌ NEVER HAD IT Never implemented
WebhookListPage, WebhookForm ❌ NEVER HAD IT Never implemented

Key Finding

These 14 components NEVER had webhook integration - it's not a regression from migration. The original webhook implementation (commit cf9eae4) only covered a subset of features:

  • FIDO StaticConfiguration (but NOT DynamicConfiguration)
  • Schema Attributes
  • SCIM
  • SMTP
  • Jans-Link

The other features were simply never updated to include webhook support.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 251411f and 6a3167c.

📒 Files selected for processing (1)
  • admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: devrimyatar
Repo: GluuFederation/flex PR: 2440
File: flex-linux-setup/flex_linux_setup/flex_setup.py:519-519
Timestamp: 2025-11-11T15:17:34.651Z
Learning: In flex-linux-setup/flex_linux_setup/flex_setup.py, the webhook LDIF (aui_webhook.ldif) should only be imported during fresh Admin UI installations, not during updates. The import is correctly guarded by the check `client_check_result['2001.'] == -1` which ensures it only runs when the Admin UI Web Client doesn't already exist. Docker update workflows differ from Linux update workflows in this regard.
📚 Learning: 2025-11-10T14:18:58.310Z
Learnt from: kdhttps
Repo: GluuFederation/flex PR: 2378
File: admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx:107-109
Timestamp: 2025-11-10T14:18:58.310Z
Learning: In the Cedarling configuration page (admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx), console.error calls should be kept in catch blocks when there are multiple operations in the try block, as they help print the whole error object with details for debugging unexpected errors.

Applied to files:

  • admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (5)
admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (5)

1-56: LGTM: Imports and component setup are well-structured.

The imports are properly organized, types are correctly imported from their respective modules, and the lazy loading of GluuInputEditor is a good performance optimization. The Redux selector properly uses the imported RootState type.


57-102: LGTM: Data fetching and form initialization are properly implemented.

The feature fetching is correctly guarded with enabled: Boolean(id) to prevent unnecessary requests during webhook creation. The use of useMemo for derived state and the Formik configuration with enableReinitialize ensure the form properly handles both create and edit scenarios.


121-139: LGTM: Validation logic is robust and user-friendly.

The validation properly handles edge cases:

  • JSON parsing is wrapped in try/catch to prevent uncaught exceptions
  • URL validation only runs when a URL is provided, preserving "required" errors
  • All error messages use translation keys for internationalization

176-191: LGTM: Mutation error handling is properly implemented.

The submission logic correctly wraps the async mutation calls in try/catch, and the console.error is appropriately kept for diagnostics when multiple operations are involved. The hooks already surface user-facing errors via toast notifications.

Based on learnings, console.error calls should be kept in catch blocks when there are multiple operations for debugging unexpected errors.


266-527: LGTM: Form rendering is comprehensive and well-structured.

The UI implementation is solid:

  • Proper use of Suspense for lazy-loaded components
  • Conditional rendering based on HTTP method for body editor
  • All user-facing strings use translation keys (including the Enabled/Disabled chip labels)
  • Proper error display and validation feedback
  • Good UX with cursor position tracking for shortcode insertion
  • Change detection correctly accounts for both form and feature selection changes

Comment on lines +317 to +323
value={selectedFeatures as unknown as Record<string, unknown>[]}
options={features as unknown as Record<string, unknown>[]}
onChange={(options) => {
const typedOptions = options as unknown as AuiFeature[]
setSelectedFeatures(
typedOptions && typedOptions.length > 0 ? [typedOptions[0]] : [],
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Type assertions suggest GluuTypeAhead component needs better typing.

The multiple type casts (as unknown as Record<string, unknown>[] and as unknown as AuiFeature[]) indicate that GluuTypeAhead isn't properly generic or typed for this use case. While this works if the shapes are compatible, it bypasses type safety.

Consider either:

  1. Making GluuTypeAhead a generic component that accepts typed options
  2. Creating a typed wrapper around GluuTypeAhead for webhook features

This is technical debt rather than a functional issue.

🤖 Prompt for AI Agents
In admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx around lines 317 to
323, the code uses repeated unsafe casts (as unknown as Record<string,
unknown>[] and as unknown as AuiFeature[]) when passing options/value to
GluuTypeAhead; fix by making GluuTypeAhead a generic component (e.g.,
GluuTypeAhead<T>) so it accepts typed props for options/value/onChange, or
alternatively create a small typed wrapper component around GluuTypeAhead
specialized for AuiFeature that enforces correct types and maps props without
any unknown casts; update the call sites here to use the generic/wrapper with
AuiFeature so setSelectedFeatures and onChange operate with real AuiFeature
types instead of asserting through unknown.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (1)

314-334: Type casts around GluuTypeAhead indicate missing generics/typing on that component.

The repeated as unknown as Record<string, unknown>[] / as unknown as AuiFeature[] casts effectively bypass type safety and rely on runtime shape compatibility. Longer term, this would be cleaner if GluuTypeAhead were generic or wrapped in a typed adapter for AuiFeature so options, value, and onChange are strongly typed without unknown hops.

This is the same technical-debt concern previously raised about GluuTypeAhead’s typing; OK to defer but worth addressing when you next touch that component.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6a3167c and 71d30bc.

📒 Files selected for processing (1)
  • admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: devrimyatar
Repo: GluuFederation/flex PR: 2440
File: flex-linux-setup/flex_linux_setup/flex_setup.py:519-519
Timestamp: 2025-11-11T15:17:34.651Z
Learning: In flex-linux-setup/flex_linux_setup/flex_setup.py, the webhook LDIF (aui_webhook.ldif) should only be imported during fresh Admin UI installations, not during updates. The import is correctly guarded by the check `client_check_result['2001.'] == -1` which ensures it only runs when the Admin UI Web Client doesn't already exist. Docker update workflows differ from Linux update workflows in this regard.
📚 Learning: 2025-11-10T14:18:58.310Z
Learnt from: kdhttps
Repo: GluuFederation/flex PR: 2378
File: admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx:107-109
Timestamp: 2025-11-10T14:18:58.310Z
Learning: In the Cedarling configuration page (admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx), console.error calls should be kept in catch blocks when there are multiple operations in the try block, as they help print the whole error object with details for debugging unexpected errors.

Applied to files:

  • admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx
🧬 Code graph analysis (1)
admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (6)
admin-ui/plugins/admin/redux/sagas/types/state.ts (1)
  • RootState (5-27)
admin-ui/plugins/admin/helper/webhook.ts (1)
  • buildWebhookInitialValues (29-41)
admin-ui/plugins/admin/components/Webhook/hooks/useWebhookMutations.ts (2)
  • useCreateWebhookWithAudit (31-66)
  • useUpdateWebhookWithAudit (68-103)
admin-ui/plugins/admin/components/Webhook/types/WebhookTypes.ts (3)
  • WebhookFormValues (7-15)
  • CursorPosition (59-62)
  • WebhookEntry (5-5)
admin-ui/plugins/admin/helper/validations/webhookValidation.ts (1)
  • getWebhookValidationSchema (4-38)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)
  • isValid (26-31)
🔇 Additional comments (2)
admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx (2)

149-193: Submit flow is robust and aligned with audit + error-handling patterns.

The submitForm implementation looks solid: it defensively parses httpRequestBody with try/catch and surfaces a field error, preserves inum/dn/baseDn on updates, wraps createWebhook/updateWebhook in a try/catch to avoid unhandled rejections, and logs failures with console.error while letting the audit hooks + toasts handle user-facing errors. This matches the recommended pattern of keeping console.error in catch blocks for multi-step operations.

Based on learnings, ...


60-66: The enabled option placement is correct for the generated hook—no changes needed.

The code useGetFeaturesByWebhookId(id ?? 'skip', { query: { enabled: Boolean(id) } }) follows the correct pattern for orval-generated React Query hooks. When enabled: false, React Query prevents query execution entirely, so the 'skip' placeholder is never sent to the backend. The enabled flag is correctly placed inside the query object, consistent with other generated hooks like useGetAllWebhooks in the same codebase.

Likely an incorrect or invalid review comment.

Comment on lines +398 to +421
<FormGroup row>
<GluuLabel
doc_category={WEBHOOK}
doc_entry="http_headers"
label="fields.http_headers"
size={4}
/>
<Col sm={8}>
<GluuProperties
compName="httpHeaders"
isInputLables={true}
formik={formik}
multiProperties
inputSm={10}
destinationPlaceholder={'placeholders.enter_key_value'}
sourcePlaceholder={'placeholders.enter_header_key'}
options={formikValues.httpHeaders || []}
isKeys={false}
buttonText="actions.add_header"
showError={!!(formik.errors.httpHeaders && formik.touched.httpHeaders)}
errorMessage={formik.errors.httpHeaders as string}
/>
</Col>
</FormGroup>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Narrow the httpHeaders error type instead of casting to string.

errorMessage={formik.errors.httpHeaders as string} forces a string cast even though Formik’s errors.httpHeaders type can be more complex (arrays/nested errors). Given your Yup schema puts a single message on the array, this is safe at runtime but loses type information.

Consider tightening the typing instead of casting, e.g., by refining the Formik type for errors.httpHeaders or using a small helper that normalizes the error to a string (or undefined). This keeps the component type-safe without relying on as string.

🤖 Prompt for AI Agents
In admin-ui/plugins/admin/components/Webhook/WebhookForm.tsx around lines 398 to
421, the code currently force-casts formik.errors.httpHeaders to string when
passing errorMessage which loses type-safety; instead narrow/normalize the error
to a string or undefined before passing it (for example update the Formik
generic types to reflect that httpHeaders errors are string | undefined, or
create a small helper that checks the runtime shape of formik.errors.httpHeaders
and returns a single message or undefined), then pass that normalized value to
GluuProperties.errorMessage so no unsafe as string cast is used.

Copy link
Contributor

@duttarnab duttarnab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Webhook URL with short-codes are not allowed.
image
  1. For Scopes-Read/Write and Delete webhook trigger url is not called on creating, editing or deleting any scope.

https://www.loom.com/share/15c4318433a34f7c9b792d9e90bd6598

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)

17-24: See previous comment regarding SSRF vulnerability.

The security issues with this function's approach are covered in the comment on lines 1-13.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 71d30bc and 49a4229.

📒 Files selected for processing (4)
  • admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1 hunks)
  • admin-ui/plugins/auth-server/components/Scopes/ScopeAddPage.tsx (2 hunks)
  • admin-ui/plugins/auth-server/components/Scopes/ScopeEditPage.tsx (2 hunks)
  • admin-ui/plugins/auth-server/components/Scopes/ScopeListPage.tsx (2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: devrimyatar
Repo: GluuFederation/flex PR: 2440
File: flex-linux-setup/flex_linux_setup/flex_setup.py:519-519
Timestamp: 2025-11-11T15:17:34.651Z
Learning: In flex-linux-setup/flex_linux_setup/flex_setup.py, the webhook LDIF (aui_webhook.ldif) should only be imported during fresh Admin UI installations, not during updates. The import is correctly guarded by the check `client_check_result['2001.'] == -1` which ensures it only runs when the Admin UI Web Client doesn't already exist. Docker update workflows differ from Linux update workflows in this regard.
📚 Learning: 2025-11-07T12:55:26.241Z
Learnt from: kdhttps
Repo: GluuFederation/flex PR: 2378
File: admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx:93-104
Timestamp: 2025-11-07T12:55:26.241Z
Learning: In the Cedarling configuration feature (admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx), the sync role to scopes mappings operation depends on the `auiPolicyStoreUrl`. The backend fetches content from this URL and syncs roles based on the response. Therefore, the audit log for the sync operation should include the `auiPolicyStoreUrl` in its payload to provide proper audit context.

Applied to files:

  • admin-ui/plugins/auth-server/components/Scopes/ScopeListPage.tsx
  • admin-ui/plugins/auth-server/components/Scopes/ScopeAddPage.tsx
  • admin-ui/plugins/auth-server/components/Scopes/ScopeEditPage.tsx
🧬 Code graph analysis (2)
admin-ui/plugins/auth-server/components/Scopes/ScopeListPage.tsx (1)
admin-ui/plugins/admin/redux/sagas/WebhookSaga.ts (1)
  • triggerWebhook (279-368)
admin-ui/plugins/auth-server/components/Scopes/ScopeEditPage.tsx (1)
admin-ui/plugins/admin/redux/sagas/WebhookSaga.ts (1)
  • triggerWebhook (279-368)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (4)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)

26-31: Good defensive programming with null/undefined handling.

The type signature correctly accepts string | undefined | null, and the early return prevents unnecessary processing for invalid inputs.

admin-ui/plugins/auth-server/components/Scopes/ScopeAddPage.tsx (1)

11-11: Wire scope creation into webhook pipeline using API response

Using triggerWebhook({ createdFeatureValue: response }) after a successful usePostOauthScopes mutation is consistent with the saga’s expectation and ensures webhooks receive the persisted scope object (including generated fields). The placement after the toast but inside the success path looks correct, and the updated dependency list on handleSubmit is appropriate.

Also applies to: 75-82

admin-ui/plugins/auth-server/components/Scopes/ScopeListPage.tsx (1)

40-40: Trigger webhooks only after successful scope deletion

Importing triggerWebhook and dispatching triggerWebhook({ createdFeatureValue: item }) after deleteScope.mutateAsync resolves cleanly ties deletions into the webhook flow while ensuring no webhook is fired on failure. Using the selected item as the payload gives webhooks full context about the deleted scope, and the updated dependency array for onDeletionConfirmed is correct.

Also applies to: 334-348

admin-ui/plugins/auth-server/components/Scopes/ScopeEditPage.tsx (1)

12-12: Send updated scope to webhooks on successful edit

The new triggerWebhook({ createdFeatureValue: response }) dispatch in the update success path correctly passes the server-returned scope object into the webhook saga, aligning the edit flow with create/delete webhook behavior. Dependency updates on handleSubmit are also consistent.

Also applies to: 136-143

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)

1-21: Harden private/local host detection (169.254/16, 0.0.0.0/8, IPv6 hostname mismatch).

isPrivateOrLocalhost still misses some high‑risk internal ranges and has an IPv6 hostname mismatch:

  • https://169.254.169.254/... (cloud metadata) is currently allowed: hostname 169.254.169.254 does not match any of the existing prefixes.
  • 0.0.0.0/8 and similar special ranges are not blocked.
  • For https://[::1]/..., new URL(url).hostname is "::1", so the "[::1]" check never matches; IPv6 loopback is only incidentally rejected by PATTERN today and would become allowed if the regex is relaxed later.

Given this is a security boundary for webhook targets, these should be treated as private/internal and rejected here, not just indirectly via PATTERN.

A minimal hardening that stays consistent with your current string‑prefix approach:

 const isPrivateOrLocalhost = (hostname: string): boolean => {
-  if (hostname === 'localhost' || hostname === '[::1]') {
+  if (hostname === 'localhost' || hostname === '::1') {
     return true
   }
   if (
     hostname.startsWith('127.') ||
     hostname.startsWith('10.') ||
-    hostname.startsWith('192.168.')
+    hostname.startsWith('192.168.') ||
+    // Link-local and special ranges often used in SSRF attacks
+    hostname.startsWith('169.254.') ||
+    hostname.startsWith('0.')
   ) {
     return true
   }
   const match = hostname.match(/^172\.(\d+)\./)
   if (match) {
     const secondOctet = parseInt(match[1], 10)
     if (secondOctet >= 16 && secondOctet <= 31) {
       return true
     }
   }
   return false
 }

You may also want to consider future‑proofing for IPv6 private/ULA/link‑local ranges if you ever relax PATTERN to accept IPv6 literals or broader host syntax.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 49a4229 and 1f1cf63.

📒 Files selected for processing (1)
  • admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: devrimyatar
Repo: GluuFederation/flex PR: 2440
File: flex-linux-setup/flex_linux_setup/flex_setup.py:519-519
Timestamp: 2025-11-11T15:17:34.651Z
Learning: In flex-linux-setup/flex_linux_setup/flex_setup.py, the webhook LDIF (aui_webhook.ldif) should only be imported during fresh Admin UI installations, not during updates. The import is correctly guarded by the check `client_check_result['2001.'] == -1` which ensures it only runs when the Admin UI Web Client doesn't already exist. Docker update workflows differ from Linux update workflows in this regard.
🧬 Code graph analysis (1)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)
admin-ui/plugins/admin/components/Webhook/index.ts (2)
  • isAllowed (7-7)
  • isValid (7-7)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f1cf63 and c898490.

📒 Files selected for processing (1)
  • admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: devrimyatar
Repo: GluuFederation/flex PR: 2440
File: flex-linux-setup/flex_linux_setup/flex_setup.py:519-519
Timestamp: 2025-11-11T15:17:34.651Z
Learning: In flex-linux-setup/flex_linux_setup/flex_setup.py, the webhook LDIF (aui_webhook.ldif) should only be imported during fresh Admin UI installations, not during updates. The import is correctly guarded by the check `client_check_result['2001.'] == -1` which ensures it only runs when the Admin UI Web Client doesn't already exist. Docker update workflows differ from Linux update workflows in this regard.
🧬 Code graph analysis (1)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)
admin-ui/plugins/admin/components/Webhook/index.ts (2)
  • isAllowed (7-7)
  • isValid (7-7)
🔇 Additional comments (2)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (2)

24-24: Confirm whether blocking query strings and fragments is intentional.

The current PATTERN enforces HTTPS but disallows query parameters (?token=abc) and fragments (#section). Many webhook services require query strings for authentication tokens or tracking parameters.

If this restriction is intentional for security reasons, please document it. Otherwise, consider extending the pattern:

-const PATTERN = /^https:\/\/([\w-]+\.)+[\w-]+(:\d+)?(\/([\w\-.]|\$\{[\w]+\})*)*$/i
+const PATTERN = /^https:\/\/([\w-]+\.)+[\w-]+(:\d+)?(\/([\w\-.]|\$\{[\w]+\})*)*([\?#].*)?$/i

Alternatively, if the restriction is intentional, add a comment:

// Webhook URLs must not contain query strings or fragments for security reasons
const PATTERN = /^https:\/\/([\w-]+\.)+[\w-]+(:\d+)?(\/([\w\-.]|\$\{[\w]+\})*)*$/i

44-49: LGTM: Validation flow is correct.

The function correctly chains null/undefined checks, the isAllowed security validation, and the PATTERN format validation. The logic is sound.

Note that the effectiveness of this function depends on the fixes to isAllowed and isPrivateOrLocalhost mentioned in other comments.

@syntrydy syntrydy requested a review from duttarnab December 2, 2025 20:27
duttarnab
duttarnab previously approved these changes Dec 4, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c898490 and 82b2e92.

📒 Files selected for processing (6)
  • admin-ui/app/locales/en/translation.json (3 hunks)
  • admin-ui/app/locales/es/translation.json (3 hunks)
  • admin-ui/app/locales/fr/translation.json (3 hunks)
  • admin-ui/app/locales/pt/translation.json (2 hunks)
  • admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1 hunks)
  • admin-ui/plugins/auth-server/components/Scopes/ScopeListPage.tsx (2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: devrimyatar
Repo: GluuFederation/flex PR: 2440
File: flex-linux-setup/flex_linux_setup/flex_setup.py:519-519
Timestamp: 2025-11-11T15:17:34.651Z
Learning: In flex-linux-setup/flex_linux_setup/flex_setup.py, the webhook LDIF (aui_webhook.ldif) should only be imported during fresh Admin UI installations, not during updates. The import is correctly guarded by the check `client_check_result['2001.'] == -1` which ensures it only runs when the Admin UI Web Client doesn't already exist. Docker update workflows differ from Linux update workflows in this regard.
📚 Learning: 2025-11-07T12:55:26.241Z
Learnt from: kdhttps
Repo: GluuFederation/flex PR: 2378
File: admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx:93-104
Timestamp: 2025-11-07T12:55:26.241Z
Learning: In the Cedarling configuration feature (admin-ui/plugins/admin/components/Cedarling/CedarlingConfigPage.tsx), the sync role to scopes mappings operation depends on the `auiPolicyStoreUrl`. The backend fetches content from this URL and syncs roles based on the response. Therefore, the audit log for the sync operation should include the `auiPolicyStoreUrl` in its payload to provide proper audit context.

Applied to files:

  • admin-ui/plugins/auth-server/components/Scopes/ScopeListPage.tsx
🧬 Code graph analysis (2)
admin-ui/plugins/auth-server/components/Scopes/ScopeListPage.tsx (1)
admin-ui/plugins/admin/redux/sagas/WebhookSaga.ts (1)
  • triggerWebhook (279-368)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)
admin-ui/plugins/admin/components/Webhook/index.ts (2)
  • isAllowed (7-7)
  • isValid (7-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: sonar scan (admin-ui)
🔇 Additional comments (11)
admin-ui/app/locales/es/translation.json (1)

448-448: ✓ Webhook and pagination translation keys added correctly.

The Spanish translations for webhook functionality and pagination are semantically appropriate and properly placed in their respective sections. The keys (results_per_page, webhook_form_description, no_webhooks_found, create_first_webhook, invalid_url_error) align with the PR objectives and follow the existing structure.

Also applies to: 746-748, 762-762

admin-ui/app/locales/fr/translation.json (1)

367-367: ✓ Webhook and pagination translation keys added correctly.

The French translations mirror the Spanish additions with semantically appropriate phrasing and proper placement. Key consistency across language files (results_per_page, webhook_form_description, no_webhooks_found, create_first_webhook, invalid_url_error) is maintained, supporting the webhook UI expansion per PR objectives.

Also applies to: 682-684, 730-730

admin-ui/app/locales/pt/translation.json (2)

334-334: Translation key placement and content are correct.

The "results_per_page" key is appropriately added to the "fields" section and the Portuguese translation is grammatically correct.

Also applies to: 334-334


703-711: Webhook message translations are contextually appropriate and consistent with English locale.

All four new webhook-related translation keys are placed in the correct "messages" section and their Portuguese translations are:

  • Grammatically correct
  • Semantically accurate
  • Consistent with the English versions in structure and meaning
admin-ui/app/locales/en/translation.json (3)

448-448: Translation key placement and content are correct.

The "results_per_page" key is appropriately added to the "fields" section with clear English text.

Also applies to: 448-448


746-762: Webhook and URL validation message translations are appropriate and well-placed.

All four new webhook-related translation keys are correctly placed in the "messages" section with:

  • Clear, user-facing English text
  • Consistent terminology and tone
  • Appropriate context for webhook configuration and error handling

334-334: Locale translations are consistent across Portuguese and English files.

The translation keys for webhook functionality and pagination ("results_per_page", "webhook_form_description", "no_webhooks_found", "create_first_webhook", "invalid_url_error") are properly aligned across both locale files:

  • Placed in matching sections ("fields" and "messages")
  • Translations are semantically equivalent
  • JSON syntax is valid in both files

These translations enable the webhook UI feature to be properly localized across languages, aligning with the PR objective to integrate the TypeScript-generated webhook client into the admin UI.

Also applies to: 448-448

admin-ui/plugins/auth-server/components/Scopes/ScopeListPage.tsx (2)

39-39: triggerWebhook import wiring looks consistent with webhook flow

Importing triggerWebhook from Plugins/admin/redux/features/WebhookSlice and using it in this component aligns with the centralized webhook handling introduced elsewhere; no issues here.


336-350: Scope delete now correctly participates in webhook + audit flow

Awaiting deleteScope.mutateAsync before dispatch(triggerWebhook({ createdFeatureValue: item })) and logScopeDeletion(item, message) ensures webhooks/audit only run after a successful delete. Adding dispatch to the dependency array keeps onDeletionConfirmed compliant with hook rules. This matches the existing pattern on create/update and closes the gap for delete.

admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (2)

1-12: LGTM! Comprehensive scheme blocklist.

The blocked schemes list now includes all common SSRF vectors, including the additional protocols (gopher, dict, tftp) requested in previous reviews.


44-60: LGTM! Private IP blocking now applies to all protocols.

The function correctly validates URLs by parsing with the URL constructor, blocking disallowed schemes, and rejecting private/localhost hostnames for all protocols (not just HTTPS). The previous critical issue where protocols like wss:// could bypass private IP checks has been fixed.

Comment on lines +62 to +69
export const isValid = (url: string | undefined | null): boolean => {
if (url === undefined || url === null || !isAllowed(url)) {
return false
}
return PATTERN.test(url)
}

export { isAllowed }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

LGTM! Validation logic is correct.

The isValid function properly chains null-safety, allow-list, and pattern checks. The control flow is sound and the type signature appropriately handles optional URLs.

Note: This validation runs client-side/at configuration time and cannot prevent DNS rebinding attacks (where a domain initially resolves to a public IP but later rebinds to a private IP). If webhook URLs are stored and invoked later by backend services, ensure the backend re-validates the resolved IP address before making the request.

🤖 Prompt for AI Agents
In admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts around lines
62-69 the client-side isValid check is fine but does not mitigate DNS rebinding
for server-side webhook delivery; implement server-side re-validation before
invoking stored webhook URLs by resolving the webhook hostname to IP(s),
checking each resolved IP is not in private/reserved ranges (RFC1918, loopback,
link-local, multicast, carrier-grade NAT, etc.), and rejecting requests if any
resolved IP is disallowed; ensure the backend performs this resolution
immediately before the outbound request, logs the resolved IPs and reason for
rejection, and fails the delivery with a clear error rather than relying solely
on client-side validation.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 82b2e92 and 5f76853.

📒 Files selected for processing (1)
  • admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: devrimyatar
Repo: GluuFederation/flex PR: 2440
File: flex-linux-setup/flex_linux_setup/flex_setup.py:519-519
Timestamp: 2025-11-11T15:17:34.651Z
Learning: In flex-linux-setup/flex_linux_setup/flex_setup.py, the webhook LDIF (aui_webhook.ldif) should only be imported during fresh Admin UI installations, not during updates. The import is correctly guarded by the check `client_check_result['2001.'] == -1` which ensures it only runs when the Admin UI Web Client doesn't already exist. Docker update workflows differ from Linux update workflows in this regard.
🧬 Code graph analysis (1)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)
admin-ui/plugins/admin/components/Webhook/index.ts (2)
  • isAllowed (7-7)
  • isValid (7-7)
🔇 Additional comments (1)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)

1-12: BLOCKED_SCHEMES set is conservative and consistent with HTTPS-only policy

The blocked schemes list is sane and, combined with the HTTPS-only PATTERN, gives a clear and consistent “HTTPS or nothing” story for webhooks. No issues here.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5f76853 and 2db02a7.

📒 Files selected for processing (1)
  • admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: devrimyatar
Repo: GluuFederation/flex PR: 2440
File: flex-linux-setup/flex_linux_setup/flex_setup.py:519-519
Timestamp: 2025-11-11T15:17:34.651Z
Learning: In flex-linux-setup/flex_linux_setup/flex_setup.py, the webhook LDIF (aui_webhook.ldif) should only be imported during fresh Admin UI installations, not during updates. The import is correctly guarded by the check `client_check_result['2001.'] == -1` which ensures it only runs when the Admin UI Web Client doesn't already exist. Docker update workflows differ from Linux update workflows in this regard.
🔇 Additional comments (1)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1)

1-12: Overall URL validation flow looks solid.

Aside from the ranges noted above, the combination of:

  • scheme blocking via BLOCKED_SCHEMES (Line [1]–[11]),
  • URL parsing and hostname-based private/reserved checks in isAllowed (Lines [60]–[76]),
  • and strict HTTPS + path/query/fragment structure in PATTERN + isValid (Lines [58]–[83])

is coherent and significantly reduces SSRF risk at the UI layer. Exporting isAllowed separately also gives you flexibility for lighter-weight checks when regex structure isn’t required.

Also applies to: 60-83

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2db02a7 and 88ed430.

📒 Files selected for processing (1)
  • admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: devrimyatar
Repo: GluuFederation/flex PR: 2440
File: flex-linux-setup/flex_linux_setup/flex_setup.py:519-519
Timestamp: 2025-11-11T15:17:34.651Z
Learning: In flex-linux-setup/flex_linux_setup/flex_setup.py, the webhook LDIF (aui_webhook.ldif) should only be imported during fresh Admin UI installations, not during updates. The import is correctly guarded by the check `client_check_result['2001.'] == -1` which ensures it only runs when the Admin UI Web Client doesn't already exist. Docker update workflows differ from Linux update workflows in this regard.
🔇 Additional comments (6)
admin-ui/plugins/admin/components/Webhook/WebhookURLChecker.ts (6)

1-12: LGTM! Comprehensive scheme blocklist.

The BLOCKED_SCHEMES array covers all major SSRF protocol vectors, including the rare-but-exploitable schemes (gopher, dict, tftp) that were added in response to past reviews. This provides strong defense-in-depth against protocol smuggling attacks.


24-45: LGTM! Complete IPv4 private range coverage.

The IPv4 checks correctly cover all RFC1918 private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), link-local (169.254.0.0/16), loopback (127.0.0.0/8), and carrier-grade NAT (100.64.0.0/10). The second-octet range validation for 172.16.0.0/12 and 100.64.0.0/10 correctly prevents false positives on public IP ranges.


47-65: LGTM! Comprehensive IPv6 reserved range blocking.

The IPv6 checks are correctly scoped to IPv6 literals (via the includes(':') guard) to prevent false positives on DNS hostnames. The function blocks:

  • IPv4-mapped addresses (::ffff:0:0/96)
  • Unique local addresses (fc00::/7 covering both fc and fd prefixes)
  • Full link-local range (fe80::/10 correctly covering fe8-feb prefixes, not just fe80:)
  • Documentation range (2001:db8::/32)
  • Multicast (ff00::/8)

This provides robust protection against IPv6-based SSRF vectors.


70-71: LGTM! Pattern comprehensively validates HTTPS webhook URLs.

The regex correctly enforces HTTPS-only, supports both DNS hostnames (with required domain structure) and IPv6 literals in bracket notation ([...]), and allows optional port, path, query parameters, and fragments. The inclusion of query parameter support ((\?[^\s#]*)?) aligns with the documented requirement for shortcode usage in query strings (e.g., ?action=${action}&user_id=${userId}).


73-89: LGTM! Strong SSRF protection via proper URL parsing.

The isAllowed function correctly:

  1. Uses the WHATWG URL constructor to parse and normalize the URL, preventing user-info bypass attacks (e.g., https://attacker.com@127.0.0.1)
  2. Blocks all disallowed schemes, not just HTTP
  3. Crucially, applies the private/localhost check to all protocols (line 81), not just HTTPS—this prevents bypasses via wss://192.168.1.1 or other non-blocked schemes
  4. Returns false for malformed URLs via the catch block

This addresses the critical SSRF vulnerabilities flagged in earlier reviews.


91-98: LGTM! Validation flow is sound and well-structured.

The isValid function properly chains:

  1. Null/undefined guard (early return for missing input)
  2. Security validation via isAllowed (SSRF protection)
  3. Format validation via PATTERN (structural correctness)

The exports provide both granular (isAllowed) and comprehensive (isValid) validation APIs. Note that this client-side validation cannot prevent DNS rebinding attacks; ensure webhook URLs are re-validated server-side immediately before invocation, as noted in past reviews.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Dec 4, 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp-admin-ui Component affected by issue or PR comp-docker-admin-ui Component affected by issue or PR kind-bug Issue or PR is a bug in existing functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(admin-ui): Use typescript generated client for Webhooks pages

3 participants