Skip to content

Add session timeout for portals#1237

Merged
PasanT9 merged 7 commits intowso2:mainfrom
DinithHerath:main
Mar 17, 2026
Merged

Add session timeout for portals#1237
PasanT9 merged 7 commits intowso2:mainfrom
DinithHerath:main

Conversation

@DinithHerath
Copy link
Copy Markdown
Contributor

@DinithHerath DinithHerath commented Jan 13, 2026

This pull request introduces a session timeout feature for admin portal, which includes new components and updates to localization files. The most important changes include the addition of the SessionTimeout component, updates to localization files to support session timeout messages, and the introduction of a web worker for handling the session timer. To use the session timeout please add the following configuration under the [1], [2] or [3].

"sessionTimeout": {
  "enable": true,
  "idleWarningTimeout": 160,
  "idleTimeout": 180
}

[1] https://github.com/wso2/apim-apps/blob/main/portals/admin/src/main/webapp/site/public/conf/settings.json
[2] https://github.com/wso2/apim-apps/blob/main/portals/publisher/src/main/webapp/site/public/conf/settings.json
[3] https://github.com/wso2/apim-apps/blob/main/portals/devportal/src/main/webapp/site/public/theme/settings.json

Fixes wso2/api-manager#3785

Summary by CodeRabbit

  • New Features

    • Automatic session timeout with a warning dialog offering “Stay Logged In” or “Logout”; appears in protected/app layouts when authenticated.
  • Localization

    • Dialog text added in English and French across portals.
  • Configuration

    • New sessionTimeout settings (enable, idleWarningTimeout, idleTimeout) added to site/theme configuration.
  • Infrastructure

    • Background timer worker added to drive idle detection.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 13, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds client-side session timeout support: new SessionTimeout React components and timer web workers in admin/devportal/publisher, localized dialog strings, sessionTimeout configuration entries, and mounts of SessionTimeout in protected app layouts to trigger logout after inactivity.

Changes

Cohort / File(s) Summary
Localization
portals/admin/.../locales/en.json, portals/admin/.../locales/fr.json, portals/devportal/.../locales/en.json, portals/publisher/.../locales/en.json
Added four SessionTimeout translation keys: dialog.title, dialog.message, dialog.label.ok, dialog.label.cancel.
SessionTimeout components
portals/admin/.../components/SessionTimeout.jsx, portals/devportal/.../components/SessionTimeout.jsx, portals/publisher/.../components/SessionTimeout.jsx
New React functional components implementing idle tracking (Web Worker-driven), warning ConfirmDialog, reset and logout flows; exported default wrapped with injectIntl.
Web worker timer
portals/admin/.../webWorkers/timer.worker.js, portals/devportal/.../webWorkers/timer.worker.js, portals/publisher/.../webWorkers/timer.worker.js
Added simple worker that posts a tick every 1000ms; files include export default {}.
Integration into protected apps
portals/admin/.../ProtectedApp.jsx, portals/devportal/.../AppRouts.jsx, portals/publisher/.../ProtectedApp.jsx
Imported and mounted <SessionTimeout /> into authenticated/protected app trees before main route rendering.
Configuration
portals/admin/.../conf/settings.json, portals/devportal/.../site/public/theme/settings.json, portals/publisher/.../conf/settings.json
Added sessionTimeout settings (enable: true, idleWarningTimeout: 160, idleTimeout: 180). publisher also moves two arrays (serviceCatalogDefinitionTypes, serviceCatalogSecurityTypes) to top-level.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Main as Main Thread (App)
    participant Worker as Web Worker (timer.worker.js)
    participant Dialog as ConfirmDialog
    participant Server as Logout Endpoint

    Worker->>Main: postMessage() every 1s (tick)
    Main->>Main: increment idleCounter / update remaining time
    User->>Main: activity (click/mousemove/keydown)
    Main->>Main: reset idleCounter

    alt idleCounter >= idleWarningTimeout
        Main->>Dialog: open warning with remaining time
        Dialog->>User: show "Are you still there?"
        alt User clicks "Stay Logged In"
            User->>Dialog: click ok
            Dialog->>Main: reset idleCounter, close dialog
        else User clicks "Logout"
            User->>Dialog: click logout
            Dialog->>Main: redirect to logout
            Main->>Server: navigate to logout URL
        end
    else idleCounter >= idleTimeout
        Main->>Server: redirect to logout URL
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I count the ticks beneath the screen,

A worker hums, so quiet and keen.
"Are you still there?" I nudge with rhyme,
Click to stay — or end the time.
Hop, reset, and hop again.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and accurately summarizes the main change: introducing a session timeout feature across the portals.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Copy link
Copy Markdown

@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

🤖 Fix all issues with AI agents
In @portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx:
- Around line 67-69: The component assigns event handlers directly which
overwrites existing handlers; update SessionTimeout.jsx to use
document.addEventListener for the events currently assigned via
document.onclick, document.onmousemove, and document.onkeydown, registering the
resetIdleTimer function, and in the component cleanup (where handlers are
removed) use document.removeEventListener with the same resetIdleTimer reference
for "click", "mousemove", and "keydown" so listeners are added/removed safely
without clobbering other handlers.

In
@portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx:
- Around line 67-69: The component currently assigns
document.onclick/document.onmousemove/document.onkeydown directly which
overwrites other handlers; change these assignments to use
document.addEventListener('click', resetIdleTimer),
document.addEventListener('mousemove', resetIdleTimer), and
document.addEventListener('keydown', resetIdleTimer') where resetIdleTimer is
referenced, and ensure the effect cleanup removes the listeners with
document.removeEventListener for the same event types and the same
resetIdleTimer function so listeners are properly detached when SessionTimeout
unmounts.

In
@portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx:
- Around line 67-69: The code currently assigns event handlers directly
(document.onclick/document.onmousemove/document.onkeydown) which overwrites
existing handlers; replace those assignments by registering listeners with
document.addEventListener('click', resetIdleTimer),
document.addEventListener('mousemove', resetIdleTimer) and
document.addEventListener('keydown', resetIdleTimer) where handlers are set (use
the existing resetIdleTimer function reference), and update the cleanup to call
document.removeEventListener for the same event types and same resetIdleTimer
reference to avoid leaking or failing to remove listeners.
🧹 Nitpick comments (5)
portals/devportal/src/main/webapp/source/src/app/webWorkers/timer.worker.js (1)

27-31: Consider handling worker termination for cleaner resource management.

The setInterval runs indefinitely without storing a reference. While the main thread can terminate the worker, consider adding an onmessage handler to allow the main thread to signal a graceful stop, which could be useful for debugging or future enhancements.

♻️ Optional: Add message handler for graceful stop
+let timerId = null;
+
+// Handle messages from main thread
+// eslint-disable-next-line no-restricted-globals
+self.onmessage = (event) => {
+    if (event.data === 'stop' && timerId) {
+        clearInterval(timerId);
+        timerId = null;
+    }
+};
+
 // This is the timer function that will be executed in the background.
-setInterval(() => {
+timerId = setInterval(() => {
     // disable following rule because linter is unaware of the worker source
     // eslint-disable-next-line no-restricted-globals
     self.postMessage('');
 }, TIMER_INTERVAL);
portals/publisher/src/main/webapp/site/public/locales/en.json (1)

2476-2479: Standardize quoting + consider ICU pluralization for {time}; verify button wiring for cancel/ok.

  • The message uses typographic quotes (“Stay Logged In”) while other files often use straight quotes; consider standardizing to avoid inconsistent encoding/string comparisons.
  • If your i18n stack supports ICU MessageFormat, consider pluralization for second(s) to avoid “1 seconds”.
  • Since the keys are label.cancel/label.ok but the values are Logout/Stay Logged In, please double-check the dialog maps the right action to the right button.
portals/devportal/src/main/webapp/site/public/locales/en.json (1)

612-615: Align SessionTimeout copy format across portals (quotes + pluralization).

  • This message uses straight quotes while publisher uses typographic quotes; recommend picking one style and applying consistently across portals.
  • Consider ICU pluralization for {time} if supported to handle “1 second” correctly.
portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)

135-135: Unnecessary injectIntl wrapper.

The component uses only FormattedMessage which doesn't require the intl prop. Since the intl prop is never consumed, the injectIntl HOC adds unnecessary overhead.

Proposed fix
-export default injectIntl(SessionTimeout);
+export default SessionTimeout;
portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)

24-129: Consider extracting shared SessionTimeout component.

This component is nearly identical to the admin and devportal versions. The only differences are:

  • Config import path/alias
  • confirmPrimary prop (present here, absent in admin/devportal)

Extracting to a shared library with configuration injection would reduce maintenance burden and ensure consistent behavior across portals.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5fa47ad and a0d8652.

📒 Files selected for processing (13)
  • portals/admin/src/main/webapp/site/public/locales/en.json
  • portals/admin/src/main/webapp/site/public/locales/fr.json
  • portals/admin/src/main/webapp/source/src/app/ProtectedApp.jsx
  • portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/admin/src/main/webapp/source/src/app/webWorkers/timer.worker.js
  • portals/devportal/src/main/webapp/site/public/locales/en.json
  • portals/devportal/src/main/webapp/source/src/app/AppRouts.jsx
  • portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/devportal/src/main/webapp/source/src/app/webWorkers/timer.worker.js
  • portals/publisher/src/main/webapp/site/public/locales/en.json
  • portals/publisher/src/main/webapp/source/src/app/ProtectedApp.jsx
  • portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/publisher/src/main/webapp/source/src/app/webWorkers/timer.worker.js
🧰 Additional context used
🧬 Code graph analysis (7)
portals/publisher/src/main/webapp/source/src/app/webWorkers/timer.worker.js (2)
portals/admin/src/main/webapp/source/src/app/webWorkers/timer.worker.js (1)
  • TIMER_INTERVAL (24-24)
portals/devportal/src/main/webapp/source/src/app/webWorkers/timer.worker.js (1)
  • TIMER_INTERVAL (24-24)
portals/publisher/src/main/webapp/source/src/app/ProtectedApp.jsx (3)
portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)
  • SessionTimeout (24-134)
portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)
  • SessionTimeout (24-133)
portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)
  • SessionTimeout (24-127)
portals/devportal/src/main/webapp/source/src/app/AppRouts.jsx (3)
portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)
  • SessionTimeout (24-134)
portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)
  • SessionTimeout (24-133)
portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)
  • SessionTimeout (24-127)
portals/devportal/src/main/webapp/source/src/app/webWorkers/timer.worker.js (2)
portals/admin/src/main/webapp/source/src/app/webWorkers/timer.worker.js (1)
  • TIMER_INTERVAL (24-24)
portals/publisher/src/main/webapp/source/src/app/webWorkers/timer.worker.js (1)
  • TIMER_INTERVAL (24-24)
portals/admin/src/main/webapp/source/src/app/ProtectedApp.jsx (3)
portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)
  • SessionTimeout (24-134)
portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)
  • SessionTimeout (24-133)
portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)
  • SessionTimeout (24-127)
portals/admin/src/main/webapp/source/src/app/webWorkers/timer.worker.js (2)
portals/devportal/src/main/webapp/source/src/app/webWorkers/timer.worker.js (1)
  • TIMER_INTERVAL (24-24)
portals/publisher/src/main/webapp/source/src/app/webWorkers/timer.worker.js (1)
  • TIMER_INTERVAL (24-24)
portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx (3)
portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx (8)
  • SessionTimeout (24-134)
  • openDialog (25-25)
  • remainingTime (26-26)
  • openDialogRef (27-27)
  • idleTimeoutRef (30-30)
  • idleWarningTimeoutRef (31-31)
  • idleSecondsCounterRef (32-32)
  • handleConfirmDialog (87-94)
portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx (8)
  • SessionTimeout (24-133)
  • openDialog (25-25)
  • remainingTime (26-26)
  • openDialogRef (27-27)
  • idleTimeoutRef (30-30)
  • idleWarningTimeoutRef (31-31)
  • idleSecondsCounterRef (32-32)
  • handleConfirmDialog (87-94)
portals/publisher/src/main/webapp/source/src/app/components/Shared/ConfirmDialog.jsx (1)
  • ConfirmDialog (14-50)
🔇 Additional comments (14)
portals/admin/src/main/webapp/site/public/locales/en.json (1)

977-980: LGTM - Session timeout localization strings are well-structured.

The new keys follow the existing naming conventions, and the message placeholder {time} appropriately supports dynamic countdown display. The wording is clear and user-friendly.

portals/devportal/src/main/webapp/source/src/app/webWorkers/timer.worker.js (1)

33-33: Empty export for bundler compatibility is fine.

The export default {} appears to be for ES module bundler compatibility. This is consistent with the parallel implementations in admin and publisher portals.

portals/admin/src/main/webapp/site/public/locales/fr.json (1)

977-980: LGTM!

French translations for the SessionTimeout dialog are correctly added and follow the established key naming convention. The {time} placeholder in the message is properly preserved for dynamic value interpolation.

portals/publisher/src/main/webapp/source/src/app/ProtectedApp.jsx (2)

47-47: LGTM!

Import follows the established pattern and is correctly placed among other component imports.


216-216: LGTM!

The SessionTimeout component is appropriately placed inside the Base component, within the themed context and error boundary. The component self-manages its activation via Configurations.sessionTimeout.enable.

portals/admin/src/main/webapp/source/src/app/ProtectedApp.jsx (2)

32-32: LGTM!

Import follows the established pattern and is consistent with the publisher portal implementation.


204-204: LGTM!

The SessionTimeout component is placed within the AppErrorBoundary, ensuring proper error handling. The component self-manages its activation state via configuration, so rendering it before the settings check is acceptable.

portals/devportal/src/main/webapp/source/src/app/AppRouts.jsx (2)

29-29: LGTM!

Import follows the established pattern and is consistent with other portal implementations.


75-75: LGTM!

Good practice to conditionally render SessionTimeout only for authenticated users. This ensures the session timeout logic is only active when there's an actual session to manage.

portals/admin/src/main/webapp/source/src/app/webWorkers/timer.worker.js (1)

1-33: LGTM!

The web worker implementation is correct and follows the established pattern used in the devportal and publisher portals. The ESLint disable comment is appropriate for the worker context where self is the global scope. The empty default export is a standard webpack convention for worker modules, and termination is properly handled by the consuming SessionTimeout component.

portals/publisher/src/main/webapp/source/src/app/webWorkers/timer.worker.js (1)

19-33: LGTM - Simple and effective timer worker.

The implementation correctly offloads the timer to a web worker to avoid blocking the main thread. The interval and message posting are straightforward.

Minor observation: The export default {} (line 33) appears vestigial since the worker is instantiated via new Worker(...) and communicates via postMessage. It's harmless but could be removed for clarity if it's not needed for bundler compatibility.

portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)

34-47: Core timeout logic is sound.

The handleTimeOut function correctly:

  • Updates remaining time after warning threshold
  • Opens dialog exactly at warning timeout
  • Triggers logout exactly at idle timeout

The use of refs for mutable state accessed in closures is appropriate.

portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)

123-123: Verify confirmPrimary prop inconsistency.

The publisher version includes confirmPrimary while admin and devportal do not. This affects button styling (contained vs text variant based on the ConfirmDialog contract). Confirm whether this difference is intentional.

portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)

96-134: Implementation is correct.

The dialog rendering, callback handling, and overall session timeout logic are implemented correctly. The component properly:

  • Displays remaining countdown time
  • Offers "Stay Logged In" and "Logout" options
  • Resets idle timer or triggers logout based on user choice

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
38.7% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Copy link
Copy Markdown

@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: 0

🧹 Nitpick comments (4)
portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx (4)

42-46: Consider using >= for the idle timeout check.

If for any reason idleSecondsCount skips past the exact idleTimeoutRef.current value (e.g., due to timing variations), the logout won't trigger. Using >= ensures the logout always fires once the threshold is met or exceeded.

Proposed fix
-        if (idleSecondsCount === idleTimeoutRef.current) {
+        if (idleSecondsCount >= idleTimeoutRef.current) {

58-59: Add validation for configuration values.

If idleTimeout or idleWarningTimeout are undefined or non-numeric, the comparisons in handleTimeOut will behave unexpectedly. Consider adding default values or validation.

Proposed fix
-        idleTimeoutRef.current = Configurations.sessionTimeout.idleTimeout;
-        idleWarningTimeoutRef.current = Configurations.sessionTimeout.idleWarningTimeout;
+        idleTimeoutRef.current = Configurations.sessionTimeout.idleTimeout || 180;
+        idleWarningTimeoutRef.current = Configurations.sessionTimeout.idleWarningTimeout || 160;

67-69: Consider using passive event listeners for better scroll performance.

The mousemove listener fires frequently. Adding { passive: true } signals to the browser that the handler won't call preventDefault(), which can improve scrolling performance.

Proposed fix
-        document.addEventListener('click', resetIdleTimer);
-        document.addEventListener('mousemove', resetIdleTimer);
-        document.addEventListener('keydown', resetIdleTimer);
+        const listenerOptions = { passive: true };
+        document.addEventListener('click', resetIdleTimer, listenerOptions);
+        document.addEventListener('mousemove', resetIdleTimer, listenerOptions);
+        document.addEventListener('keydown', resetIdleTimer, listenerOptions);

And in cleanup:

-            document.removeEventListener('click', resetIdleTimer);
-            document.removeEventListener('mousemove', resetIdleTimer);
-            document.removeEventListener('keydown', resetIdleTimer);
+            document.removeEventListener('click', resetIdleTimer, listenerOptions);
+            document.removeEventListener('mousemove', resetIdleTimer, listenerOptions);
+            document.removeEventListener('keydown', resetIdleTimer, listenerOptions);

136-136: Remove unnecessary injectIntl wrapper.

The component uses FormattedMessage declaratively, which accesses the intl context directly. The injectIntl HOC is only needed when you need to access the intl object imperatively (e.g., intl.formatMessage()). Since the intl prop is never used, this wrapper adds unnecessary overhead.

Proposed fix

Remove the import:

-import { injectIntl, FormattedMessage } from 'react-intl';
+import { FormattedMessage } from 'react-intl';

Simplify the export:

-export default injectIntl(SessionTimeout);
+export default SessionTimeout;
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a0d8652 and aed8976.

📒 Files selected for processing (3)
  • portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx
🔇 Additional comments (1)
portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)

96-133: LGTM!

The dialog implementation with react-intl is well-structured. The countdown display and localized messages are correctly implemented.

Copy link
Copy Markdown

@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

🧹 Nitpick comments (1)
portals/admin/src/main/webapp/site/public/conf/settings.json (1)

25-28: Make the new config schema self-describing.

enable breaks the existing *.enabled convention in these settings files, and idleWarningTimeout / idleTimeout still leave the unit implicit. Since operators will hand-edit this in all three portals, please standardize the boolean name and make the timeout unit explicit in the contract before this spreads further.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@portals/admin/src/main/webapp/site/public/conf/settings.json` around lines 25
- 28, The sessionTimeout config uses non-standard keys: rename "enable" to
"enabled" to match the existing *.enabled convention and make units explicit by
renaming "idleWarningTimeout" and "idleTimeout" to e.g.
"idleWarningTimeoutSeconds" and "idleTimeoutSeconds" (or another explicit unit
suffix) and keep the numeric values the same; update any code that reads
sessionTimeout (references to sessionTimeout, idleWarningTimeout, idleTimeout)
to use the new keys and convert/validate units if necessary so the schema is
self-describing across portals.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@portals/publisher/src/main/webapp/site/public/conf/settings.json`:
- Around line 51-66: The change renames top-level keys to
serviceCatalogDefinitionTypes and serviceCatalogSecurityTypes which will break
configs still using
app.serviceCatalogDefinitionTypes/app.serviceCatalogSecurityTypes; update the
configuration loader to accept both the new top-level keys and the old app.*
paths (e.g., when loading settings look up serviceCatalogDefinitionTypes ||
app?.serviceCatalogDefinitionTypes and serviceCatalogSecurityTypes ||
app?.serviceCatalogSecurityTypes) so existing custom settings are honored, and
add a short upgrade note in the settings documentation mentioning the
deprecation of app.serviceCatalog* keys and the timeline for removal.

---

Nitpick comments:
In `@portals/admin/src/main/webapp/site/public/conf/settings.json`:
- Around line 25-28: The sessionTimeout config uses non-standard keys: rename
"enable" to "enabled" to match the existing *.enabled convention and make units
explicit by renaming "idleWarningTimeout" and "idleTimeout" to e.g.
"idleWarningTimeoutSeconds" and "idleTimeoutSeconds" (or another explicit unit
suffix) and keep the numeric values the same; update any code that reads
sessionTimeout (references to sessionTimeout, idleWarningTimeout, idleTimeout)
to use the new keys and convert/validate units if necessary so the schema is
self-describing across portals.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 57ca81af-24bd-4551-b23e-0cb49db3dbab

📥 Commits

Reviewing files that changed from the base of the PR and between aed8976 and b135f4f.

📒 Files selected for processing (3)
  • portals/admin/src/main/webapp/site/public/conf/settings.json
  • portals/devportal/src/main/webapp/site/public/theme/settings.json
  • portals/publisher/src/main/webapp/site/public/conf/settings.json

Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@portals/admin/src/main/webapp/site/public/locales/fr.json`:
- Around line 981-984: The French locale contains English text for the session
timeout keys; update the values for "SessionTimeout.dialog.label.cancel",
"SessionTimeout.dialog.label.ok", "SessionTimeout.dialog.message", and
"SessionTimeout.dialog.title" in fr.json to their French translations (e.g., "Se
déconnecter", "Rester connecté", "Votre session est sur le point d'expirer en
raison de l'inactivité. Pour maintenir votre session active, cliquez sur «
Rester connecté ». Si aucune action n'est effectuée, vous serez automatiquement
déconnecté dans {time} secondes, pour des raisons de sécurité.", and "Êtes-vous
toujours là ?") so French users see the dialog in French.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8155d863-edeb-4c6a-942d-6b9ea8e5801f

📥 Commits

Reviewing files that changed from the base of the PR and between b135f4f and f550fe7.

📒 Files selected for processing (5)
  • portals/admin/src/main/webapp/site/public/locales/en.json
  • portals/admin/src/main/webapp/site/public/locales/fr.json
  • portals/devportal/src/main/webapp/site/public/locales/en.json
  • portals/devportal/src/main/webapp/site/public/theme/settings.json
  • portals/publisher/src/main/webapp/site/public/locales/en.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • portals/admin/src/main/webapp/site/public/locales/en.json
  • portals/devportal/src/main/webapp/site/public/locales/en.json
  • portals/devportal/src/main/webapp/site/public/theme/settings.json

Copy link
Copy Markdown
Contributor

@Piumal1999 Piumal1999 left a comment

Choose a reason for hiding this comment

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

@DinithHerath, I added few comments.

Also, could you please include a screenshot or a preview in the PR description?

Co-authored-by: Piumal Rathnayake <piumal1999@gmail.com>
Co-authored-by: Dinith Herath <41161459+DinithHerath@users.noreply.github.com>
Copy link
Copy Markdown

@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.

🧹 Nitpick comments (4)
portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx (2)

129-129: Consider removing unused injectIntl wrapper.

The component uses FormattedMessage components directly and doesn't access the intl prop. The injectIntl HOC can be removed since it's not providing any value here.

♻️ Suggested fix
-export default injectIntl(SessionTimeout);
+export default SessionTimeout;

And update the import:

-import { injectIntl, FormattedMessage } from 'react-intl';
+import { FormattedMessage } from 'react-intl';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx`
at line 129, Remove the unused injectIntl HOC and its import from the
SessionTimeout component: stop exporting with injectIntl(SessionTimeout) and
export the SessionTimeout component directly, and remove the corresponding
import of injectIntl since the component only uses FormattedMessage and does not
reference the intl prop; ensure the default export is simply SessionTimeout and
delete the injectIntl import statement.

108-116: Fix multiline string formatting in defaultMessage.

The defaultMessage contains a line break in the middle of the string, which may cause unexpected whitespace in the rendered output. Consider using string concatenation or a template literal for cleaner formatting.

♻️ Suggested fix
                 message={
                     <FormattedMessage
                         id='SessionTimeout.dialog.message'
-                        defaultMessage='Your session is about to expire due to inactivity. To keep your session active, 
-                        click "Stay Logged In". If no action is taken, you will be logged out 
-                        automatically in {time} seconds, for security reasons.'
+                        defaultMessage={
+                            'Your session is about to expire due to inactivity. To keep your session active, '
+                            + 'click "Stay Logged In". If no action is taken, you will be logged out '
+                            + 'automatically in {time} seconds, for security reasons.'
+                        }
                         values={{time: remainingTime}} // Use remainingTime here
                     />
                 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx`
around lines 108 - 116, The defaultMessage in the FormattedMessage inside the
SessionTimeout component contains an embedded newline which can produce
unexpected whitespace; fix it by replacing the multiline literal with a
single-line string (or concatenate/join the lines or use a template literal) for
the defaultMessage prop in the FormattedMessage call (the JSX where
id='SessionTimeout.dialog.message'), preserving the {time: remainingTime} values
prop and the same punctuation so the rendered message remains identical but
without the embedded line break.
portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)

136-136: Consider removing unused injectIntl wrapper.

Consistent with the other portal versions - the intl prop from injectIntl is not used since the component only uses FormattedMessage components directly.

♻️ Suggested fix
-export default injectIntl(SessionTimeout);
+export default SessionTimeout;

And update the import:

-import { injectIntl, FormattedMessage } from 'react-intl';
+import { FormattedMessage } from 'react-intl';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx`
at line 136, Remove the unused injectIntl wrapper around the SessionTimeout
component: replace the export default injectIntl(SessionTimeout) with a direct
export of the component (export default SessionTimeout), remove the import of
injectIntl from 'react-intl', and verify that no code in SessionTimeout (props
or propTypes) depends on an injected intl prop (the component only uses
FormattedMessage), updating propTypes if necessary.
portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)

135-135: Consider removing unused injectIntl wrapper.

Same as the publisher version - the intl prop is not used since only FormattedMessage components are used directly.

♻️ Suggested fix
-export default injectIntl(SessionTimeout);
+export default SessionTimeout;

And update the import:

-import { injectIntl, FormattedMessage } from 'react-intl';
+import { FormattedMessage } from 'react-intl';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx`
at line 135, The export currently wraps the SessionTimeout component with
injectIntl even though the component does not use the injected intl prop; remove
the injectIntl usage by exporting SessionTimeout directly (replace the export
default injectIntl(SessionTimeout) with export default SessionTimeout) and
remove the now-unused injectIntl import from the top of the file so there are no
unused imports.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx`:
- Line 136: Remove the unused injectIntl wrapper around the SessionTimeout
component: replace the export default injectIntl(SessionTimeout) with a direct
export of the component (export default SessionTimeout), remove the import of
injectIntl from 'react-intl', and verify that no code in SessionTimeout (props
or propTypes) depends on an injected intl prop (the component only uses
FormattedMessage), updating propTypes if necessary.

In
`@portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx`:
- Line 135: The export currently wraps the SessionTimeout component with
injectIntl even though the component does not use the injected intl prop; remove
the injectIntl usage by exporting SessionTimeout directly (replace the export
default injectIntl(SessionTimeout) with export default SessionTimeout) and
remove the now-unused injectIntl import from the top of the file so there are no
unused imports.

In
`@portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx`:
- Line 129: Remove the unused injectIntl HOC and its import from the
SessionTimeout component: stop exporting with injectIntl(SessionTimeout) and
export the SessionTimeout component directly, and remove the corresponding
import of injectIntl since the component only uses FormattedMessage and does not
reference the intl prop; ensure the default export is simply SessionTimeout and
delete the injectIntl import statement.
- Around line 108-116: The defaultMessage in the FormattedMessage inside the
SessionTimeout component contains an embedded newline which can produce
unexpected whitespace; fix it by replacing the multiline literal with a
single-line string (or concatenate/join the lines or use a template literal) for
the defaultMessage prop in the FormattedMessage call (the JSX where
id='SessionTimeout.dialog.message'), preserving the {time: remainingTime} values
prop and the same punctuation so the rendered message remains identical but
without the embedded line break.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2ef3cea6-e6ee-4067-ac92-6b84360a7840

📥 Commits

Reviewing files that changed from the base of the PR and between f550fe7 and bc7722b.

📒 Files selected for processing (8)
  • portals/admin/src/main/webapp/site/public/conf/settings.json
  • portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/admin/src/main/webapp/source/src/app/webWorkers/timer.worker.js
  • portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/devportal/src/main/webapp/source/src/app/webWorkers/timer.worker.js
  • portals/publisher/src/main/webapp/site/public/conf/settings.json
  • portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/publisher/src/main/webapp/source/src/app/webWorkers/timer.worker.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • portals/devportal/src/main/webapp/source/src/app/webWorkers/timer.worker.js

@DinithHerath DinithHerath requested a review from Piumal1999 March 14, 2026 13:42
Piumal1999
Piumal1999 previously approved these changes Mar 14, 2026
@PasanT9
Copy link
Copy Markdown
Contributor

PasanT9 commented Mar 16, 2026

@coderabbitai Seems like all the comments are reviewed. Please check and approve.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 16, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

Let me check the current state of all review comments on this PR.


🏁 Script executed:

#!/bin/bash
# Get all review comments on PR `#1237`
gh pr view 1237 --repo wso2/apim-apps --json reviews,reviewRequests

echo "---REVIEW THREADS---"
gh api repos/wso2/apim-apps/pulls/1237/comments --paginate | jq '[.[] | {id, body: .body[0:200], path: .path, line: .line, user: .user.login, created_at: .created_at}]'

echo "---PR REVIEW STATES---"
gh api repos/wso2/apim-apps/pulls/1237/reviews --paginate | jq '[.[] | {id, state, user: .user.login, submitted_at: .submitted_at, body: .body[0:100]}]'

Length of output: 59332


@PasanT9 I've reviewed all the comment threads on PR #1237. Here's a summary of the status:

✅ Resolved issues:

  • Direct event handler assignment (document.onclick etc.) — fixed using addEventListener/removeEventListener in all three portals
  • serviceCatalog* config path concern — clarified as a non-issue (keys were already top-level)
  • French locale English text — clarified as intentional (entire fr.json file uses English)
  • Copyright year header fixes — suggestions submitted by DinithHerath on March 14

📝 Remaining open items (all nitpick-level, non-blocking):

  • Unused injectIntl wrapper in SessionTimeout.jsx across all three portals (admin, devportal, publisher)
  • Multiline string in defaultMessage in publisher's SessionTimeout.jsx

These are minor code quality items that don't affect functionality. Piumal1999 has already approved the PR. I'll go ahead and approve.

[approve]

@DinithHerath
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 16, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@DinithHerath
Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 16, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx`:
- Line 20: The component imports and wraps SessionTimeout with injectIntl but
never uses the injected intl prop; remove the unused HOC and import: delete
injectIntl from the import list alongside FormattedMessage and change the export
so it exports the SessionTimeout component directly (stop using
injectIntl(SessionTimeout)); also remove any unused intl prop from the
SessionTimeout function signature if present. Apply the same change for the
identical component in the publisher variant.

In
`@portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx`:
- Around line 111-113: The defaultMessage string in the SessionTimeout component
(the defaultMessage prop in SessionTimeout.jsx) is split across raw newlines
using single quotes which is invalid; fix it by replacing the broken multiline
single-quoted string with a single valid JS string (either one-line,
concatenated strings, or a template literal using backticks) that preserves the
placeholder {time} and the exact message punctuation and quotes (e.g., keep
“Stay Logged In” as part of the string), ensuring no raw newlines remain in the
literal.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c976d79d-8ef9-4b21-80ee-d4e6d5bedd2e

📥 Commits

Reviewing files that changed from the base of the PR and between f550fe7 and c7a0cfd.

📒 Files selected for processing (13)
  • portals/admin/src/main/webapp/site/public/conf/settings.json
  • portals/admin/src/main/webapp/site/public/locales/en.json
  • portals/admin/src/main/webapp/site/public/locales/fr.json
  • portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/admin/src/main/webapp/source/src/app/webWorkers/timer.worker.js
  • portals/devportal/src/main/webapp/site/public/locales/en.json
  • portals/devportal/src/main/webapp/site/public/theme/settings.json
  • portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/devportal/src/main/webapp/source/src/app/webWorkers/timer.worker.js
  • portals/publisher/src/main/webapp/site/public/conf/settings.json
  • portals/publisher/src/main/webapp/site/public/locales/en.json
  • portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/publisher/src/main/webapp/source/src/app/webWorkers/timer.worker.js
🚧 Files skipped from review as they are similar to previous changes (3)
  • portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/admin/src/main/webapp/site/public/locales/fr.json
  • portals/publisher/src/main/webapp/source/src/app/webWorkers/timer.worker.js

Copy link
Copy Markdown

@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.

♻️ Duplicate comments (1)
portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)

111-113: ⚠️ Potential issue | 🔴 Critical

Fix invalid multiline single-quoted string in defaultMessage.

Line 111 starts a single-quoted string that continues across raw newlines (Lines 111-113), which is invalid JavaScript syntax.

💡 Proposed fix
-                        defaultMessage='Your session is about to expire due to inactivity. To keep your session active, 
-                        click “Stay Logged In”. If no action is taken, you will be logged out 
-                        automatically in {time} seconds, for security reasons.'
+                        defaultMessage={
+                            'Your session is about to expire due to inactivity. To keep your session active, '
+                            + 'click "Stay Logged In". If no action is taken, you will be logged out '
+                            + 'automatically in {time} seconds, for security reasons.'
+                        }
#!/bin/bash
# Verify there is no raw newline inside single-quoted defaultMessage in publisher SessionTimeout.
python - <<'PY'
from pathlib import Path
import re

p = Path("portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx")
text = p.read_text(encoding="utf-8")
m = re.search(r"defaultMessage='[^']*\n\s*[^']*'", text)

print("FOUND_INVALID_MULTILINE_SINGLE_QUOTED_DEFAULTMESSAGE" if m else "NOT_FOUND")
if m:
    print("\nMatched snippet:\n")
    print(m.group(0))
PY

Expected result after fix: NOT_FOUND.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx`
around lines 111 - 113, The defaultMessage in SessionTimeout.jsx is written as a
single-quoted string spanning raw newlines, which is invalid; update the message
in the SessionTimeout component (the defaultMessage prop) to remove raw newlines
by using a single-line string, a template literal, or explicit
concatenation/escaped newline sequences so the text does not contain unescaped
line breaks; ensure the prop value remains the same text and preserves the
{time} placeholder and smart quotes, and run the provided verification script to
confirm no raw multiline single-quoted defaultMessage remains.
🧹 Nitpick comments (1)
portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx (1)

20-20: Remove unused injectIntl wrapper.

SessionTimeout does not use an injected intl prop; FormattedMessage is sufficient on its own. This applies to all three variants: admin, publisher, and devportal.

♻️ Proposed refactor
-import { injectIntl, FormattedMessage } from 'react-intl';
+import { FormattedMessage } from 'react-intl';
...
-export default injectIntl(SessionTimeout);
+export default SessionTimeout;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx`
at line 20, Remove the unused injectIntl wrapper: update the SessionTimeout
component by deleting injectIntl from the import statement and removing any use
of injectIntl when exporting the component (e.g., change export default
injectIntl(SessionTimeout) to export default SessionTimeout); keep
FormattedMessage as-is and ensure no references to the injected intl prop remain
in the SessionTimeout component (apply same change pattern across admin,
publisher, and devportal variants).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In
`@portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx`:
- Around line 111-113: The defaultMessage in SessionTimeout.jsx is written as a
single-quoted string spanning raw newlines, which is invalid; update the message
in the SessionTimeout component (the defaultMessage prop) to remove raw newlines
by using a single-line string, a template literal, or explicit
concatenation/escaped newline sequences so the text does not contain unescaped
line breaks; ensure the prop value remains the same text and preserves the
{time} placeholder and smart quotes, and run the provided verification script to
confirm no raw multiline single-quoted defaultMessage remains.

---

Nitpick comments:
In `@portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx`:
- Line 20: Remove the unused injectIntl wrapper: update the SessionTimeout
component by deleting injectIntl from the import statement and removing any use
of injectIntl when exporting the component (e.g., change export default
injectIntl(SessionTimeout) to export default SessionTimeout); keep
FormattedMessage as-is and ensure no references to the injected intl prop remain
in the SessionTimeout component (apply same change pattern across admin,
publisher, and devportal variants).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3e2841f4-2936-4048-ae3a-b464f0e1add2

📥 Commits

Reviewing files that changed from the base of the PR and between 3cd577e and c7a0cfd.

📒 Files selected for processing (16)
  • portals/admin/src/main/webapp/site/public/conf/settings.json
  • portals/admin/src/main/webapp/site/public/locales/en.json
  • portals/admin/src/main/webapp/site/public/locales/fr.json
  • portals/admin/src/main/webapp/source/src/app/ProtectedApp.jsx
  • portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/admin/src/main/webapp/source/src/app/webWorkers/timer.worker.js
  • portals/devportal/src/main/webapp/site/public/locales/en.json
  • portals/devportal/src/main/webapp/site/public/theme/settings.json
  • portals/devportal/src/main/webapp/source/src/app/AppRouts.jsx
  • portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/devportal/src/main/webapp/source/src/app/webWorkers/timer.worker.js
  • portals/publisher/src/main/webapp/site/public/conf/settings.json
  • portals/publisher/src/main/webapp/site/public/locales/en.json
  • portals/publisher/src/main/webapp/source/src/app/ProtectedApp.jsx
  • portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/publisher/src/main/webapp/source/src/app/webWorkers/timer.worker.js

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
37.5% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@DinithHerath DinithHerath requested a review from Piumal1999 March 16, 2026 09:07
@DinithHerath
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 16, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@DinithHerath
Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 16, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@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.

🧹 Nitpick comments (4)
portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx (2)

58-59: Validate timeout values before starting idle tracking.

Malformed or inverted values can leave warning/logout logic in a broken state without obvious errors.

Suggested hardening
-        idleTimeoutRef.current = Settings.sessionTimeout.idleTimeout;
-        idleWarningTimeoutRef.current = Settings.sessionTimeout.idleWarningTimeout;
+        const idleTimeout = Number(Settings.sessionTimeout.idleTimeout);
+        const idleWarningTimeout = Number(Settings.sessionTimeout.idleWarningTimeout);
+        if (!Number.isFinite(idleTimeout) || !Number.isFinite(idleWarningTimeout)
+            || idleTimeout <= 0 || idleWarningTimeout < 0 || idleWarningTimeout >= idleTimeout) {
+            return () => { };
+        }
+        idleTimeoutRef.current = idleTimeout;
+        idleWarningTimeoutRef.current = idleWarningTimeout;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx`
around lines 58 - 59, Validate Settings.sessionTimeout values before assigning
to idleTimeoutRef.current and idleWarningTimeoutRef.current in
SessionTimeout.jsx: ensure both are finite numbers >= 0, coerce/parse numeric
types, clamp to sensible min/max, and if idleWarningTimeout >= idleTimeout
detect the inversion and either swap them or set warning to a smaller default
(e.g., idleTimeout - defaultWarningDelta). Use defined fallback constants when
values are missing or invalid and emit a console.warn or logger message
indicating which values were corrected so idle tracking and logout logic cannot
start with malformed timeouts.

67-69: Broaden idle-reset events for touch/pointer users.

Keyboard/mouse/click-only tracking does not capture common touch interactions.

Suggested listener expansion
-        document.addEventListener('click', resetIdleTimer);
-        document.addEventListener('mousemove', resetIdleTimer);
-        document.addEventListener('keydown', resetIdleTimer);
+        const activityEvents = ['click', 'mousemove', 'keydown', 'touchstart', 'pointerdown'];
+        activityEvents.forEach((eventName) => document.addEventListener(eventName, resetIdleTimer));
...
-            document.removeEventListener('click', resetIdleTimer);
-            document.removeEventListener('mousemove', resetIdleTimer);
-            document.removeEventListener('keydown', resetIdleTimer);
+            activityEvents.forEach((eventName) => document.removeEventListener(eventName, resetIdleTimer));

Also applies to: 80-82

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx`
around lines 67 - 69, The idle-reset currently only listens for 'click',
'mousemove', and 'keydown' via document.addEventListener; extend this to include
touch and pointer interactions by adding listeners for 'touchstart',
'touchmove', 'pointerdown', and 'pointermove' (using the same resetIdleTimer
callback) wherever document.addEventListener('click'...),
document.addEventListener('mousemove'...), and
document.addEventListener('keydown'...) are added (e.g., near the resetIdleTimer
setup and the corresponding cleanup/removeEventListener logic) so touch/pointer
users are properly detected and cleaned up symmetrically.
portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx (2)

67-69: Include touch/pointer activity in idle reset listeners.

Current listeners miss touch-only interactions, which can log active mobile/tablet users out unexpectedly.

Suggested listener expansion
-        document.addEventListener('click', resetIdleTimer);
-        document.addEventListener('mousemove', resetIdleTimer);
-        document.addEventListener('keydown', resetIdleTimer);
+        const activityEvents = ['click', 'mousemove', 'keydown', 'touchstart', 'pointerdown'];
+        activityEvents.forEach((eventName) => document.addEventListener(eventName, resetIdleTimer));
...
-            document.removeEventListener('click', resetIdleTimer);
-            document.removeEventListener('mousemove', resetIdleTimer);
-            document.removeEventListener('keydown', resetIdleTimer);
+            activityEvents.forEach((eventName) => document.removeEventListener(eventName, resetIdleTimer));

Also applies to: 80-82

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx`
around lines 67 - 69, The idle-reset event handlers in SessionTimeout.jsx
currently attach only 'click', 'mousemove', and 'keydown' to call
resetIdleTimer; add touch and pointer events to cover mobile/tablet interactions
by including 'touchstart', 'touchmove', and 'pointerdown' (and/or 'pointermove')
alongside the existing events wherever document.addEventListener(...) is used
(the same place that registers resetIdleTimer), and mirror those same events in
the cleanup/removeEventListener calls so removeEventListener(...) also
unregisters 'touchstart', 'touchmove', and 'pointerdown' for the same
resetIdleTimer handler.

58-59: Harden timeout config parsing before enabling the worker flow.

If these values are missing, non-numeric, or misordered (idleWarningTimeout >= idleTimeout), the warning/logout logic can fail silently.

Suggested hardening
-        idleTimeoutRef.current = Configurations.sessionTimeout.idleTimeout;
-        idleWarningTimeoutRef.current = Configurations.sessionTimeout.idleWarningTimeout;
+        const idleTimeout = Number(Configurations.sessionTimeout.idleTimeout);
+        const idleWarningTimeout = Number(Configurations.sessionTimeout.idleWarningTimeout);
+        if (!Number.isFinite(idleTimeout) || !Number.isFinite(idleWarningTimeout)
+            || idleTimeout <= 0 || idleWarningTimeout < 0 || idleWarningTimeout >= idleTimeout) {
+            return () => { };
+        }
+        idleTimeoutRef.current = idleTimeout;
+        idleWarningTimeoutRef.current = idleWarningTimeout;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx`
around lines 58 - 59, Validate and normalize session timeout values before
assigning to idleTimeoutRef.current and idleWarningTimeoutRef.current: read
Configurations.sessionTimeout, ensure both idleTimeout and idleWarningTimeout
exist and are numeric and positive, coerce or parse integers, enforce
idleWarningTimeout < idleTimeout (swap or clamp if misordered), and only enable
the worker flow when the final validated values meet these rules; otherwise fall
back to safe defaults and log a warning so the idle warning/logout logic won’t
fail silently (refer to Configurations.sessionTimeout, idleTimeoutRef.current,
idleWarningTimeoutRef.current and the code path that starts the worker).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx`:
- Around line 67-69: The idle-reset event handlers in SessionTimeout.jsx
currently attach only 'click', 'mousemove', and 'keydown' to call
resetIdleTimer; add touch and pointer events to cover mobile/tablet interactions
by including 'touchstart', 'touchmove', and 'pointerdown' (and/or 'pointermove')
alongside the existing events wherever document.addEventListener(...) is used
(the same place that registers resetIdleTimer), and mirror those same events in
the cleanup/removeEventListener calls so removeEventListener(...) also
unregisters 'touchstart', 'touchmove', and 'pointerdown' for the same
resetIdleTimer handler.
- Around line 58-59: Validate and normalize session timeout values before
assigning to idleTimeoutRef.current and idleWarningTimeoutRef.current: read
Configurations.sessionTimeout, ensure both idleTimeout and idleWarningTimeout
exist and are numeric and positive, coerce or parse integers, enforce
idleWarningTimeout < idleTimeout (swap or clamp if misordered), and only enable
the worker flow when the final validated values meet these rules; otherwise fall
back to safe defaults and log a warning so the idle warning/logout logic won’t
fail silently (refer to Configurations.sessionTimeout, idleTimeoutRef.current,
idleWarningTimeoutRef.current and the code path that starts the worker).

In
`@portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx`:
- Around line 58-59: Validate Settings.sessionTimeout values before assigning to
idleTimeoutRef.current and idleWarningTimeoutRef.current in SessionTimeout.jsx:
ensure both are finite numbers >= 0, coerce/parse numeric types, clamp to
sensible min/max, and if idleWarningTimeout >= idleTimeout detect the inversion
and either swap them or set warning to a smaller default (e.g., idleTimeout -
defaultWarningDelta). Use defined fallback constants when values are missing or
invalid and emit a console.warn or logger message indicating which values were
corrected so idle tracking and logout logic cannot start with malformed
timeouts.
- Around line 67-69: The idle-reset currently only listens for 'click',
'mousemove', and 'keydown' via document.addEventListener; extend this to include
touch and pointer interactions by adding listeners for 'touchstart',
'touchmove', 'pointerdown', and 'pointermove' (using the same resetIdleTimer
callback) wherever document.addEventListener('click'...),
document.addEventListener('mousemove'...), and
document.addEventListener('keydown'...) are added (e.g., near the resetIdleTimer
setup and the corresponding cleanup/removeEventListener logic) so touch/pointer
users are properly detected and cleaned up symmetrically.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 37033a20-153e-4b8d-a3cc-44c7e47f71a9

📥 Commits

Reviewing files that changed from the base of the PR and between 3cd577e and 3d301b5.

📒 Files selected for processing (16)
  • portals/admin/src/main/webapp/site/public/conf/settings.json
  • portals/admin/src/main/webapp/site/public/locales/en.json
  • portals/admin/src/main/webapp/site/public/locales/fr.json
  • portals/admin/src/main/webapp/source/src/app/ProtectedApp.jsx
  • portals/admin/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/admin/src/main/webapp/source/src/app/webWorkers/timer.worker.js
  • portals/devportal/src/main/webapp/site/public/locales/en.json
  • portals/devportal/src/main/webapp/site/public/theme/settings.json
  • portals/devportal/src/main/webapp/source/src/app/AppRouts.jsx
  • portals/devportal/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/devportal/src/main/webapp/source/src/app/webWorkers/timer.worker.js
  • portals/publisher/src/main/webapp/site/public/conf/settings.json
  • portals/publisher/src/main/webapp/site/public/locales/en.json
  • portals/publisher/src/main/webapp/source/src/app/ProtectedApp.jsx
  • portals/publisher/src/main/webapp/source/src/app/components/SessionTimeout.jsx
  • portals/publisher/src/main/webapp/source/src/app/webWorkers/timer.worker.js

@PasanT9 PasanT9 merged commit 7906754 into wso2:main Mar 17, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Silent Authentication for APIM portals to keep the session in sync with IDP

3 participants