Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 31 additions & 21 deletions backend/src/controllers/auth.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,31 +30,41 @@ const getGoogleClient = () => {
*/
export const signup = catchAsync(async (req, res) => {
const { name, email, password } = req.body;
const existing = await User.findOne({ email });
if (existing) {
return res.status(409).json({ message: "An account with this email already exists" });
}

// Secure password hashing with 10 salt rounds
const hashedPassword = await bcrypt.hash(password, 10);

// Sanitize string attributes before insertion
const user = await User.create({
name: name.trim(),
email: email.toLowerCase().trim(),
password: hashedPassword
// Password Strength Validation
const passwordRegex =
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&^#()[\]{}\-_=+|\\:;"'<>,./~`]).{8,}$/;

if (!passwordRegex.test(password)) {
return res.status(400).json({
message:
"Password must be at least 8 characters long and contain uppercase, lowercase, number, and special character",
});
}

// Set secure HTTP-Only authentication cookie
generateTokenAndSetCookie(user._id, res);

res.status(201).json({
_id: user._id,
name: user.name,
email: user.email,
profilePicture: user.profilePicture,
statusMood: user.statusMood || null,
const existing = await User.findOne({ email });
if (existing) {
return res.status(409).json({
message: "An account with this email already exists",
});
}
Comment on lines +45 to +50

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical: Email duplicate check must normalize the email consistently with user creation.

The duplicate check queries using the raw email parameter, but line 56 creates the user with email.toLowerCase().trim(). This normalization mismatch allows the duplicate check to pass for emails that differ only in casing (e.g., "Test@Example.com" vs "test@example.com"), which will either:

  • Create duplicate accounts if the database lacks a case-insensitive unique constraint, or
  • Cause a database constraint violation error after the duplicate check passed
🔧 Proposed fix
-    const existing = await User.findOne({ email });
+    const existing = await User.findOne({ email: email.toLowerCase().trim() });
     if (existing) {
         return res.status(409).json({
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const existing = await User.findOne({ email });
if (existing) {
return res.status(409).json({
message: "An account with this email already exists",
});
}
const existing = await User.findOne({ email: email.toLowerCase().trim() });
if (existing) {
return res.status(409).json({
message: "An account with this email already exists",
});
}
🤖 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 `@backend/src/controllers/auth.controller.js` around lines 45 - 50, Normalize
the incoming email before performing the duplicate lookup so it matches how
users are created: compute a normalizedEmail (e.g., email.toLowerCase().trim())
and use User.findOne({ email: normalizedEmail }) for the duplicate check, then
reuse normalizedEmail when creating the user so User.findOne, the duplicate
check, and the creation all use the same normalized value.


const hashedPassword = await bcrypt.hash(password, 10);

const user = await User.create({
name: name.trim(),
email: email.toLowerCase().trim(),
password: hashedPassword,
});

generateTokenAndSetCookie(user._id, res);

res.status(201).json({
_id: user._id,
name: user.name,
email: user.email,
profilePicture: user.profilePicture,
});
Comment on lines +62 to +67

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

API contract inconsistency: Response payload omits statusMood field.

The signup response returns only _id, name, email, and profilePicture, but the login (line 96) and googleAuth (line 149) endpoints include statusMood: user.statusMood || null. This creates an inconsistent API shape across authentication endpoints.

Impact:
The frontend stores the entire response as authUser (see context snippet 1). The Settings page initializes state from authUser?.statusMood (see context snippet 2). After signup, statusMood will be undefined, but after login/OAuth it will be present. This asymmetry can cause UI inconsistencies or require special handling in downstream components.

🔧 Proposed fix for consistency
     res.status(201).json({
         _id: user._id,
         name: user.name,
         email: user.email,
         profilePicture: user.profilePicture,
+        statusMood: user.statusMood || null,
     });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
res.status(201).json({
_id: user._id,
name: user.name,
email: user.email,
profilePicture: user.profilePicture,
});
res.status(201).json({
_id: user._id,
name: user.name,
email: user.email,
profilePicture: user.profilePicture,
statusMood: user.statusMood || null,
});
🤖 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 `@backend/src/controllers/auth.controller.js` around lines 62 - 67, The signup
response omits the statusMood field causing an inconsistent API shape versus
login and googleAuth; update the signup response in the signup handler to
include statusMood: user.statusMood || null (same key and fallback used by login
and googleAuth) so the returned payloads from signup, login, and googleAuth are
consistent; locate the signup function in auth.controller.js and add the
statusMood property to the res.status(201).json object alongside _id, name,
email, and profilePicture.

});

/**
Expand Down