Skip to content

Standarized the API Response in Dashboard API-Middleware#299

Merged
yash-pouranik merged 4 commits into
geturbackend:mainfrom
Ayush4958:pr-dashboard-middleware
Jun 11, 2026
Merged

Standarized the API Response in Dashboard API-Middleware#299
yash-pouranik merged 4 commits into
geturbackend:mainfrom
Ayush4958:pr-dashboard-middleware

Conversation

@Ayush4958

@Ayush4958 Ayush4958 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

🚀 Pull Request Description

I had added AppError and AppResponse Utility to entire backend's middleware of Dashboard API which provide a standard way to operate. Migrated raw JSON response with standard utility.

Fixes #237

🛠️ Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📝 Documentation update
  • 🎨 UI/UX improvement (Frontend only)
  • ⚙️ Refactor / Chore

🧪 Testing & Validation

Backend Verification:

  • I have run npm test in the backend/ directory and all tests passed.
  • I have verified the API endpoints using Postman/Thunder Client.
  • New unit tests have been added (if applicable).

Frontend Verification:

  • I have run npm run lint in the frontend/ directory.
  • Verified the UI changes on different screen sizes (Responsive).
  • Checked for any console errors in the browser dev tools.

📸 Screenshots / Recordings (Optional)

✅ Checklist

  • My code follows the code style of this project.
  • I have performed a self-review of my code.
  • I have commented my code, particularly in hard-to-understand areas.
  • My changes generate no new warnings or errors.
  • I have updated the documentation (README/Docs) accordingly.

Summary by CodeRabbit

  • Refactor
    • Standardized error propagation across authentication, rate-limiting, and project-loading so failures now surface via consistent error objects with appropriate HTTP status codes and clear messages.
  • Tests
    • Updated and added tests to cover the new error flows and verify behavior for authentication, rate-limit, and project-loading scenarios.

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d179de3e-f304-45ec-b26e-292864ff21bb

📥 Commits

Reviewing files that changed from the base of the PR and between 651a4ea and 348a298.

📒 Files selected for processing (2)
  • apps/dashboard-api/src/__tests__/loadProjectForAdmin.test.js
  • apps/dashboard-api/src/middlewares/loadProjectForAdmin.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/dashboard-api/src/middlewares/loadProjectForAdmin.js
  • apps/dashboard-api/src/tests/loadProjectForAdmin.test.js

📝 Walkthrough

Walkthrough

Five dashboard-api middleware files and their tests were updated to import AppError from @urbackend/common and delegate errors via next(new AppError(...)) instead of returning HTTP JSON; tests now mock AppError and assert error delegation and payload fields.

Changes

AppError Adoption Across Dashboard Middlewares

Layer / File(s) Summary
authMiddleware AppError adoption
apps/dashboard-api/src/middlewares/authMiddleware.js, apps/dashboard-api/src/__tests__/authMiddleware.test.js
authMiddleware imports AppError and delegates 401 errors (missing/malformed token) and JWT verification failures via next(new AppError(...)). Tests mock AppError, assert next is called with AppError-like objects, and validate statusCode/message fields.
auth_limiter AppError adoption
apps/dashboard-api/src/middlewares/auth_limiter.js, apps/dashboard-api/src/__tests__/auth_limiter.test.js
authLimiter and publicLimiter replace static message responses with handler functions that call next(new AppError(429, ...)). Tests consolidate Express setup into createTestApp() and assert AppError-based error handling and standard rate-limit headers.
loadProjectForAdmin AppError adoption
apps/dashboard-api/src/middlewares/loadProjectForAdmin.js, apps/dashboard-api/src/__tests__/loadProjectForAdmin.test.js
loadProjectForAdmin imports AppError and delegates missing projectId (400), not-found/unauthorized (404), and caught exceptions via next(...). On success it assigns req.project and calls next(). Tests cover missing ID, not-found, and success paths.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant authLimiter
  participant authMiddleware
  participant jwt
  participant ExpressErrorHandler

  Client->>authLimiter: incoming request (rate-limited)
  authLimiter-->>ExpressErrorHandler: next(new AppError(429, "Too many requests")) (on breach)
  Client->>authMiddleware: request with Authorization/cookie
  authMiddleware->>jwt: jwt.verify(token)
  jwt-->>authMiddleware: throws (expired/invalid) or returns payload
  alt jwt throws
    authMiddleware->>ExpressErrorHandler: next(new AppError(401, "Invalid Token"))
  else valid token
    authMiddleware->>authMiddleware: attach user -> next()
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

GSSOC'26, level:intermediate, quality:clean, type:refactor, mentor:yash-pouranik

Suggested reviewers

  • yash-pouranik
  • Nitin-kumar-yadav1307

🐰 A rabbit hops through middleware code,
Passing AppError like a tidy ode,
next() leads the way, errors no longer stay,
Tests mock and check each hop on the road,
Hooray — clean flows lighten the load.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR implements AppError-based error propagation via next() but does not modify the specified middleware files (authorizeReadOperation.js, verifyApiKey.js) from issue #237, nor implements the full standardized response structure {success, error, message}. Either update the remaining middleware files listed in issue #237 (authorizeReadOperation.js, verifyApiKey.js) to match the standardization approach, or clarify scope alignment with issue #237 requirements.
Title check ❓ Inconclusive The PR title mentions 'Standarized' (misspelled 'Standardized'), but the scope focuses on AppError-based error handling rather than the full response schema standardization described in issue #237. Clarify whether the title should reference 'error handling standardization' or update to reflect the complete response structure changes including both error and success responses.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Out of Scope Changes check ✅ Passed All code changes are directly related to implementing error handling standardization through AppError across dashboard middleware files, with corresponding test updates.
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

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
apps/dashboard-api/src/__tests__/authMiddleware.test.js (1)

163-165: ⚡ Quick win

Update expected statusCode when middleware is corrected.

These tests assert statusCode 400 for JWT verification failures, matching the current implementation. When the middleware is updated to use 401 for authentication failures (as suggested in the middleware review), update these assertions to expect 401.

📝 Future update needed
-            expect(next.mock.calls[0][0].statusCode).toBe(400);
+            expect(next.mock.calls[0][0].statusCode).toBe(401);

Also applies to: 178-180

🤖 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 `@apps/dashboard-api/src/__tests__/authMiddleware.test.js` around lines 163 -
165, Update the test assertions that currently expect a 400 statusCode for JWT
verification failures to expect 401 instead: change the assertions that inspect
next.mock.calls[0][0].statusCode (and the identical assertions at the other
block) so they assert 401 when the middleware returns an AppError for
authentication failure; leave the AppError and message checks unchanged.
apps/dashboard-api/src/__tests__/auth_limiter.test.js (1)

80-80: 💤 Low value

Consider asserting the full response shape.

The assertion now only checks blocked.body.message instead of the full response object. While this is sufficient for verifying the rate-limit behavior, asserting the complete response shape (including success: false and error fields) would provide stronger validation of the error handler's output format.

🔍 Optional enhancement
+            expect(blocked.body).toEqual({
+                success: false,
+                error: 'Error',
+                message: 'Too many attempts. Please try again in 15 minutes.'
+            });
-            expect(blocked.body.message).toBe('Too many attempts. Please try again in 15 minutes.');
🤖 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 `@apps/dashboard-api/src/__tests__/auth_limiter.test.js` at line 80, Update the
assertion in the auth limiter test so it checks the entire response body shape
returned when rate-limited (the `blocked` response), not just
`blocked.body.message`; assert that `blocked.body` includes `success: false`,
the `message: 'Too many attempts. Please try again in 15 minutes.'`, and an
`error` field (or appropriate error details) to validate the error handler
output format in this test (look for the `blocked` variable in
apps/dashboard-api/src/__tests__/auth_limiter.test.js).
🤖 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 `@apps/dashboard-api/src/middlewares/authMiddleware.js`:
- Line 39: Replace the 400 status used for JWT verification failures with 401 in
the auth middleware: locate the return new AppError(...) call in authMiddleware
(the line that currently does return next(new AppError(400, 'Invalid Token'))),
and change the status code argument from 400 to 401 so token verification errors
produce HTTP 401 Unauthorized while keeping the existing error message and flow.
- Line 2: Locate the auth middleware where JWT verification uses the imported
AppError (symbol: AppError) and replace any instantiation that returns new
AppError(400, 'Invalid Token') with a 401 status (e.g., new AppError(401,
'Invalid Token') or new AppError(401, 'Unauthorized')) so JWT verification
failures return the correct HTTP Unauthorized status; ensure the same change is
applied for expired or otherwise invalid credential errors in the middleware
(look for functions handling token verification/verification callbacks).

In `@apps/dashboard-api/src/middlewares/loadProjectForAdmin.js`:
- Around line 5-20: Add unit tests for the loadProjectForAdmin middleware to
cover the three behaviors: when req.params.projectId is missing it should call
next with an AppError(400); when Project.findOne returns null it should call
next with an AppError(404); and when Project.findOne returns a project it should
set req.project and call next without an error. In tests stub/mock the Project
model's findOne to return null or a project, provide fake req/res objects and a
spy for next, and assert next was called with the expected AppError instance for
the error cases and that req.project equals the returned project for the success
case; also restore mocks between tests.

---

Nitpick comments:
In `@apps/dashboard-api/src/__tests__/auth_limiter.test.js`:
- Line 80: Update the assertion in the auth limiter test so it checks the entire
response body shape returned when rate-limited (the `blocked` response), not
just `blocked.body.message`; assert that `blocked.body` includes `success:
false`, the `message: 'Too many attempts. Please try again in 15 minutes.'`, and
an `error` field (or appropriate error details) to validate the error handler
output format in this test (look for the `blocked` variable in
apps/dashboard-api/src/__tests__/auth_limiter.test.js).

In `@apps/dashboard-api/src/__tests__/authMiddleware.test.js`:
- Around line 163-165: Update the test assertions that currently expect a 400
statusCode for JWT verification failures to expect 401 instead: change the
assertions that inspect next.mock.calls[0][0].statusCode (and the identical
assertions at the other block) so they assert 401 when the middleware returns an
AppError for authentication failure; leave the AppError and message checks
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: defaults

Review profile: CHILL

Plan: Pro

Run ID: a43b248f-f47b-4297-a96d-1e30303a78d1

📥 Commits

Reviewing files that changed from the base of the PR and between b6e59ab and 38e5864.

📒 Files selected for processing (5)
  • apps/dashboard-api/src/__tests__/authMiddleware.test.js
  • apps/dashboard-api/src/__tests__/auth_limiter.test.js
  • apps/dashboard-api/src/middlewares/authMiddleware.js
  • apps/dashboard-api/src/middlewares/auth_limiter.js
  • apps/dashboard-api/src/middlewares/loadProjectForAdmin.js

Comment thread apps/dashboard-api/src/middlewares/authMiddleware.js
Comment thread apps/dashboard-api/src/middlewares/authMiddleware.js Outdated
Comment thread apps/dashboard-api/src/middlewares/loadProjectForAdmin.js

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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)
apps/dashboard-api/src/middlewares/authMiddleware.js (1)

34-39: ⚠️ Potential issue | 🟠 Major

Map only JWT validation errors to 401 Invalid Token
The catch block currently converts every jwt.verify failure into a 401, masking operational/config issues (e.g., missing/invalid JWT_SECRET, which typically won’t be one of jsonwebtoken’s token-validation error names). Restrict 401 to jsonwebtoken validation/expiration errors (JsonWebTokenError, TokenExpiredError, NotBeforeError) and forward everything else with next(err).

🔧 Proposed fix
     } catch (err) {
         if (process.env.NODE_ENV !== 'test') {
             console.error(err);
         }

-        return next(new AppError(401, 'Invalid Token'));
+        if (
+            err?.name === 'JsonWebTokenError' ||
+            err?.name === 'TokenExpiredError' ||
+            err?.name === 'NotBeforeError'
+        ) {
+            return next(new AppError(401, 'Invalid Token'));
+        }
+        return next(err);
     }
 };
🤖 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 `@apps/dashboard-api/src/middlewares/authMiddleware.js` around lines 34 - 39,
The catch block in your auth middleware is turning every error into a 401;
update the catch in the function that calls jwt.verify (the auth middleware
around jwt.verify) to only map jsonwebtoken validation errors to a new
AppError(401, 'Invalid Token') by checking err.name against 'JsonWebTokenError',
'TokenExpiredError', and 'NotBeforeError'; for any other errors (e.g.,
missing/invalid JWT_SECRET or unexpected runtime errors) call next(err) to
propagate the original error instead (you may keep the existing non-test
console.error line for logging).
🧹 Nitpick comments (1)
apps/dashboard-api/src/__tests__/loadProjectForAdmin.test.js (1)

45-70: ⚡ Quick win

Add coverage for the catch -> next(err) branch in the middleware.

This suite validates three primary paths, but it does not assert behavior when Project.findOne rejects. A small test here prevents regressions in error forwarding.

➕ Suggested test case
     it('should set req.project and call next without error if project is found', async () => {
         req.params.projectId = 'proj123';
         const mockProject = { _id: 'proj123', name: 'Test Project' };
         Project.findOne.mockResolvedValueOnce(mockProject);

         await loadProjectForAdmin(req, res, next);

         expect(Project.findOne).toHaveBeenCalledWith({ _id: 'proj123', owner: 'user123' });
         expect(req.project).toEqual(mockProject);
         expect(next).toHaveBeenCalledTimes(1);
         expect(next).toHaveBeenCalledWith();
     });
+
+    it('should forward unexpected errors via next(err)', async () => {
+        req.params.projectId = 'proj123';
+        const dbError = new Error('db failure');
+        Project.findOne.mockRejectedValueOnce(dbError);
+
+        await loadProjectForAdmin(req, res, next);
+
+        expect(next).toHaveBeenCalledTimes(1);
+        expect(next).toHaveBeenCalledWith(dbError);
+    });
 });
🤖 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 `@apps/dashboard-api/src/__tests__/loadProjectForAdmin.test.js` around lines 45
- 70, Add a test that covers the error branch by making Project.findOne reject
(e.g., mockRejectedValueOnce(new Error('db'))), call loadProjectForAdmin(req,
res, next), and assert that next was called once with the original error
(expect(next).toHaveBeenCalledWith(expect.any(Error))) and that req.project is
not set; reference the loadProjectForAdmin middleware, Project.findOne mock, and
the next callback when adding this case.
🤖 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 `@apps/dashboard-api/src/__tests__/loadProjectForAdmin.test.js`:
- Around line 3-4: Move the jest.mock('`@urbackend/common`') call so it runs
before any require of '`@urbackend/common`' or the middleware; specifically, place
jest.mock('`@urbackend/common`') at the top of the test file before you require
Project or loadProjectForAdmin, then require Project and loadProjectForAdmin
after the mock is declared (optionally use jest.resetModules() in beforeEach if
tests need a clean module cache). This ensures the mock for '`@urbackend/common`'
is active when loadProjectForAdmin (which imports that module at module load
time) is required.

---

Outside diff comments:
In `@apps/dashboard-api/src/middlewares/authMiddleware.js`:
- Around line 34-39: The catch block in your auth middleware is turning every
error into a 401; update the catch in the function that calls jwt.verify (the
auth middleware around jwt.verify) to only map jsonwebtoken validation errors to
a new AppError(401, 'Invalid Token') by checking err.name against
'JsonWebTokenError', 'TokenExpiredError', and 'NotBeforeError'; for any other
errors (e.g., missing/invalid JWT_SECRET or unexpected runtime errors) call
next(err) to propagate the original error instead (you may keep the existing
non-test console.error line for logging).

---

Nitpick comments:
In `@apps/dashboard-api/src/__tests__/loadProjectForAdmin.test.js`:
- Around line 45-70: Add a test that covers the error branch by making
Project.findOne reject (e.g., mockRejectedValueOnce(new Error('db'))), call
loadProjectForAdmin(req, res, next), and assert that next was called once with
the original error (expect(next).toHaveBeenCalledWith(expect.any(Error))) and
that req.project is not set; reference the loadProjectForAdmin middleware,
Project.findOne mock, and the next callback when adding this case.
🪄 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: 540cb9d0-347c-45be-bca5-533236d7519d

📥 Commits

Reviewing files that changed from the base of the PR and between 38e5864 and 651a4ea.

📒 Files selected for processing (4)
  • apps/dashboard-api/src/__tests__/authMiddleware.test.js
  • apps/dashboard-api/src/__tests__/loadProjectForAdmin.test.js
  • apps/dashboard-api/src/middlewares/authMiddleware.js
  • apps/dashboard-api/src/middlewares/loadProjectForAdmin.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/dashboard-api/src/middlewares/loadProjectForAdmin.js
  • apps/dashboard-api/src/tests/authMiddleware.test.js

Comment thread apps/dashboard-api/src/__tests__/loadProjectForAdmin.test.js Outdated
@Ayush4958

Copy link
Copy Markdown
Contributor Author

@yash-pouranik ,
This PR is ready for review

@yash-pouranik

Copy link
Copy Markdown
Collaborator

one coderabbitai
comment is still open
@Ayush4958

@Ayush4958

Copy link
Copy Markdown
Contributor Author

@yash-pouranik , It's fixed but
Code Rabbit Bot didn't resolved it though

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

cool now everything looks perfect.

@yash-pouranik yash-pouranik merged commit 92b871f into geturbackend:main Jun 11, 2026
8 checks passed
@Ayush4958

Copy link
Copy Markdown
Contributor Author

@yash-pouranik
U forgot to add labels

@yash-pouranik

Copy link
Copy Markdown
Collaborator

yh

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Standardize Error Response Schemas Across All Middlewares

2 participants