Skip to content

Conversation

@JoshuaSBrown
Copy link
Collaborator

@JoshuaSBrown JoshuaSBrown commented Dec 5, 2025

Ticket

Description

How Has This Been Tested?

Artifacts (if appropriate):

Tasks

  • - A description of the PR has been provided, and a diagram included if it is a new feature.
  • - Formatter has been run
  • - CHANGELOG comment has been added
  • - Labels have been assigned to the pr
  • - A reviwer has been added
  • - A user has been assigned to work on the pr
  • - If new feature a unit test has been added

Summary by Sourcery

Refine the user token expiring lookup endpoint logging and response handling.

Enhancements:

  • Standardize request logging for the expiring user token endpoint using the client from query parameters and a shared description string.
  • Adjust the expiring token query handling to store results locally, send them in the response, and log only the count of expiring tokens instead of the full result set for success and failure paths.

@JoshuaSBrown JoshuaSBrown self-assigned this Dec 5, 2025
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Dec 5, 2025

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Refactors the GET /token/get/expiring route to use query param–based client identification, improves logging descriptions, and standardizes success/failure log metadata including an aggregated count of expiring tokens.

Sequence diagram for refactored GET /token/get/expiring route

sequenceDiagram
    actor Client
    participant UserRouter
    participant Logger
    participant Database
    participant Response

    Client->>UserRouter: GET /token/get/expiring?expires_in&client
    Note over UserRouter: Build desc = "User access tokens expiring in {expires_in} seconds"

    UserRouter->>Logger: logRequestStarted(client=req.queryParams.client, correlationId, httpVerb=GET, routePath=/token/get/expiring, status=Started, description=desc)

    alt Successful query
        UserRouter->>Database: _query(exp = now_in_seconds + expires_in)
        Database-->>UserRouter: results (cursor)
        UserRouter->>UserRouter: extra_log_info = results.toArray()
        UserRouter-->>Response: send(results)

        UserRouter->>Logger: logRequestSuccess(client=req.queryParams.client, correlationId, httpVerb=GET, routePath=/token/get/expiring, status=Success, description=desc, extra={expiring_token_count: extra_log_info.length})
    else Query or processing error
        UserRouter->>Logger: logRequestFailure(client=req.queryParams.client, correlationId, httpVerb=GET, routePath=/token/get/expiring, status=Failure, description=desc, extra={expiring_token_count: extra_log_info.length}, error=e)
        UserRouter-->>Response: handleException(e)
    end
Loading

File-Level Changes

Change Details Files
Refactor the expiring user access tokens route to rely on request query parameters and improve logging metadata.
  • Remove unused local variables and use req.queryParams.client directly as the logged client identifier.
  • Introduce a shared desc string that describes the operation using the expires_in query parameter and reuse it across all logs.
  • Ensure the database query result is stored in a const results variable and still returned via res.send(results).
  • Materialize the cursor into an array for logging purposes and log only the count of expiring tokens instead of the entire result set on success and failure.
  • Align success and failure logger calls to use the same route path, description, and extra shape, while keeping correlation ID and HTTP verb consistent.
core/database/foxx/api/user_router.js

Possibly linked issues

  • #N/A: PR refactors the expiring token route, replacing undefined client usage with req.queryParams.client and improving logging.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • Calling results.toArray() for logging after res.send(results) may consume the cursor and change what the client receives; consider either sending the array (and logging its length) or using a cheap count-only query/log field instead.
  • If expires_in is required for this route, it would be safer to validate and coerce req.queryParams.expires_in to a number up front and fail fast on missing/invalid values rather than interpolating it directly into the description and query parameter.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Calling `results.toArray()` for logging after `res.send(results)` may consume the cursor and change what the client receives; consider either sending the array (and logging its length) or using a cheap count-only query/log field instead.
- If `expires_in` is required for this route, it would be safer to validate and coerce `req.queryParams.expires_in` to a number up front and fail fast on missing/invalid values rather than interpolating it directly into the description and query parameter.

## Individual Comments

### Comment 1
<location> `core/database/foxx/api/user_router.js:1163-1170` </location>
<code_context>
             });

-            results = g_db._query(
+            const results = g_db._query(
                 "for i in u filter i.expiration != Null && i.expiration < @exp return {id:i._id,access:i.access,refresh:i.refresh,expiration:i.expiration}",
                 {
                     exp: Math.floor(Date.now() / 1000) + req.queryParams.expires_in,
                 },
             );
             res.send(results);
+            extra_log_info = results.toArray();
             logger.logRequestSuccess({
-                client: client?._id,
</code_context>

<issue_to_address>
**issue (bug_risk):** Avoid consuming the query cursor twice; materialize once before sending the response.

The handler sends the cursor directly with `res.send(results);` and then calls `results.toArray();`. If Foxx consumes the cursor during serialization, `toArray()` may fail or return an empty array, causing `expiring_token_count` logs to diverge from the actual response. To avoid this, materialize once and reuse:

```js
const cursor = g_db._query(/* ... */);
const results = cursor.toArray();
res.send(results);
extra_log_info = results;
```

This keeps the response and logging consistent and avoids double-consuming the cursor.
</issue_to_address>

### Comment 2
<location> `core/database/foxx/api/user_router.js:1155` </location>
<code_context>
         try {
             logger.logRequestStarted({
-                client: user?._id,
+                client: req.queryParams.client,
                 correlationId: req.headers["x-correlation-id"],
                 httpVerb: "GET",
</code_context>

<issue_to_address>
**🚨 issue (security):** Logging `client` from a request query param may allow spoofed client identifiers.

Using `req.queryParams.client` lets any caller spoof the logged client id, which can corrupt audit trails. If `client` should reflect an authenticated user or trusted client, use an identifier from the auth context (e.g., user id, token subject, validated client id) or validate/normalize the query param before logging it.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +1163 to +1170
const results = g_db._query(
"for i in u filter i.expiration != Null && i.expiration < @exp return {id:i._id,access:i.access,refresh:i.refresh,expiration:i.expiration}",
{
exp: Math.floor(Date.now() / 1000) + req.queryParams.expires_in,
},
);
res.send(results);
extra_log_info = results.toArray();
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (bug_risk): Avoid consuming the query cursor twice; materialize once before sending the response.

The handler sends the cursor directly with res.send(results); and then calls results.toArray();. If Foxx consumes the cursor during serialization, toArray() may fail or return an empty array, causing expiring_token_count logs to diverge from the actual response. To avoid this, materialize once and reuse:

const cursor = g_db._query(/* ... */);
const results = cursor.toArray();
res.send(results);
extra_log_info = results;

This keeps the response and logging consistent and avoids double-consuming the cursor.

try {
logger.logRequestStarted({
client: user?._id,
client: req.queryParams.client,
Copy link
Contributor

Choose a reason for hiding this comment

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

🚨 issue (security): Logging client from a request query param may allow spoofed client identifiers.

Using req.queryParams.client lets any caller spoof the logged client id, which can corrupt audit trails. If client should reflect an authenticated user or trusted client, use an identifier from the auth context (e.g., user id, token subject, validated client id) or validate/normalize the query param before logging it.

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.

[Refactor] - Foxx, there is a bug in the user router /usr/token/get

2 participants