feat: add applicant image upload functionality#2564
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughA new application picture upload feature is added, including error message constants, Cloudinary configuration, a POST endpoint with file validation middleware, image service integration for Cloudinary uploads, and comprehensive test coverage for both success and failure scenarios. Changes
Sequence DiagramsequenceDiagram
participant Client
participant Router
participant Authenticate as Auth Middleware
participant ValidatePic as Validator Middleware
participant Controller
participant ImageService
participant Cloudinary
Client->>Router: POST /applications/picture (file, auth token)
Router->>Authenticate: Check authentication
Authenticate->>Router: User verified
Router->>ValidatePic: Validate file
ValidatePic->>ValidatePic: Check file presence & MIME type
ValidatePic->>Router: Validation passed
Router->>Controller: Forward request
Controller->>ImageService: uploadApplicationImage({file, userId})
ImageService->>ImageService: Encode to Base64 Data URI
ImageService->>Cloudinary: Upload with public_id
Cloudinary-->>ImageService: Return publicId & URL
ImageService-->>Controller: Return {publicId, url}
Controller-->>Client: 201 Created {message, image}
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
@coderabbitai review bro |
|
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@routes/applications.ts`:
- Around line 19-25: The POST /picture route lacks rate limiting—add the
existing commonRateLimiter middleware into the router.post middleware chain
before the upload handler so requests hit rate limits; specifically update the
router.post call that currently lists authenticate, upload.single("profile"),
applicationValidator.validateApplicationPicture, and
applications.postUserPicture to include commonRateLimiter (imported from
middlewares/rateLimiting.js) in the middleware sequence (e.g., after
authenticate and before upload.single) so the route uses commonRateLimiter and
still calls applicationValidator.validateApplicationPicture and
applications.postUserPicture.
In `@test/integration/application.test.ts`:
- Around line 361-397: Add integration tests for the validation/error paths
around the POST /applications/picture route: add a test that sends no attachment
and asserts the response is the expected validation error from
validateApplicationPicture (e.g., 400 and appropriate error message), a test
that attaches an invalid file type (e.g., .txt or .gif) and asserts the
middleware returns the correct validation response, and a test where
sinon.stub(imageService, "uploadApplicationImage") is made to reject to assert
the route returns the service error (status/code and message) and is handled
correctly; place these alongside the existing tests in application.test.ts and
reuse the same auth cookie setup (cookieName/secondUserJwt) and
mockUploadResponse reference but adjust stubbing/attachment to trigger each
path.
- Around line 381-396: The test stubs imageService.uploadApplicationImage but
never restores it, risking test pollution; update the test suite to restore the
stub after the case by adding an afterEach that calls sinon.restore() (or
explicitly calls uploadApplicationImage.restore() if you capture the stub
variable) so the stub created in the "should return 201 and image data when
authenticated with valid image" test is removed before other tests run; locate
the stub usage in the test that posts to "/applications/picture" and add the
afterEach cleanup alongside other per-test cleanup blocks.
36bf39e to
856f32d
Compare
856f32d to
3b9eca5
Compare
prakashchoudhary07
left a comment
There was a problem hiding this comment.
@AnujChhikara Why is this needed? Don't we already have a profile uploading API route?
Yes Sir we do have another route for the image upload but that has the validation that user should be part of discord and some other functionality like adding image for verification for both discord and that uploaded image. Here is the link for that part Upload Image function |
Okay, so what do we have to do to use the existing route? |
We can use query param here and based on that make the discord user middleware optional and then need to create one function that based on query param trigger old image upload function or this application image upload function |
1c2fb5b to
9ace222
Compare
| router.post("/picture", authenticate, checkIsVerifiedDiscord, upload.single("profile"), users.postUserPicture); | ||
| router.post( | ||
| "/picture", | ||
| authenticate, |
Check failure
Code scanning / CodeQL
Missing rate limiting High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 7 days ago
In general, this should be fixed by introducing a rate-limiting middleware (for example using the well-known express-rate-limit package) and applying it to the sensitive route(s) that perform authentication/authorization and potentially expensive operations. The middleware should be configured with reasonable windowMs and max values to balance protection and usability, and should be placed early enough in the middleware chain that expensive handlers (like file parsing and business logic) are not invoked when the limit is exceeded.
For this specific code, the most targeted change that does not alter existing functionality is:
- Import
express-rate-limitat the top ofroutes/users.js. - Define a limiter specifically for the
/pictureupload route (e.g., something likeuserPictureUploadLimiterallowing a small number of uploads per minute per IP). - Insert this limiter in the middleware chain for the
/picturePOST route before the Multerupload.single("profile")middleware, so that excessive requests are rejected before file parsing and subsequent authorization/Discord checks.
Concretely:
- At the top of
routes/users.jsafter the existingrequirestatements, addconst rateLimit = require("express-rate-limit");and a newconst userPictureUploadLimiter = rateLimit({ ... })definition. - Modify the
router.post("/picture", ...)route to insertuserPictureUploadLimiterbetweenauthenticateandupload.single("profile").
No other routes need to be changed to address this specific alert; the change remains tightly scoped to the flagged route and uses a standard, well-known dependency.
| @@ -16,7 +16,15 @@ | ||
| const { userAuthorization } = require("../middlewares/userAuthorization"); | ||
| const conditionalMiddleware = require("../middlewares/conditionalMiddleware"); | ||
| const skipWhenApplicationType = require("../middlewares/pictureRouteMiddleware"); | ||
| const rateLimit = require("express-rate-limit"); | ||
|
|
||
| const userPictureUploadLimiter = rateLimit({ | ||
| windowMs: 15 * 60 * 1000, // 15 minutes | ||
| max: 50, // limit each IP to 50 picture upload requests per windowMs | ||
| standardHeaders: true, | ||
| legacyHeaders: false, | ||
| }); | ||
|
|
||
| router.post("/", authorizeAndAuthenticate([ROLES.SUPERUSER], [Services.CRON_JOB_HANDLER]), users.markUnverified); | ||
| router.post("/update-in-discord", authenticate, authorizeRoles([SUPERUSER]), users.setInDiscordScript); | ||
| router.post("/verify", authenticate, users.verifyUser); | ||
| @@ -69,6 +76,7 @@ | ||
| router.post( | ||
| "/picture", | ||
| authenticate, | ||
| userPictureUploadLimiter, | ||
| upload.single("profile"), | ||
| skipWhenApplicationType(checkIsVerifiedDiscord), | ||
| users.handleUserPictureUpload |
| @@ -42,7 +42,8 @@ | ||
| "passport-github2": "0.1.12", | ||
| "passport-google-oauth20": "^2.0.0", | ||
| "rate-limiter-flexible": "5.0.3", | ||
| "winston": "3.13.0" | ||
| "winston": "3.13.0", | ||
| "express-rate-limit": "^8.2.1" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/chai": "4.3.16", |
| Package | Version | Security advisories |
| express-rate-limit (npm) | 8.2.1 | None |
* Merge pull request #2576 from RealDevSquad/2569-refactor-test-for-group-idle fix: test expectations for idle user * feat: enhance application scoring and update validation (#2573) * feat: enhance application scoring and update validation - Added score handling in nudgeApplication logic to increment score on nudging. - Updated application creation to set an initial score of 50. - Enhanced application update validation to include optional fields: firstName, lastName, college, skills, city, state, country, and role. - Improved integration tests to verify score updates and application modifications. - Adjusted unit tests to reflect changes in application scoring logic. * feat: introduce application scoring system and update application queries * test: refactor application update test for invalid role handling * refactor: remove firstName and lastName from application update validation and tests * refactor: rename 'college' to 'institution' in application validation, service, and tests * feat: implement user picture upload handling for application type (#2564) --------- Co-authored-by: Vinit khandal <vinit224488@gmail.com>
Date: 17 Feb, 2026
Developer Name: @AnujChhikara
Issue Ticket Number
Description
Documentation Updated?
Under Feature Flag
Database Changes
Breaking Changes
Development Tested?
Screenshots
Screenshot 1
Screen.Recording.2026-02-21.at.1.52.27.AM.mov
Test Coverage
Screenshot 1
Additional Notes