Skip to content

fix: user login/logout sync#1558

Open
parmesant wants to merge 1 commit intoparseablehq:mainfrom
parmesant:session-sync
Open

fix: user login/logout sync#1558
parmesant wants to merge 1 commit intoparseablehq:mainfrom
parmesant:session-sync

Conversation

@parmesant
Copy link
Contributor

@parmesant parmesant commented Feb 26, 2026

Fixes #XXXX.

Description


This PR has:

  • been tested to ensure log ingestion and log query works.
  • added comments explaining the "why" and the intent of the code wherever would not be obvious for an unfamiliar reader.
  • added documentation for new or modified features or behaviors.

Summary by CodeRabbit

  • New Features

    • Added Prism node integration with configurable endpoint via CLI option and environment variable.
    • Enhanced logout synchronization across cluster nodes.
  • Improvements

    • Improved cookie handling to support multiple cookie values.
  • Chores

    • Removed debug logging statements.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 26, 2026

Walkthrough

This PR adds Prism node endpoint configuration and implements post-logout synchronization. It introduces a prism_endpoint field for Prism node integration, adds a new logout_sync function that communicates with all live nodes, extends logout handlers to trigger synchronization, and refines cookie handling and logging.

Changes

Cohort / File(s) Summary
Prism Integration
src/cli.rs
Added prism_endpoint configuration field with clap attributes to support Prism node connectivity via environment variable or CLI argument.
Logout Synchronization
src/handlers/http/oidc.rs, src/utils/mod.rs
Introduced logout_sync() async function that posts logout notifications to /o/logout/sync on all live nodes; integrated into logout handler to trigger post-redirect synchronization.
Utility Refinements
src/rbac/user.rs, src/utils/mod.rs
Removed debug logging statement from UserGroup validation; extended cookie header handling to support multiple cookies; removed warning log for missing stream authentication.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant OIDCHandler as OIDC Handler
    participant UtilsFunc as Utils (logout_sync)
    participant LiveNode1 as Live Node 1
    participant LiveNode2 as Live Node 2

    Client->>OIDCHandler: POST /logout request
    activate OIDCHandler
    OIDCHandler->>OIDCHandler: Determine redirect response
    OIDCHandler->>UtilsFunc: await logout_sync(session, tenant_id)
    deactivate OIDCHandler
    activate UtilsFunc
    UtilsFunc->>LiveNode1: POST /o/logout/sync (sessionKey)
    UtilsFunc->>LiveNode2: POST /o/logout/sync (sessionKey)
    LiveNode1-->>UtilsFunc: OK
    LiveNode2-->>UtilsFunc: OK
    deactivate UtilsFunc
    OIDCHandler-->>Client: Redirect Response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Suggested labels

for next release

Suggested reviewers

  • praveen5959
  • nikhilsinhaparseable

Poem

🐰 A Prism node now shines so bright,
With logout sync spreading the light,
Across all nodes the word does fly,
Sessions fade as cookies comply,
Config and sync in harmony unite! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description uses only the template placeholders with no actual content filled in: issue reference, goal, solutions, key changes, and all checklist items remain unchecked. Fill in the description section with the actual goal, solutions chosen with rationale, and key changes. Check off completed checklist items or explain why they were not completed.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: user login/logout sync' clearly summarizes the main change, which introduces logout synchronization and prism endpoint configuration across multiple files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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

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

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

🧹 Nitpick comments (1)
src/utils/mod.rs (1)

309-337: Consider logging or handling failed sync responses.

The function propagates transport errors but does not check HTTP response status codes. A node returning 4xx/5xx will be silently ignored. While this may be intentional for resilience (logout should proceed even if some nodes fail), consider logging failed sync attempts for observability.

This pattern is consistent with login_sync above, so if intentional, no change needed.

♻️ Optional: Add response status check with logging
         async move {
-            INTRA_CLUSTER_CLIENT
+            let response = INTRA_CLUSTER_CLIENT
                 .post(url)
                 .header(header::AUTHORIZATION, node.token)
                 .header(header::CONTENT_TYPE, "application/json")
                 .json(&json!(
                     {
                         "sessionKey": _session
                     }
                 ))
                 .send()
                 .await?;
+            if !response.status().is_success() {
+                tracing::warn!("logout_sync failed for node: status {}", response.status());
+            }
             Ok::<(), anyhow::Error>(())
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/mod.rs` around lines 309 - 337, The logout_sync loop currently
sends requests via INTRA_CLUSTER_CLIENT inside for_each_live_node but does not
inspect HTTP response status, so 4xx/5xx from nodes are ignored; update the
async block in logout_sync to capture the response from .send().await, check
response.status().is_success(), and when not successful use the project's
logging (e.g., tracing::error! or the same logger used elsewhere) to record the
node.identity/domain and status/body to aid observability; ensure the function
still returns Ok(()) on per-node failures if you want to preserve resilience
(i.e., log and continue rather than propagating an error), matching the behavior
of login_sync if that pattern is intended.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/utils/mod.rs`:
- Around line 256-263: The loop over request cookies currently calls
map.insert(...) which overwrites the COOKIE header so only the last cookie
remains; change the call to map.append(reqwest::header::COOKIE,
reqwest::header::HeaderValue::from_bytes(cookie.as_bytes()).unwrap()) so each
iteration adds a cookie value instead of replacing the previous one (update the
code where req.get_all(...), cookie, and map are used).

---

Nitpick comments:
In `@src/utils/mod.rs`:
- Around line 309-337: The logout_sync loop currently sends requests via
INTRA_CLUSTER_CLIENT inside for_each_live_node but does not inspect HTTP
response status, so 4xx/5xx from nodes are ignored; update the async block in
logout_sync to capture the response from .send().await, check
response.status().is_success(), and when not successful use the project's
logging (e.g., tracing::error! or the same logger used elsewhere) to record the
node.identity/domain and status/body to aid observability; ensure the function
still returns Ok(()) on per-node failures if you want to preserve resilience
(i.e., log and continue rather than propagating an error), matching the behavior
of login_sync if that pattern is intended.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f1278d2 and 51e3f7e.

📒 Files selected for processing (4)
  • src/cli.rs
  • src/handlers/http/oidc.rs
  • src/rbac/user.rs
  • src/utils/mod.rs
💤 Files with no reviewable changes (1)
  • src/rbac/user.rs

Comment on lines +256 to +263
} else if req.contains_key(actix_web::http::header::COOKIE) {
// multiple cookies
for cookie in req.get_all(actix_web::http::header::COOKIE) {
map.insert(
reqwest::header::COOKIE,
reqwest::header::HeaderValue::from_bytes(cookie.as_bytes()).unwrap(),
);
}
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 | 🟠 Major

Bug: Only the last cookie is retained due to insert() overwriting.

The loop iterates over all cookies but insert() replaces the previous value for the same key. Only the last cookie will be preserved. Use append() instead to add multiple cookie values.

🐛 Proposed fix
     } else if req.contains_key(actix_web::http::header::COOKIE) {
         // multiple cookies
         for cookie in req.get_all(actix_web::http::header::COOKIE) {
-            map.insert(
+            map.append(
                 reqwest::header::COOKIE,
                 reqwest::header::HeaderValue::from_bytes(cookie.as_bytes()).unwrap(),
             );
         }
📝 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
} else if req.contains_key(actix_web::http::header::COOKIE) {
// multiple cookies
for cookie in req.get_all(actix_web::http::header::COOKIE) {
map.insert(
reqwest::header::COOKIE,
reqwest::header::HeaderValue::from_bytes(cookie.as_bytes()).unwrap(),
);
}
} else if req.contains_key(actix_web::http::header::COOKIE) {
// multiple cookies
for cookie in req.get_all(actix_web::http::header::COOKIE) {
map.append(
reqwest::header::COOKIE,
reqwest::header::HeaderValue::from_bytes(cookie.as_bytes()).unwrap(),
);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/mod.rs` around lines 256 - 263, The loop over request cookies
currently calls map.insert(...) which overwrites the COOKIE header so only the
last cookie remains; change the call to map.append(reqwest::header::COOKIE,
reqwest::header::HeaderValue::from_bytes(cookie.as_bytes()).unwrap()) so each
iteration adds a cookie value instead of replacing the previous one (update the
code where req.get_all(...), cookie, and map are used).

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.

1 participant