Skip to content

Comments

js-project-api-irisdgz#40

Open
irisdgz wants to merge 8 commits intoTechnigo:masterfrom
irisdgz:master
Open

js-project-api-irisdgz#40
irisdgz wants to merge 8 commits intoTechnigo:masterfrom
irisdgz:master

Conversation

@irisdgz
Copy link

@irisdgz irisdgz commented Feb 8, 2026

Please include your Render link here.
https://js-project-api-w19.onrender.com/

Copy link

@qabalany qabalany left a comment

Choose a reason for hiding this comment

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

Hi Iris! I'm really impressed with your API implementation! You've built a secure, well-structured application with authentication that shows strong understanding of backend development principles. Here are my observations

Comment on lines +11 to +35
const existingUser = await User.findOne({ email: email.toLowerCase() });

if (existingUser) {
return res.status(400).json({ success: false, message: "User already exists" });
}

const salt = bcrypt.genSaltSync();
const hashedPassword = bcrypt.hashSync(password, salt);
const user = new User({ email, password: hashedPassword });
await user.save();

res.status(201).json({
success: true,
response: { email: user.email, id: user._id, accessToken: user.accessToken },
});
} catch (error) {
res.status(400).json({ success: false, response: error });
}
});

// LOGIN
router.post("/login", async (req, res) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email: email.toLowerCase() });

Choose a reason for hiding this comment

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

I love that you're normalizing emails to lowercase in both signup and login! This prevents issues where a user signs up with "User@Email.com" but tries to log in with "user@email.com". This kind of thoughtful UX consideration makes the API much more user-friendly.

You could add one more layer of polish by also trimming whitespace:
const email = req.body.email.toLowerCase().trim();

Comment on lines +27 to +42
// AUTHENTICATION MIDDLEWARE
// This function sits between the request and the actual route logic
const authenticateUser = async (req, res, next) => {
const accessToken = req.header("Authorization");
try {
const user = await User.findOne({ accessToken: accessToken });
if (user) {
req.user = user;
next();
} else {
res.status(401).json({ success: false, response: "Please log in" });
}
} catch (error) {
res.status(500).json({ success: false, response: error.message });
}
};

Choose a reason for hiding this comment

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

Your authenticateUser middleware is beautifully implemented!
he way you're passing req.user to the next handler (line 34) is particularly clever - it makes the authenticated user available throughout the request lifecycle. Excellent work!

Comment on lines +4 to +19
const UserSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: true,
},
password: {
type: String,
required: true,
},
accessToken: {
type: String,
// this generates a long random string as the user's secret token
default: () => crypto.randomBytes(128).toString("hex"),
},
});

Choose a reason for hiding this comment

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

Well-Structured Schema Design!
The crypto token generation (line 17) is particularly impressive, you're creating a highly secure, random token.

Comment on lines +98 to +100
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(400).json({ success: false, message: "Invalid ID" });
}

Choose a reason for hiding this comment

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

I really appreciate that you're validating the MongoDB ObjectId before querying! This prevents unnecessary database calls and potential errors.

response: { email: user.email, id: user._id, accessToken: user.accessToken },
});
} catch (error) {
res.status(400).json({ success: false, response: error });

Choose a reason for hiding this comment

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

In the signup catch block, you're returning the full error object. While this is helpful for debugging, you might want to provide more user friendly messages in production:
res.status(400).json({
success: false,
message: "Unable to create account. Please check your details and try again."
});

Comment on lines +44 to +57
const Message = mongoose.model(
"Message",
new mongoose.Schema({
message: {
type: String,
required: true,
minlength: 5,
maxlength: 140,
trim: true,
},
hearts: { type: Number, default: 0 },
createdAt: { type: Date, default: Date.now },
})
);

Choose a reason for hiding this comment

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

Your Message model works great! For consistency and maintainability, you might consider moving it to a separate file like models/Message.js, similar to how you organized the User model. This would make the server.js file cleaner and follow the same pattern you've already established. It's a small organizational win that makes the codebase easier to navigate!

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.

2 participants