Skip to content

Feature/login plugin - #162

Open
kappsegla wants to merge 28 commits into
mainfrom
feature/loginPlugin
Open

Feature/login plugin#162
kappsegla wants to merge 28 commits into
mainfrom
feature/loginPlugin

Conversation

@kappsegla

@kappsegla kappsegla commented Jul 5, 2026

Copy link
Copy Markdown

Summary by CodeRabbit

  • New Features
    • Added session-based authentication using SID cookies, including automatic protection for non-public pages.
    • Introduced /login, /logout, and /session/status, plus homepage logout visibility tied to authentication.
    • Implemented server-side session tracking with periodic idle-timeout cleanup and a session status JSON endpoint.
  • Bug Fixes
    • Improved login security with CSRF validation and consistent unauthenticated handling (redirect on GET, 401 otherwise).
  • Documentation
    • Clarified global BasicAuth behavior in pipeline usage notes.
  • Tests
    • Added/expanded tests for login, logout, session auth/status, and idle cleanup.
  • Chores
    • Updated logout button styling/hover behavior in the UI.

…ugin and GatewayRouter. Updated Bootstrap to integrate BasicAuth and adjusted RouterConfig for login endpoint.
… handling. Update BasicAuthPlugin to support dynamic realm rotation.
…ionAuthFilter`, `SessionStore`, and related plugins (`LogoutPlugin`, `SessionStatusPlugin`). Update tests for new session handling implementation.
…ionAuthFilter`, `SessionStore`, and related plugins (`LogoutPlugin`, `SessionStatusPlugin`). Update tests for new session handling implementation.
@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1f54e738-0667-4e6f-958e-97156068207c

📥 Commits

Reviewing files that changed from the base of the PR and between 45da7ba and ca74209.

📒 Files selected for processing (2)
  • src/main/java/org/juv25d/plugin/LogoutPlugin.java
  • src/main/resources/static/css/styles.css
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/resources/static/css/styles.css

📝 Walkthrough

Walkthrough

Adds server-side sessions, scheduled cleanup, global authentication filtering, login/logout/status endpoints, route registration, frontend logout visibility, credential handling, configuration, and tests.

Changes

Session Authentication Feature

Layer / File(s) Summary
Session model and cleanup store
src/main/java/org/juv25d/auth/..., src/main/java/org/juv25d/App.java, src/test/java/org/juv25d/auth/...
Adds session identity, idle expiration, secure IDs, access tracking, scheduled cleanup, application lifecycle controls, and scheduler validation.
Cookie utility and global authentication filter
src/main/java/org/juv25d/util/CookieUtils.java, src/main/java/org/juv25d/filter/SessionAuthFilter.java, src/test/java/org/juv25d/filter/...
Parses SID cookies and enforces public-path bypass, redirects, 401 responses, and authenticated filter-chain pass-through.
Login and credential handling
src/main/java/org/juv25d/plugin/LoginPlugin.java, config/Users, src/test/java/org/juv25d/plugin/LoginPluginTest.java
Adds CSRF-protected login rendering, credential loading and verification, session creation, SID cookies, and login tests.
Logout and session status
src/main/java/org/juv25d/plugin/LogoutPlugin.java, src/main/java/org/juv25d/plugin/SessionStatusPlugin.java, src/test/java/org/juv25d/plugin/LogoutPluginTest.java
Adds POST logout invalidation and cookie clearing, plus JSON authentication status reporting.
Routing, bootstrap, and frontend integration
src/main/java/org/juv25d/router/RouterConfig.java, src/main/java/org/juv25d/Bootstrap.java, src/main/resources/static/index.html, src/main/resources/static/css/styles.css, docs/notes/pipeline-usage.md
Registers authentication routes, invokes router configuration during bootstrap, adds conditional logout visibility and styling, and documents global BasicAuth handling.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant SessionAuthFilter
  participant LoginPlugin
  participant SessionStore
  participant LogoutPlugin

  Browser->>SessionAuthFilter: request protected path
  SessionAuthFilter->>SessionStore: get(sid)
  SessionStore-->>SessionAuthFilter: no session
  SessionAuthFilter-->>Browser: 302 to /login
  Browser->>LoginPlugin: POST credentials and CSRF token
  LoginPlugin->>SessionStore: create(username)
  SessionStore-->>LoginPlugin: Session
  LoginPlugin-->>Browser: 302 with SID cookie
  Browser->>SessionAuthFilter: request with SID cookie
  SessionAuthFilter->>SessionStore: get(sid)
  SessionStore-->>SessionAuthFilter: Session
  SessionAuthFilter-->>Browser: continue request
  Browser->>LogoutPlugin: POST /logout
  LogoutPlugin->>SessionStore: invalidate(sid)
  LogoutPlugin-->>Browser: 302 with cleared cookie
Loading

Possibly related PRs

Suggested labels: enhancement

Poem

A rabbit guards the login gate,
With SID tucked in, I hop in late.
Sessions bloom and cookies glow,
Status tells which paths to go.
Logout clears the burrow bright! 🐰

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is related to the changeset, but it is too generic to describe the main scope beyond a login-related feature. Use a more specific title, such as "Add session-based login/logout authentication".
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/loginPlugin

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
config/Users (1)

1-2: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Replace the committed default login credentials. LoginPlugin loads config/Users by default, so lunk:lunk becomes a real credential unless every deployment overrides the path. If this is only a sample fixture, keep it out of the runtime fallback or replace it with clearly non-production data.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/Users` around lines 1 - 2, Replace the committed default credentials
in config/Users so LoginPlugin does not ship with a real fallback login. Update
the default data used by LoginPlugin’s config loading path to remove lunk:lunk,
and if this file is only a sample fixture, keep it out of the runtime fallback
or replace it with clearly non-production placeholder credentials.
🧹 Nitpick comments (4)
src/main/java/org/juv25d/auth/SessionStore.java (1)

31-38: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Cleanup runs synchronously on every session creation.

cleanupExpired() performs a full scan of sessions on every create() call, so login latency grows with the number of stored sessions. Consider decoupling expiry cleanup from the hot path (e.g., a scheduled background sweep or a counter-triggered periodic sweep) instead of running it on every login.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/org/juv25d/auth/SessionStore.java` around lines 31 - 38,
SessionStore.create currently calls cleanupExpired() on every new session,
putting a full sessions scan on the login hot path. Move the expiry sweep out of
create by making cleanupExpired run on a background schedule or only after a
periodic trigger/counter threshold, and keep create focused on creating and
storing the Session. Use the SessionStore and cleanupExpired symbols to locate
the change.
src/test/java/org/juv25d/filter/SessionAuthFilterTest.java (1)

22-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test leaves session in the shared singleton store.

SessionStore is a process-wide singleton; the session created in authenticatedRequest_passesThrough_andSetsHeaders is never invalidated, so it persists across tests/test classes sharing the JVM. Consider invalidating created sessions in @AfterEach.

♻️ Proposed cleanup
+    `@AfterEach`
+    void tearDown() {
+        // invalidate any sessions created during the test
+    }

Also applies to: 61-79

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/test/java/org/juv25d/filter/SessionAuthFilterTest.java` around lines 22 -
27, The SessionAuthFilterTest setup leaves state behind in the process-wide
SessionStore singleton, so sessions created by
authenticatedRequest_passesThrough_andSetsHeaders can leak into later tests.
Update SessionAuthFilterTest to track any created session IDs and invalidate
them in an `@AfterEach` cleanup method, alongside any other test-created sessions,
while keeping the existing setup() reset of SessionStore intact.
src/test/java/org/juv25d/plugin/LoginPluginTest.java (1)

43-101: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding edge-case test coverage.

Current tests cover GET render, valid login, and invalid credentials. Missing: empty username/password (line 41-44 branch in LoginPlugin), unsupported HTTP method (405 branch), and missing/incorrect Content-Type on POST.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/test/java/org/juv25d/plugin/LoginPluginTest.java` around lines 43 - 101,
Add edge-case coverage for LoginPlugin.handle by testing the branches not
currently exercised: empty username/password input, unsupported HTTP methods
that should return 405, and POST requests with missing or incorrect
Content-Type. Extend LoginPluginTest with focused cases that call plugin.handle
with these request variants and assert the expected status/body behavior so the
login form and validation paths are fully covered.
src/test/java/org/juv25d/plugin/LogoutPluginTest.java (1)

24-53: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding a no-cookie/invalid-session logout test.

Only the happy path (valid session) is covered. Add a case where no SID cookie is sent (or it references an unknown session) to confirm handle() still clears the cookie and redirects gracefully.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/test/java/org/juv25d/plugin/LogoutPluginTest.java` around lines 24 - 53,
Add a logout test that covers the no-cookie or invalid-session path in
LogoutPluginTest, since only the valid-session flow is currently asserted.
Create a request without an SID cookie, or with one that does not match any
SessionStore entry, then call LogoutPlugin.handle and verify it still returns a
302 redirect to "/" and sets a clearing SID cookie with the expected attributes.
Use the existing SessionStore, HttpRequest, HttpResponse, and LogoutPlugin
symbols to keep the test aligned with the current happy-path setup.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/java/org/juv25d/auth/SessionStore.java`:
- Around line 13-22: SessionStore is intended to be a singleton, but it is still
publicly instantiable because no constructor is declared. Add a private
constructor inside SessionStore so only getInstance() can create/access the
single shared instance, and keep the existing INSTANCE field as the sole source
of truth used by SessionAuthFilter, LoginPlugin, and LogoutPlugin.

In `@src/main/java/org/juv25d/Bootstrap.java`:
- Around line 33-39: Bootstrap currently relies on an unused RouterConfig DI
lookup to trigger route registration, which is easy to remove accidentally. In
the bootstrap flow that builds the Pipeline, replace the implicit
side-effect-only container.get(RouterConfig.class) with an explicit
initialization step on RouterConfig so the /login, /logout, /session/status, and
proxy routes are registered intentionally. Keep the base Router retrieval and
Pipeline construction tied to that explicit setup so the behavior remains
obvious and harder to break during refactors.

In `@src/main/java/org/juv25d/filter/SessionAuthFilter.java`:
- Around line 60-64: The authenticated response headers in SessionAuthFilter are
leaking user identity to clients, so remove the X-Authenticated and X-User
response header writes from the authenticated path and keep authentication state
exposed only through the existing /session/status flow. Update the doFilter
logic in SessionAuthFilter so it still allows the request through with
chain.doFilter(req, res) but no longer sets client-visible identity headers on
every authenticated response.

In `@src/main/java/org/juv25d/plugin/LoginPlugin.java`:
- Around line 46-51: The login check in LoginPlugin is comparing cleartext
passwords from loadUsers() directly against the submitted password, so update
the credential flow to store hashed passwords (for example via bcrypt or argon2)
and verify against the hash instead of using Objects.equals() on raw strings.
Keep the fix localized around loadUsers(), resolveUsersFilePath(), and the
username/password validation block so the login path performs a hash
verification with constant-time comparison for the final check.
- Around line 37-63: The LoginPlugin login handler accepts credentials without
any CSRF validation, so add a same-origin safeguard before creating the session.
Update the login flow in LoginPlugin to reject requests unless a valid CSRF
token is present or the request passes an Origin/Referer same-origin check, and
make sure the login form generated by renderLoginForm includes the token when
applicable. Apply the check in the credential-processing path that currently
uses parseForm, loadUsers, and SessionStore.create so the session cookie is only
issued for legitimate same-site submissions.

In `@src/main/java/org/juv25d/plugin/LogoutPlugin.java`:
- Around line 36-60: The readCookie logic in LogoutPlugin is duplicated across
session-related components, so move it into a shared utility such as CookieUtils
and have LogoutPlugin, SessionStatusPlugin, LoginPlugin, and SessionAuthFilter
call that common helper. Keep the same parsing and decoding behavior in the
extracted method, and update the UTF_8 reference to use the imported
StandardCharsets instead of the fully qualified name.
- Around line 18-34: The logout handler in LogoutPlugin.handle() currently
accepts any HTTP method, which allows CSRF via GET. Add an explicit method check
at the start of handle() so only POST is accepted, and reject other methods with
an appropriate non-success response before touching SessionStore or clearing the
SID cookie. Use the existing handle(HttpRequest, HttpResponse) entry point and
its req.method() access to enforce the restriction consistently with
LoginPlugin’s method-specific behavior.

---

Outside diff comments:
In `@config/Users`:
- Around line 1-2: Replace the committed default credentials in config/Users so
LoginPlugin does not ship with a real fallback login. Update the default data
used by LoginPlugin’s config loading path to remove lunk:lunk, and if this file
is only a sample fixture, keep it out of the runtime fallback or replace it with
clearly non-production placeholder credentials.

---

Nitpick comments:
In `@src/main/java/org/juv25d/auth/SessionStore.java`:
- Around line 31-38: SessionStore.create currently calls cleanupExpired() on
every new session, putting a full sessions scan on the login hot path. Move the
expiry sweep out of create by making cleanupExpired run on a background schedule
or only after a periodic trigger/counter threshold, and keep create focused on
creating and storing the Session. Use the SessionStore and cleanupExpired
symbols to locate the change.

In `@src/test/java/org/juv25d/filter/SessionAuthFilterTest.java`:
- Around line 22-27: The SessionAuthFilterTest setup leaves state behind in the
process-wide SessionStore singleton, so sessions created by
authenticatedRequest_passesThrough_andSetsHeaders can leak into later tests.
Update SessionAuthFilterTest to track any created session IDs and invalidate
them in an `@AfterEach` cleanup method, alongside any other test-created sessions,
while keeping the existing setup() reset of SessionStore intact.

In `@src/test/java/org/juv25d/plugin/LoginPluginTest.java`:
- Around line 43-101: Add edge-case coverage for LoginPlugin.handle by testing
the branches not currently exercised: empty username/password input, unsupported
HTTP methods that should return 405, and POST requests with missing or incorrect
Content-Type. Extend LoginPluginTest with focused cases that call plugin.handle
with these request variants and assert the expected status/body behavior so the
login form and validation paths are fully covered.

In `@src/test/java/org/juv25d/plugin/LogoutPluginTest.java`:
- Around line 24-53: Add a logout test that covers the no-cookie or
invalid-session path in LogoutPluginTest, since only the valid-session flow is
currently asserted. Create a request without an SID cookie, or with one that
does not match any SessionStore entry, then call LogoutPlugin.handle and verify
it still returns a 302 redirect to "/" and sets a clearing SID cookie with the
expected attributes. Use the existing SessionStore, HttpRequest, HttpResponse,
and LogoutPlugin symbols to keep the test aligned with the current happy-path
setup.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 38a84309-4ed6-4b87-9d34-9c182997f2ac

📥 Commits

Reviewing files that changed from the base of the PR and between d3b747c and a02963e.

📒 Files selected for processing (14)
  • config/Users
  • docs/notes/pipeline-usage.md
  • src/main/java/org/juv25d/Bootstrap.java
  • src/main/java/org/juv25d/auth/Session.java
  • src/main/java/org/juv25d/auth/SessionStore.java
  • src/main/java/org/juv25d/filter/SessionAuthFilter.java
  • src/main/java/org/juv25d/plugin/LoginPlugin.java
  • src/main/java/org/juv25d/plugin/LogoutPlugin.java
  • src/main/java/org/juv25d/plugin/SessionStatusPlugin.java
  • src/main/java/org/juv25d/router/RouterConfig.java
  • src/main/resources/static/index.html
  • src/test/java/org/juv25d/filter/SessionAuthFilterTest.java
  • src/test/java/org/juv25d/plugin/LoginPluginTest.java
  • src/test/java/org/juv25d/plugin/LogoutPluginTest.java

Comment thread src/main/java/org/juv25d/auth/SessionStore.java
Comment thread src/main/java/org/juv25d/Bootstrap.java Outdated
Comment thread src/main/java/org/juv25d/filter/SessionAuthFilter.java Outdated
Comment thread src/main/java/org/juv25d/plugin/LoginPlugin.java
Comment thread src/main/java/org/juv25d/plugin/LoginPlugin.java
Comment thread src/main/java/org/juv25d/plugin/LogoutPlugin.java
Comment thread src/main/java/org/juv25d/plugin/LogoutPlugin.java Outdated
…iguration. Update `Bootstrap` to initialize routes using `RouterConfig`.
…date form rendering and tests for CSRF token validation.
…invalid methods. Update test to reflect change.
…Password` method for authentication and `hashPassword` utility for administrators. Update tests to reflect hashed password handling.
…. Refactor `SessionAuthFilter`, `LoginPlugin`, `SessionStatusPlugin`, and `LogoutPlugin` to use the new utility.
…. Refactor `SessionAuthFilter`, `LoginPlugin`, `SessionStatusPlugin`, and `LogoutPlugin` to use the new utility.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/test/java/org/juv25d/plugin/LoginPluginTest.java (1)

21-45: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Restore the previous system-property values.

setup() clears any existing users.* properties, and cleanup() clears them again, permanently changing JVM-global state for other tests. Save the original values and restore them in @AfterEach to avoid order-dependent failures.

Proposed fix
+    private String previousUsersFile;
+    private String previousUsersDir;
+    private String previousUsersFilename;
+
     `@BeforeEach`
     void setup() throws IOException {
+        previousUsersFile = System.getProperty("users.file");
+        previousUsersDir = System.getProperty("users.dir");
+        previousUsersFilename = System.getProperty("users.filename");
         System.clearProperty("users.file");
         System.clearProperty("users.dir");
         System.clearProperty("users.filename");
         // ...
     }

     `@AfterEach`
     void cleanup() throws IOException {
-        System.clearProperty("users.file");
-        System.clearProperty("users.dir");
-        System.clearProperty("users.filename");
+        restoreProperty("users.file", previousUsersFile);
+        restoreProperty("users.dir", previousUsersDir);
+        restoreProperty("users.filename", previousUsersFilename);
         // ...
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/test/java/org/juv25d/plugin/LoginPluginTest.java` around lines 21 - 45,
Update LoginPluginTest setup() and cleanup() to capture the original values of
users.file, users.dir, and users.filename before clearing them, then restore
those saved values in cleanup() instead of always clearing the properties.
Preserve null values by removing properties that were originally unset, and
continue deleting tempUsersFile as before.
🧹 Nitpick comments (1)
src/test/java/org/juv25d/plugin/LoginPluginTest.java (1)

68-115: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Add negative CSRF and same-origin tests.

These tests only exercise valid CSRF tokens. Add cases for missing/mismatched CSRF tokens and cross-origin requests, asserting rejection and that no SID cookie is issued.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/test/java/org/juv25d/plugin/LoginPluginTest.java` around lines 68 - 115,
Add negative tests in LoginPluginTest alongside the existing postLogin tests for
a missing CSRF token, a mismatched CSRF token, and a cross-origin request.
Invoke LoginPlugin.handle for each case and assert the request is rejected, the
response is not a successful login redirect, and the Set-Cookie header does not
contain a SID cookie.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/java/org/juv25d/plugin/LoginPlugin.java`:
- Around line 76-77: Update the password assignment in the login flow to
preserve the exact form value, removing the trim operation while retaining the
existing empty default. Keep username normalization unchanged and ensure the
unmodified password is passed to verification and hashPassword consistently.
- Around line 278-286: Update LoginPlugin.hashPassword to use a substantially
higher PBKDF2-HMAC-SHA256 iteration count and add a version identifier to the
returned hash format. Preserve the salt and derived-hash encoding, and ensure
the format clearly distinguishes new hashes so existing Users entries can be
migrated.
- Around line 218-229: Update isSameOrigin to parse the Origin and Referer
values as URIs, then compare their normalized host and port exactly against the
request Host authority. Remove the contains-based matching and ensure a missing
Host or invalid URI fails closed rather than matching every value.

---

Outside diff comments:
In `@src/test/java/org/juv25d/plugin/LoginPluginTest.java`:
- Around line 21-45: Update LoginPluginTest setup() and cleanup() to capture the
original values of users.file, users.dir, and users.filename before clearing
them, then restore those saved values in cleanup() instead of always clearing
the properties. Preserve null values by removing properties that were originally
unset, and continue deleting tempUsersFile as before.

---

Nitpick comments:
In `@src/test/java/org/juv25d/plugin/LoginPluginTest.java`:
- Around line 68-115: Add negative tests in LoginPluginTest alongside the
existing postLogin tests for a missing CSRF token, a mismatched CSRF token, and
a cross-origin request. Invoke LoginPlugin.handle for each case and assert the
request is rejected, the response is not a successful login redirect, and the
Set-Cookie header does not contain a SID cookie.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5be5072d-e362-45ad-8c47-029554c04f1a

📥 Commits

Reviewing files that changed from the base of the PR and between a02963e and df44deb.

📒 Files selected for processing (11)
  • src/main/java/org/juv25d/Bootstrap.java
  • src/main/java/org/juv25d/auth/SessionStore.java
  • src/main/java/org/juv25d/filter/SessionAuthFilter.java
  • src/main/java/org/juv25d/plugin/LoginPlugin.java
  • src/main/java/org/juv25d/plugin/LogoutPlugin.java
  • src/main/java/org/juv25d/plugin/SessionStatusPlugin.java
  • src/main/java/org/juv25d/router/RouterConfig.java
  • src/main/java/org/juv25d/util/CookieUtils.java
  • src/test/java/org/juv25d/filter/SessionAuthFilterTest.java
  • src/test/java/org/juv25d/plugin/LoginPluginTest.java
  • src/test/java/org/juv25d/plugin/LogoutPluginTest.java
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/main/java/org/juv25d/auth/SessionStore.java
  • src/main/java/org/juv25d/router/RouterConfig.java
  • src/test/java/org/juv25d/plugin/LogoutPluginTest.java

Comment thread src/main/java/org/juv25d/plugin/LoginPlugin.java Outdated
Comment thread src/main/java/org/juv25d/plugin/LoginPlugin.java Outdated
Comment thread src/main/java/org/juv25d/plugin/LoginPlugin.java Outdated
…t`, `Origin`, and `Referer` headers. Update tests to include `Host` and `Origin`.
…ks in `LoginPlugin`. Support case-insensitive username matching and add backwards compatibility to password verification. Upgrade PBKDF2 iteration count and introduce versioned password hashing format.
…LoginPlugin`, `LogoutPlugin`, and `SessionStatusPlugin`.
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (2)
src/main/java/org/juv25d/plugin/LogoutPlugin.java (1)

19-33: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Logout accepts GET → CSRF-via-GET.

Allowing GET lets a malicious page force-invalidate a victim's session with a simple <img src="/logout">. Restrict logout to POST (or require the CSRF token) instead of accepting GET for convenience.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/org/juv25d/plugin/LogoutPlugin.java` around lines 19 - 33,
Update the method validation in LogoutPlugin to accept only POST requests,
removing the GET allowance while preserving the existing 405 response for other
methods. Keep the SID cookie lookup and SessionStore invalidation behavior
unchanged for valid POST requests.
src/main/java/org/juv25d/plugin/LoginPlugin.java (1)

50-58: 🔒 Security & Privacy | 🔴 Critical | 🏗️ Heavy lift

CSRF protection is generated but never enforced.

A CSRF token is issued as a cookie and embedded as _csrf, but the POST path never compares them, and the same-origin check was removed (Line 50). A cross-site page can auto-submit credentials and the 302 will set the victim's SID, silently logging them into the attacker's account. Validate the submitted _csrf against the CSRF-TOKEN cookie (constant-time) before creating the session, or reinstate an Origin/Referer same-origin check that fails closed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/org/juv25d/plugin/LoginPlugin.java` around lines 50 - 58,
Update the POST handling around parseForm in LoginPlugin to enforce CSRF
protection before creating a session: retrieve the submitted _csrf value and
CSRF-TOKEN cookie, compare them using a constant-time method, and reject the
request when either is missing or mismatched. Alternatively, reinstate a
same-origin Origin/Referer check that fails closed; ensure session creation and
the login redirect occur only after validation succeeds.
🧹 Nitpick comments (1)
src/main/resources/static/index.html (1)

28-30: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Prefer a POST form for logout.

This link invokes the state-changing logout handler through GET, allowing cross-site navigations or prefetches to invalidate a user’s session. Make logout POST-only with CSRF protection, or explicitly document this trade-off.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/resources/static/index.html` around lines 28 - 30, Update the
nav-logout markup to submit logout through a POST form instead of the current
GET link, and include the application’s established CSRF protection mechanism.
Preserve the existing hidden styling and logout presentation while targeting the
existing /logout handler.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@config/Users`:
- Line 1: Replace the cleartext sample credential in config/Users at lines 1-1
with a PBKDF2 hash generated by LoginPlugin.hashPassword(...). In
src/main/java/org/juv25d/plugin/LoginPlugin.java at lines 229-236, remove the
plaintext fallback so verification accepts only pbkdf2:-formatted entries and
rejects cleartext passwords.

In `@src/main/java/org/juv25d/filter/SessionAuthFilter.java`:
- Around line 10-14: Clean up imports in SessionAuthFilter by removing the
unused URLDecoder, HashMap, and Map imports, retain StandardCharsets, and apply
the project’s Spotless formatting so import ordering and formatting pass CI.

---

Duplicate comments:
In `@src/main/java/org/juv25d/plugin/LoginPlugin.java`:
- Around line 50-58: Update the POST handling around parseForm in LoginPlugin to
enforce CSRF protection before creating a session: retrieve the submitted _csrf
value and CSRF-TOKEN cookie, compare them using a constant-time method, and
reject the request when either is missing or mismatched. Alternatively,
reinstate a same-origin Origin/Referer check that fails closed; ensure session
creation and the login redirect occur only after validation succeeds.

In `@src/main/java/org/juv25d/plugin/LogoutPlugin.java`:
- Around line 19-33: Update the method validation in LogoutPlugin to accept only
POST requests, removing the GET allowance while preserving the existing 405
response for other methods. Keep the SID cookie lookup and SessionStore
invalidation behavior unchanged for valid POST requests.

---

Nitpick comments:
In `@src/main/resources/static/index.html`:
- Around line 28-30: Update the nav-logout markup to submit logout through a
POST form instead of the current GET link, and include the application’s
established CSRF protection mechanism. Preserve the existing hidden styling and
logout presentation while targeting the existing /logout handler.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aec6d8cc-b187-400e-b045-3bd5a25e80b5

📥 Commits

Reviewing files that changed from the base of the PR and between d3b747c and e8da11a.

📒 Files selected for processing (15)
  • config/Users
  • docs/notes/pipeline-usage.md
  • src/main/java/org/juv25d/Bootstrap.java
  • src/main/java/org/juv25d/auth/Session.java
  • src/main/java/org/juv25d/auth/SessionStore.java
  • src/main/java/org/juv25d/filter/SessionAuthFilter.java
  • src/main/java/org/juv25d/plugin/LoginPlugin.java
  • src/main/java/org/juv25d/plugin/LogoutPlugin.java
  • src/main/java/org/juv25d/plugin/SessionStatusPlugin.java
  • src/main/java/org/juv25d/router/RouterConfig.java
  • src/main/java/org/juv25d/util/CookieUtils.java
  • src/main/resources/static/index.html
  • src/test/java/org/juv25d/filter/SessionAuthFilterTest.java
  • src/test/java/org/juv25d/plugin/LoginPluginTest.java
  • src/test/java/org/juv25d/plugin/LogoutPluginTest.java

Comment thread config/Users
Comment thread src/main/java/org/juv25d/filter/SessionAuthFilter.java Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (3)
src/main/java/org/juv25d/plugin/LogoutPlugin.java (1)

18-28: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Logout still reachable via GET (CSRF-via-GET).

This intentionally keeps GET enabled for logout, but that still means any cross-site page (<img src="/logout">) can force-invalidate a victim's session without consent. This was previously flagged and remains open. If “logout via link” convenience is required, consider requiring POST only and using a JS-driven fetch(..., {method:'POST'}) from the nav link (as done for other authenticated actions) instead of a plain anchor tag.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/org/juv25d/plugin/LogoutPlugin.java` around lines 18 - 28,
Update LogoutPlugin.handle to accept POST only and reject GET requests with the
existing 405 response path. Preserve the current response headers and body for
unsupported methods, and move logout-link convenience to a client-side POST
request rather than retaining GET access.
src/main/java/org/juv25d/plugin/LoginPlugin.java (1)

33-58: 🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

CSRF protection is fully disabled despite the token scaffolding.

The CSRF token is generated, set as a cookie (line 36), and rendered into a hidden form field (line 129), but on POST the _csrf value from parseForm is never read or compared — the comments at lines 50 and 54 explicitly say the same-origin check and CSRF validation are disabled/removed. The previously-flagged isSameOrigin helper no longer exists at all. This is a regression from an already-flagged critical issue: previously there was an imperfect same-origin check, now there is none, so any cross-site page can submit credentials to /login and the resulting 302 will set the victim's session cookie (login CSRF / session fixation via forged submission).

🔒 Suggested fix
         Map<String, String> form = parseForm(req);
-
-        // CSRF-validering är inaktiverad – värden används inte här.
-
+        String csrfCookie = CookieUtils.readCookie(req, "CSRF-TOKEN");
+        String csrfForm = form.getOrDefault("_csrf", "");
+        if (csrfCookie == null || csrfForm.isEmpty() || !MessageDigest.isEqual(
+                csrfCookie.getBytes(StandardCharsets.UTF_8), csrfForm.getBytes(StandardCharsets.UTF_8))) {
+            res.setStatusCode(403);
+            res.setStatusText("Forbidden");
+            renderLoginForm(res, "Invalid or missing CSRF token", generateCsrfToken());
+            return;
+        }
         String username = form.getOrDefault("username", "").trim();

Also applies to: 106-150, 204-208

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/org/juv25d/plugin/LoginPlugin.java` around lines 33 - 58,
Restore CSRF validation in LoginPlugin.handle: on POST, read the submitted _csrf
value from parseForm and compare it with the CSRF token from the request cookie
before processing credentials, rejecting missing or mismatched tokens with the
existing bad-request/error response path. Ensure the GET-generated token remains
available in the hidden form field and cookie, and remove the comments or flow
that explicitly disable validation.
config/Users (1)

1-1: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Plaintext credential handling remains unresolved across config/Users and LoginPlugin.java. The sample file still stores a cleartext password, and the verifier still accepts non-hashed entries; together they let plaintext credentials authenticate, bypassing the PBKDF2 hardening added elsewhere in this file.

  • config/Users#L1-L1: replace lunk:lunk with a PBKDF2 hash produced by LoginPlugin.hashPassword(...).
  • src/main/java/org/juv25d/plugin/LoginPlugin.java#L229-L236: remove the plaintext fallback branch so only pbkdf2:-formatted entries verify, and reject cleartext.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/Users` at line 1, Replace the cleartext credential in config/Users
line 1 with a PBKDF2 hash generated by LoginPlugin.hashPassword(...). In
src/main/java/org/juv25d/plugin/LoginPlugin.java lines 229-236, remove the
plaintext verification fallback so only pbkdf2:-formatted entries are accepted
and cleartext credentials are rejected.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/java/org/juv25d/auth/SessionStore.java`:
- Around line 33-38: Move expired-session cleanup out of the create method’s
only trigger by scheduling cleanupExpired() through the application lifecycle,
using the existing SessionStore ownership boundaries. Ensure the scheduler is
started with the store/application and shut down cleanly, while preserving
immediate cleanup during create if desired. Add coverage proving sessions expire
and are removed without a subsequent login.

In `@src/main/java/org/juv25d/filter/SessionAuthFilter.java`:
- Around line 13-20: Correct the class Javadoc for the authentication filter:
remove the claim that valid sessions expose X-Authenticated and X-User headers,
and add /session/status to the documented public unauthenticated paths. Update
only the documentation near the filter declaration, preserving the
implementation behavior.

---

Duplicate comments:
In `@config/Users`:
- Line 1: Replace the cleartext credential in config/Users line 1 with a PBKDF2
hash generated by LoginPlugin.hashPassword(...). In
src/main/java/org/juv25d/plugin/LoginPlugin.java lines 229-236, remove the
plaintext verification fallback so only pbkdf2:-formatted entries are accepted
and cleartext credentials are rejected.

In `@src/main/java/org/juv25d/plugin/LoginPlugin.java`:
- Around line 33-58: Restore CSRF validation in LoginPlugin.handle: on POST,
read the submitted _csrf value from parseForm and compare it with the CSRF token
from the request cookie before processing credentials, rejecting missing or
mismatched tokens with the existing bad-request/error response path. Ensure the
GET-generated token remains available in the hidden form field and cookie, and
remove the comments or flow that explicitly disable validation.

In `@src/main/java/org/juv25d/plugin/LogoutPlugin.java`:
- Around line 18-28: Update LogoutPlugin.handle to accept POST only and reject
GET requests with the existing 405 response path. Preserve the current response
headers and body for unsupported methods, and move logout-link convenience to a
client-side POST request rather than retaining GET access.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c448ecf3-3b79-469e-ad98-067faa4be818

📥 Commits

Reviewing files that changed from the base of the PR and between d3b747c and aa1cf6f.

📒 Files selected for processing (15)
  • config/Users
  • docs/notes/pipeline-usage.md
  • src/main/java/org/juv25d/Bootstrap.java
  • src/main/java/org/juv25d/auth/Session.java
  • src/main/java/org/juv25d/auth/SessionStore.java
  • src/main/java/org/juv25d/filter/SessionAuthFilter.java
  • src/main/java/org/juv25d/plugin/LoginPlugin.java
  • src/main/java/org/juv25d/plugin/LogoutPlugin.java
  • src/main/java/org/juv25d/plugin/SessionStatusPlugin.java
  • src/main/java/org/juv25d/router/RouterConfig.java
  • src/main/java/org/juv25d/util/CookieUtils.java
  • src/main/resources/static/index.html
  • src/test/java/org/juv25d/filter/SessionAuthFilterTest.java
  • src/test/java/org/juv25d/plugin/LoginPluginTest.java
  • src/test/java/org/juv25d/plugin/LogoutPluginTest.java

Comment thread src/main/java/org/juv25d/auth/SessionStore.java
Comment thread src/main/java/org/juv25d/filter/SessionAuthFilter.java
… tests. Update application lifecycle to manage scheduler startup/shutdown.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/java/org/juv25d/auth/SessionStore.java`:
- Line 99: Update the session access and cleanup paths to serialize
expiry-check-plus-touch with expiry removal per session ID. In the method
handling session refresh (the get/touch flow), use the session map’s per-key
atomic operation so expiration validation and touch occur together; update
safeCleanup to use the same atomic per-key operation when removing expired
sessions, preserving existing behavior for missing or non-expired sessions.

In `@src/test/java/org/juv25d/auth/SessionStoreTest.java`:
- Around line 33-37: Update the cleanup test around store.get(id) to verify
scheduled eviction without triggering lazy eviction: poll the package-private
sessions membership directly until a deadline, asserting the entry is removed,
then optionally retain the get(id) null check. Use short polling intervals and a
bounded timeout to avoid a fixed sleep masking scheduler failures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: bb411582-7023-436e-ade6-b417c8f33217

📥 Commits

Reviewing files that changed from the base of the PR and between e8da11a and 8054e11.

📒 Files selected for processing (5)
  • src/main/java/org/juv25d/App.java
  • src/main/java/org/juv25d/auth/SessionStore.java
  • src/main/java/org/juv25d/filter/SessionAuthFilter.java
  • src/main/java/org/juv25d/plugin/LoginPlugin.java
  • src/test/java/org/juv25d/auth/SessionStoreTest.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/org/juv25d/filter/SessionAuthFilter.java
  • src/main/java/org/juv25d/plugin/LoginPlugin.java

Comment thread src/main/java/org/juv25d/auth/SessionStore.java
Comment thread src/test/java/org/juv25d/auth/SessionStoreTest.java Outdated
@ithsjava25 ithsjava25 deleted a comment from coderabbitai Bot Jul 23, 2026
@ithsjava25 ithsjava25 deleted a comment from coderabbitai Bot Jul 23, 2026
@Linsss123

Copy link
Copy Markdown

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (2)
src/main/java/org/juv25d/plugin/LogoutPlugin.java (1)

18-28: 🔒 Security & Privacy | 🟡 Minor

GET is still accepted for /logout, allowing CSRF-forced logout.

A third-party page (e.g. <img src="/logout">) can force-invalidate a victim's session since GET is explicitly permitted. This was already raised previously and suggested restricting to POST only.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/org/juv25d/plugin/LogoutPlugin.java` around lines 18 - 28,
Update LogoutPlugin.handle to reject GET requests and accept only POST for
/logout. Preserve the existing 405 response construction for unsupported
methods, including GET, while allowing the POST logout flow to continue
unchanged.
src/main/java/org/juv25d/plugin/LoginPlugin.java (1)

50-68: 🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

CSRF protection was built but never wired up — validation is explicitly disabled.

renderLoginForm issues a CSRF-TOKEN cookie and embeds it in a hidden _csrf field, and the login POST parses that field into form, but the comment on Line 54 confirms the submitted _csrf value is never compared against the cookie. The same-origin check that used to guard this endpoint was also removed outright (Line 50). This reopens the exact CSRF vulnerability flagged in a prior review: a cross-site page can auto-submit attacker credentials, and the resulting 302 sets the victim's browser with the attacker's SID cookie, silently logging the victim into the attacker's account.

🔒 Proposed fix: enforce double-submit CSRF check
         Map<String, String> form = parseForm(req);
 
-        // CSRF-validering är inaktiverad – värden används inte här.
+        String csrfCookie = CookieUtils.readCookie(req, "CSRF-TOKEN");
+        String csrfForm = form.getOrDefault("_csrf", "");
+        if (csrfCookie == null || csrfForm.isEmpty()
+                || !MessageDigest.isEqual(
+                        csrfCookie.getBytes(StandardCharsets.UTF_8),
+                        csrfForm.getBytes(StandardCharsets.UTF_8))) {
+            res.setStatusCode(403);
+            res.setStatusText("Forbidden");
+            byte[] body = "Invalid CSRF token".getBytes(StandardCharsets.UTF_8);
+            res.setHeader("Content-Type", "text/plain; charset=UTF-8");
+            res.setHeader("Content-Length", String.valueOf(body.length));
+            res.setBody(body);
+            return;
+        }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/org/juv25d/plugin/LoginPlugin.java` around lines 50 - 68, Wire
CSRF validation into the login POST handler before processing credentials: read
the CSRF cookie, retrieve the submitted `_csrf` value from `form`, and reject
the request when either is missing or they do not match. Restore the same-origin
validation for this endpoint if the existing helper is available, and render the
login form with an error instead of issuing the login redirect or setting a
session.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/java/org/juv25d/plugin/LoginPlugin.java`:
- Around line 71-91: Update the authentication logic in LoginPlugin around
expectedHash and verifyPassword so unknown usernames also invoke PBKDF2
verification using the predefined DUMMY_HASH, while known users continue using
their stored hash. Avoid short-circuiting before verification, then reject
authentication when the username is absent or verification fails.

In `@src/main/resources/static/index.html`:
- Around line 28-30: Replace the logout link in the nav-logout element with a
CSRF-protected POST flow, using the application's existing CSRF token mechanism
and logout endpoint expectations. Update the corresponding client-side/logout
handling so normal user logout submits POST with the token, and ensure GET
navigation cannot trigger logout.

---

Duplicate comments:
In `@src/main/java/org/juv25d/plugin/LoginPlugin.java`:
- Around line 50-68: Wire CSRF validation into the login POST handler before
processing credentials: read the CSRF cookie, retrieve the submitted `_csrf`
value from `form`, and reject the request when either is missing or they do not
match. Restore the same-origin validation for this endpoint if the existing
helper is available, and render the login form with an error instead of issuing
the login redirect or setting a session.

In `@src/main/java/org/juv25d/plugin/LogoutPlugin.java`:
- Around line 18-28: Update LogoutPlugin.handle to reject GET requests and
accept only POST for /logout. Preserve the existing 405 response construction
for unsupported methods, including GET, while allowing the POST logout flow to
continue unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cf9dbf00-2210-410d-b3ac-bc8e55603903

📥 Commits

Reviewing files that changed from the base of the PR and between d3b747c and a9f9556.

📒 Files selected for processing (17)
  • config/Users
  • docs/notes/pipeline-usage.md
  • src/main/java/org/juv25d/App.java
  • src/main/java/org/juv25d/Bootstrap.java
  • src/main/java/org/juv25d/auth/Session.java
  • src/main/java/org/juv25d/auth/SessionStore.java
  • src/main/java/org/juv25d/filter/SessionAuthFilter.java
  • src/main/java/org/juv25d/plugin/LoginPlugin.java
  • src/main/java/org/juv25d/plugin/LogoutPlugin.java
  • src/main/java/org/juv25d/plugin/SessionStatusPlugin.java
  • src/main/java/org/juv25d/router/RouterConfig.java
  • src/main/java/org/juv25d/util/CookieUtils.java
  • src/main/resources/static/index.html
  • src/test/java/org/juv25d/auth/SessionStoreTest.java
  • src/test/java/org/juv25d/filter/SessionAuthFilterTest.java
  • src/test/java/org/juv25d/plugin/LoginPluginTest.java
  • src/test/java/org/juv25d/plugin/LogoutPluginTest.java

Comment thread src/main/java/org/juv25d/plugin/LoginPlugin.java
Comment thread src/main/resources/static/index.html

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/org/juv25d/plugin/LogoutPlugin.java (1)

20-27: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Include the required Allow header on 405 responses.

Clients cannot discover the permitted method from this response. Add Allow: POST.

Proposed fix
         if (!"POST".equalsIgnoreCase(req.method())) {
             res.setStatusCode(405);
             res.setStatusText("Method Not Allowed");
+            res.setHeader("Allow", "POST");
             byte[] body = "Method Not Allowed".getBytes(StandardCharsets.UTF_8);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/org/juv25d/plugin/LogoutPlugin.java` around lines 20 - 27,
Update the non-POST response handling in LogoutPlugin to set an `Allow` header
with the value `POST` alongside the existing 405 response headers, before
returning. Preserve the current status, body, and content headers.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/resources/static/css/styles.css`:
- Around line 34-45: Update the .nav-menu .btn-logout rule to inherit the
surrounding text metrics by explicitly inheriting font-size and line-height,
while preserving its existing font family, weight, and other styles.

---

Outside diff comments:
In `@src/main/java/org/juv25d/plugin/LogoutPlugin.java`:
- Around line 20-27: Update the non-POST response handling in LogoutPlugin to
set an `Allow` header with the value `POST` alongside the existing 405 response
headers, before returning. Preserve the current status, body, and content
headers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0a5324c6-808d-43ba-9bef-9b7f8a5d799a

📥 Commits

Reviewing files that changed from the base of the PR and between a9f9556 and 45da7ba.

📒 Files selected for processing (4)
  • src/main/java/org/juv25d/plugin/LoginPlugin.java
  • src/main/java/org/juv25d/plugin/LogoutPlugin.java
  • src/main/resources/static/css/styles.css
  • src/main/resources/static/index.html
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/resources/static/index.html

Comment thread src/main/resources/static/css/styles.css
…nd improve link styling with inherited `font-size` and `line-height`.
@Linsss123

Copy link
Copy Markdown

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

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.

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.

2 participants