Skip to content

admin auth follow-ups: account-keyed audit/sessions, atomic revocation, drop dev-login change-password#495

Merged
Joey0538 merged 4 commits into
mainfrom
claude/admin-service-portal-m99rqg
Jul 13, 2026
Merged

admin auth follow-ups: account-keyed audit/sessions, atomic revocation, drop dev-login change-password#495
Joey0538 merged 4 commits into
mainfrom
claude/admin-service-portal-m99rqg

Conversation

@Joey0538

@Joey0538 Joey0538 commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Follow-up work after #472 (admin/botplatform backend) and #473 (admin-frontend + chat-frontend) merged.

chat-frontend — remove /dev-login change-password step (e8fec18)

The botplatform POST /api/v1/password/change endpoint was removed in #472 (rotation moves to the bot registration web), so the forced change-password step in the dev-login flow called a dead endpoint.

  • BotLoginPage connects the session directly on a successful login, regardless of requirePasswordChange.
  • Removed the changePassword API wrapper and deleted pages/ChangePasswordPage/.

admin-service — finish account-keying (232b31d)

The user/session endpoints moved to :account in #472; this closes the remaining userId-shaped spots:

  • Audit filter now ?targetAccount= (was ?targetUserId=, which could not match the account-only audit entries written by user.update / user.password.set / session.revoke*).
  • sessionView response now includes account (only roles stays out of the projection).
  • createUser audit records the target by account only, matching the other mutating handlers.
  • admin-frontend audit filter + API types and docs/client-api.md (§9.6/§9.9, SessionView) updated to match.

admin-service — atomic session revocation (1fe2eb9)

Deactivating a user or resetting a password now revokes the account's sessions in the same Mongo transaction as the state change, so a failed revoke can't leave live tokens for a disabled user (or an old credential), and the API never reports success unless both succeeded.

  • UpdateUser (deactivate path) and UpdateUserPassword run the $set + session DeleteMany inside a transaction; non-deactivate updates keep the plain single-doc path.
  • Handlers drop their separate best-effort revoke calls.
  • New pkg/testutil single-node replica-set Mongo helper (MongoDBReplicaSet / EnsureMongoReplicaSet / TerminateMongoReplicaSet), connected with directConnection=true. Only admin-service integration tests use it; the rest of the suite keeps the standalone shared Mongo.

Verification

  • Go: make lint → 0 issues · make test SERVICE=admin-service · make sast-gosec clean.
  • admin-service integration suite runs on the replica-set Mongo, including new atomic-revocation assertions (update_deactivated_revokes_sessions_atomically, revokes_the_account's_sessions_atomically).
  • Frontend: admin-frontend vitest 119/119 + tsc; chat-frontend vitest 681/681 + tsc + vite build.

Not included (separate efforts)

Cross-site fan-out on user create/update, and the bot registration web for password rotation.

🤖 Generated with Claude Code


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Session listings now display the associated account.
    • Audit logs can be filtered by target account.
    • Deactivating an account or changing its password now revokes active sessions atomically.
  • Changes

    • Bot login proceeds directly to the application, even when a password change is required.
    • The in-app forced password-change screen is no longer available.
  • Documentation

    • Updated API documentation for session responses and audit filtering.

claude added 3 commits July 12, 2026 05:10
The botplatform /api/v1/password/change endpoint was removed on the backend;
password rotation now happens in the bot registration web. Drop the forced
change-password step from the /dev-login flow: BotLoginPage connects the session
directly on a successful login regardless of requirePasswordChange, the
changePassword API wrapper is removed, and the ChangePasswordPage is deleted.
…create audit

Follow-up consistency after moving the admin user/session endpoints to account:

- Audit list filter is now `?targetAccount=` (AuditFilter.TargetAccount),
  fixing a gap where the old `?targetUserId=` filter could not match the
  account-only audit entries written by user.update / user.password.set /
  session.revoke*.
- sessionView now includes `account` (only roles stay out of the projection).
- createUser audit records the target by account only, matching the other
  mutating handlers.
- admin-frontend: audit filter input + API client (AuditFilter.targetAccount,
  AdminSession.account) and docs (client-api.md §9.6/§9.9, SessionView) updated
  to match.
…a Mongo transaction

Deactivating a user or resetting their password now revokes the account's
sessions in the same multi-document transaction as the state change, so a
failed revoke can no longer leave live tokens for a disabled user or an
old credential — and the API never reports success unless both succeeded.

- store_mongo: UpdateUser (deactivate path) and UpdateUserPassword run the
  $set + session DeleteMany inside a transaction (new withTransaction helper);
  non-deactivate updates keep the plain single-doc path.
- handler: drop the separate best-effort DeleteSessionsByAccount calls.
- testutil: add a single-node replica-set Mongo helper (MongoDBReplicaSet /
  EnsureMongoReplicaSet / TerminateMongoReplicaSet), connected with
  directConnection=true so transactions work from the host. admin-service
  integration tests run on it; the rest of the suite keeps the standalone
  shared Mongo.
- integration tests assert sessions are revoked atomically on both paths.
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Joey0538, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 45 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d2cfb7e6-90af-4f85-adbd-4f38e8ab6553

📥 Commits

Reviewing files that changed from the base of the PR and between 1fe2eb9 and d20bbca.

📒 Files selected for processing (2)
  • admin-service/store_mongo.go
  • pkg/testutil/mongo_replicaset.go
📝 Walkthrough

Walkthrough

Admin audit filters now use account names, session responses expose accounts, and user deactivation/password updates revoke sessions atomically through MongoDB transactions. Bot login connects immediately without a password-change step. Integration tests use a MongoDB replica set.

Changes

Admin services and console

Layer / File(s) Summary
Audit and session contracts
admin-frontend/src/api/admin/*, admin-frontend/src/components/AuditView/*, admin-service/handler.go, admin-service/store.go, admin-service/store_mongo.go, admin-service/*_test.go, docs/client-api.md
Audit filtering now uses targetAccount; session projections include account; frontend wiring, tests, and API documentation match the updated contract.
Atomic session revocation
admin-service/store_mongo.go, admin-service/handler.go, admin-service/handler_test.go, admin-service/integration_test.go
Deactivation and password updates revoke account sessions within MongoDB transactions, with handlers and tests updated accordingly.
Replica-set integration support
pkg/testutil/mongo_replicaset.go, pkg/testutil/terminate.go, admin-service/integration_test.go
Integration tests use isolated MongoDB replica-set databases and shared startup and teardown helpers.

Chat bot authentication

Layer / File(s) Summary
Immediate bot login flow
chat-frontend/src/api/auth/botAuth.js, chat-frontend/src/api/auth/botAuth.test.js, chat-frontend/src/pages/BotLoginPage/*, chat-frontend/src/pages/ChangePasswordPage/*
The bot login flow connects immediately after authentication; the password-change helper, form, export, and related tests were removed.

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

Sequence Diagram(s)

sequenceDiagram
  participant AdminHandler
  participant storeMongo
  participant MongoDB
  AdminHandler->>storeMongo: Update user or password
  storeMongo->>MongoDB: Update account in transaction
  storeMongo->>MongoDB: Revoke account sessions
  MongoDB-->>storeMongo: Return transaction result
  storeMongo-->>AdminHandler: Return operation result
Loading

Possibly related PRs

  • hmchangw/chat#208: Updates the shared Mongo test-container lifecycle used by the replica-set teardown changes.
  • hmchangw/chat#472: Introduces related admin-service and authentication portal surfaces.
  • hmchangw/chat#473: Introduces the admin console and audit-view surfaces updated here.

Suggested reviewers: mliu33, hmchangw

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: account-keyed admin audit/sessions, atomic revocation, and removal of the dev-login password-change flow.
Docstring Coverage ✅ Passed Docstring coverage is 90.00% which is sufficient. The required threshold is 80.00%.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/admin-service-portal-m99rqg

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: 1

Caution

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

⚠️ Outside diff range comments (1)
admin-service/store_mongo.go (1)

330-340: 🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

Add an index for audit targetAccount lookups.
ListAudit now filters on targetAccount, but the only audit-specific index is still {targetUserId, timestamp}. The current audit write paths leave targetUserID empty, so that index no longer helps these queries; add a {siteId, targetAccount, timestamp} index here.

🤖 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 `@admin-service/store_mongo.go` around lines 330 - 340, Add a MongoDB audit
index covering siteId, targetAccount, and timestamp alongside the existing audit
indexes, so ListAudit targetAccount queries use the appropriate compound index.
Update the audit index initialization or migration logic rather than changing
ListAudit’s filter behavior.
🧹 Nitpick comments (2)
pkg/testutil/mongo_replicaset.go (2)

91-92: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Switch the pkg/testutil cleanup logs to slog. The same fmt.Fprintf(os.Stderr, ...) pattern appears in the other terminate helpers too, so this is better handled as a small package-wide cleanup than a one-off change.

🤖 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 `@pkg/testutil/mongo_replicaset.go` around lines 91 - 92, Replace the
fmt.Fprintf(os.Stderr) cleanup logging in the mongo replica-set test utilities,
including the Disconnect path and other terminate helpers, with the package’s
slog-based logging. Preserve each existing error message and cleanup behavior
while applying the change consistently across pkg/testutil.

Source: Coding guidelines


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

Use mongoutil.Connect here instead of mongo.Connect — it already accepts the rewritten URI and keeps the ping/logging behavior consistent with the rest of the Mongo helpers.

🤖 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 `@pkg/testutil/mongo_replicaset.go` at line 59, In the connection setup around
the mongo client variable, replace mongo.Connect with mongoutil.Connect while
preserving the existing rewritten directURI and error handling. Use the helper’s
established ping and logging behavior without changing surrounding replica-set
setup.

Source: Coding guidelines

🤖 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 `@pkg/testutil/mongo_replicaset.go`:
- Line 44: Document each intentionally discarded error at the `_ =
container.Terminate(ctx)` calls in the Mongo replica-set test utility, including
the occurrences near lines 44, 55, 61, and 123. Add concise comments explaining
why termination errors are intentionally ignored, without changing the cleanup
behavior.

---

Outside diff comments:
In `@admin-service/store_mongo.go`:
- Around line 330-340: Add a MongoDB audit index covering siteId, targetAccount,
and timestamp alongside the existing audit indexes, so ListAudit targetAccount
queries use the appropriate compound index. Update the audit index
initialization or migration logic rather than changing ListAudit’s filter
behavior.

---

Nitpick comments:
In `@pkg/testutil/mongo_replicaset.go`:
- Around line 91-92: Replace the fmt.Fprintf(os.Stderr) cleanup logging in the
mongo replica-set test utilities, including the Disconnect path and other
terminate helpers, with the package’s slog-based logging. Preserve each existing
error message and cleanup behavior while applying the change consistently across
pkg/testutil.
- Line 59: In the connection setup around the mongo client variable, replace
mongo.Connect with mongoutil.Connect while preserving the existing rewritten
directURI and error handling. Use the helper’s established ping and logging
behavior without changing surrounding replica-set 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 42cb1885-3429-41cf-8bd7-d7900cf637bb

📥 Commits

Reviewing files that changed from the base of the PR and between 06dd3b2 and 1fe2eb9.

📒 Files selected for processing (20)
  • admin-frontend/src/api/admin/admin.test.ts
  • admin-frontend/src/api/admin/index.ts
  • admin-frontend/src/components/AuditView/AuditView.jsx
  • admin-frontend/src/components/AuditView/AuditView.test.jsx
  • admin-service/handler.go
  • admin-service/handler_test.go
  • admin-service/integration_test.go
  • admin-service/store.go
  • admin-service/store_mongo.go
  • chat-frontend/src/api/auth/botAuth.js
  • chat-frontend/src/api/auth/botAuth.test.js
  • chat-frontend/src/pages/BotLoginPage/BotLoginPage.jsx
  • chat-frontend/src/pages/BotLoginPage/BotLoginPage.test.jsx
  • chat-frontend/src/pages/ChangePasswordPage/ChangePasswordForm.jsx
  • chat-frontend/src/pages/ChangePasswordPage/ChangePasswordForm.test.jsx
  • chat-frontend/src/pages/ChangePasswordPage/index.jsx
  • chat-frontend/src/pages/ChangePasswordPage/style.css
  • docs/client-api.md
  • pkg/testutil/mongo_replicaset.go
  • pkg/testutil/terminate.go
💤 Files with no reviewable changes (5)
  • chat-frontend/src/pages/ChangePasswordPage/style.css
  • chat-frontend/src/pages/ChangePasswordPage/index.jsx
  • chat-frontend/src/pages/ChangePasswordPage/ChangePasswordForm.jsx
  • chat-frontend/src/api/auth/botAuth.js
  • chat-frontend/src/pages/ChangePasswordPage/ChangePasswordForm.test.jsx

Comment thread pkg/testutil/mongo_replicaset.go Outdated
@julianshen

julianshen commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Code Review

⚠️ Rules that failed

The following rules failed to run and were skipped:

  • opencode-review

… test helper

Addresses CodeRabbit review on #495:

- Replace the now-dead {targetUserId, timestamp} admin_audit index with
  {siteId, targetAccount, timestamp}, backing the ListAudit targetAccount
  filter (audit entries are keyed by account, not internal user ID).
- Document the intentionally-discarded errors on the best-effort
  container.Terminate / db.Drop calls in the replica-set test helper.

Skipped (mirror the existing pkg/testutil/mongo.go on purpose): the slog and
mongoutil.Connect nitpicks — matching the sibling standalone helper; a
package-wide change is out of scope here.

@GITMateuszCharczuk GITMateuszCharczuk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM!

@Joey0538 Joey0538 merged commit 74ab979 into main Jul 13, 2026
6 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.

4 participants