Skip to content

Conversation

@OleksandrY0
Copy link

No description provided.

Copy link

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Choose a reason for hiding this comment

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

Review Summary

You've built a solid architectural foundation, and the core JWT authentication flow is well-implemented. However, changes are needed because several critical features are missing and there's a significant bug in the error handling.

Here are the main points to address:

  • Missing Core Features: The password reset and profile management (changing name, password, email) functionalities are not implemented. You'll need to add the corresponding routes, controllers, and service logic.
  • Incomplete Registration: The name field is a requirement for registration but is missing from the user.model.js and the registration logic in auth.controller.js.
  • Login Logic: The login process in auth.controller.js must check if a user's account has been activated before allowing them to log in.
  • Critical Error Handling Bug: In app-back/src/middlewares/error.midleware.js, you must add a return after sending the JSON response for an ApiError to prevent the server from crashing.
  • Missing 404 Handler: The application lacks a catch-all route in index.js to handle requests for non-existent pages as required.

Once these key features are implemented, your project will be in great shape. Keep up the good work!


✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨

Important

Fix the issues, commit the changes, and then re-request my review using the Re-request review button2 in the Reviewers tab.

Tip

If you have any comments about this review, please leave a message in the Add a comment section below and mention me with the @mateacademy-ai-mentor tag3.
I will read your message during my next review of your pull request. Please do not reply directly to my comments, as that feature is not supported yet.

Caution

Do not close the pull request until the review is complete. Closing it early can lead to unexpected behavior and disrupt the review process.

Footnotes

  1. Rate AI review example

  2. Re-request AI review example

  3. Add AI review comments example

app.use(cookieParser());

app.use('/auth', authRouter);
app.use('/users', userRouter);

Choose a reason for hiding this comment

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

The task requires you to provide a 404 page for all other pages. You should add a catch-all middleware here to handle any requests that don't match the /auth or /users routes.

};

const register = async (req, res) => {
const { email, password } = req.body;

Choose a reason for hiding this comment

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

The task requires registration with name, email, and password. The name field is missing from this implementation. You'll need to update this to accept the user's name, and likely update your user model and service as well.


if (!user) {
return res.sendStatus(404);
}

Choose a reason for hiding this comment

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

The requirements state that if a user is not active, you should ask them to activate their email. Before proceeding with the password check, you should verify if the user's account has been activated (i.e., if user.activationToken is null).

Comment on lines 10 to 12
export const userController = {
getAllActivated,
};

Choose a reason for hiding this comment

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

This controller is missing the required functions for profile management. According to the requirements, you need to implement endpoints that allow an authenticated user to change their name, password, and email.

if (error instanceof ApiError) {
res.status(error.status).send({
message: error.message,
errors: error.message,

Choose a reason for hiding this comment

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

In your ApiError class, you have a distinct errors property. To provide more detailed error information to the client, you should use error.errors here instead of repeating error.message.

Comment on lines 34 to 37
export const emailService = {
sendActivationEmail,
send,
};

Choose a reason for hiding this comment

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

This service is missing functions for other required email notifications. According to the task description, you also need to send an email for password resets and another to notify a user when their email address has been changed.

@@ -0,0 +1,3 @@
import { client } from './utils/db.utils.js';

client.sync({ force: true });

Choose a reason for hiding this comment

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

Using { force: true } is great for development as it drops and recreates tables, ensuring a clean state. However, it's crucial to remember that this is a destructive operation. If this script were ever run against a production database, it would wipe out all data. It's a good practice to prevent such scripts from running in production, for example, by checking if process.env.NODE_ENV !== 'production'.

Comment on lines 16 to 17
function normalizedUser({ id, email }) {
return { id, email };

Choose a reason for hiding this comment

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

The task requirements specify that a user has a name. This normalization function should also include the user's name in the returned object.

});
}

async function register(email, password) {

Choose a reason for hiding this comment

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

According to the task description, registration must use name, email, and password. This function is missing the name parameter and the logic to save it to the new user record.

Comment on lines 41 to 46
export const userService = {
register,
getAllActivated,
normalizedUser,
findByEmail,
};

Choose a reason for hiding this comment

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

This service is missing the implementation for several key features. You need to add functions to handle the password reset flow and to allow users to update their profile information (name, password, and email) as required by the task.

Copy link

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Choose a reason for hiding this comment

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

Review Summary

Great progress on the application! You've implemented many of the core features and the overall structure is looking good. However, a few critical requirements are still missing, so I'm requesting some changes before approval.

Here are the main issues to address:

  • Runtime Error: The application will crash when trying to manage the user profile because ApiError is used without being imported in src/controllers/user.controller.js.
  • Missing 404 Handler: The catch-all route for handling non-existent pages in src/index.js is still commented out. This is a core requirement that needs to be implemented.
  • Incomplete Password Logic: Both the password reset (auth.controller.js) and change password (user.controller.js) features are missing the required validation to check the new password against a confirmation field.
  • Missing Email Change Notification: When a user changes their email, the old email address must be notified. This functionality is missing from user.service.js and email.service.js.

Please fix these issues to meet the task requirements. You're very close to finishing!


✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨

Important

Fix the issues, commit the changes, and then re-request my review using the Re-request review button2 in the Reviewers tab.

Tip

If you have any comments about this review, please leave a message in the Add a comment section below and mention me with the @mateacademy-ai-mentor tag3.
I will read your message during my next review of your pull request. Please do not reply directly to my comments, as that feature is not supported yet.

Caution

Do not close the pull request until the review is complete. Closing it early can lead to unexpected behavior and disrupt the review process.

Footnotes

  1. Rate AI review example

  2. Re-request AI review example

  3. Add AI review comments example

Comment on lines +17 to +19
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1

Choose a reason for hiding this comment

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

It's a good practice to use the latest major versions of GitHub Actions to benefit from new features, bug fixes, and performance improvements. Consider updating actions/checkout to v4 and actions/setup-node to v4. The v1 version of setup-node is quite outdated and may not support newer Node.js features efficiently.

Comment on lines 30 to 32
// app.all('/', (req, res) => {
// res.status(404).json({ message: 'Page not found' });
// });

Choose a reason for hiding this comment

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

The catch-all route for handling 404 errors is commented out, which means the application doesn't meet the requirement to display a 404 page for non-existent routes. This handler should be placed after all other routes to function correctly. Also, consider using app.all('*', ...) to catch all paths and methods that haven't been matched by other routes.

const userId = req.user.id;

if (!name || name.trim().length < 2) {
throw ApiError.badRequest('Name is invalid');

Choose a reason for hiding this comment

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

The ApiError class is used here, but it hasn't been imported into this file. This will cause a ReferenceError at runtime.

};

const changePassword = async (req, res) => {
const { oldPassword, newPassword } = req.body;

Choose a reason for hiding this comment

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

The requirements state that changing a password requires an old password, a new password, and a confirmation field. This implementation is missing the logic to check if newPassword and its confirmation match.

};

const changeEmail = async (req, res) => {
const { password, newEmail } = req.body;

Choose a reason for hiding this comment

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

According to the task description, the user must confirm their new email address. This controller is missing the validation to check the newEmail against a confirmation field from the request body.


function sign(user) {
const token = jwt.sign(user, process.env.JWT_KEY, {
expiresIn: '5s',

Choose a reason for hiding this comment

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

An expiration of 5 seconds is very short for an access token and might lead to a poor user experience, as it would require frequent refreshing. While this is fine for testing purposes, you might want to consider a longer duration, like '15m' or '30m', for a real application.

Comment on lines 43 to 47
export const emailService = {
sendActivationEmail,
sendResetPasswordEmail,
send,
};

Choose a reason for hiding this comment

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

The task requirements state that when a user changes their email, a notification must be sent to the old email address. This service is missing a function to handle that specific notification. Consider adding a new function, like sendEmailChangeNotification(oldEmail, newEmail), to create and send this email.

Comment on lines 42 to 47
async function changeEmail(user, email) {
user.email = email;

await user.save();

return user;

Choose a reason for hiding this comment

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

This function is missing a crucial validation step. Before updating the email, you must check if the new email address is already in use by another user. If it is, you should throw an ApiError.badRequest to prevent a unique constraint violation in the database.

Comment on lines 42 to 47
async function changeEmail(user, email) {
user.email = email;

await user.save();

return user;

Choose a reason for hiding this comment

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

According to the task requirements, when an email is changed, a notification must be sent to the old email address. This implementation is missing that step. You should capture the old email address from the user object before updating it and then call a method on the emailService to send the notification.

@@ -0,0 +1,3 @@
import { client } from './utils/db.utils.js';

client.sync({ force: true });

Choose a reason for hiding this comment

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

Using { force: true } is a destructive operation that drops all existing tables and recreates them from the models. While this is very useful for development and testing to ensure a clean state, it must never be used in a production environment as it will cause irreversible data loss.

Copy link

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Choose a reason for hiding this comment

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

Review Summary

Excellent progress on the application! You've successfully addressed most of the previous feedback, which is great to see. I am approving this submission as an educational override to help you move forward, but please take a moment to review a few critical points.

  • In app-back/src/controllers/user.controller.js, you should throw the ApiError instead of returning it. Returning the error prevents our error-handling middleware from catching it, which will cause the request to hang without a response.
  • The 404 handler in app-back/src/index.js currently only catches requests to the root path (/). To meet the requirement, it needs to be a true catch-all for any unhandled route, like app.all('*', ...).
  • There's a small bit of redundant password validation in app-back/src/controllers/auth.controller.js that can be removed for cleaner code.

Keep up the fantastic work, you're very close to a perfect solution!


✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨

Footnotes

  1. Rate AI review example

const userId = req.user.id;

if (authController.validatePassword(newPassword)) {
return ApiError.badRequest();

Choose a reason for hiding this comment

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

When validatePassword returns an error message (a truthy value), you should throw the ApiError instead of returning it. The catchError utility is designed to catch thrown errors, but returning a value here will not send a proper response to the client.

}

if (newPassword !== confirmPassword) {
return ApiError.badRequest();

Choose a reason for hiding this comment

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

Similar to the previous point, you should throw ApiError.badRequest() here. Returning the error object directly will not be handled correctly by Express or your error middleware.

Comment on lines +158 to +162
if (validatePassword(password)) {
return res
.status(400)
.json({ message: 'Password must be at least 6 characters' });
}

Choose a reason for hiding this comment

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

This password validation check is redundant because the same check is already performed on line 148. You can safely remove this block of code.

Comment on lines +30 to +32
app.all('/', (req, res) => {
res.status(404).json({ message: 'Page not found' });
});

Choose a reason for hiding this comment

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

This route will only handle requests to / and return a 404. To meet the requirement of handling all non-existent pages, this should be a catch-all route like app.all('*', ...). Make sure to place it after all other route definitions.

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