From d8f1ea4a05b91ecda4b96522d522e1292cc40f14 Mon Sep 17 00:00:00 2001 From: Joslyn Manzi Karenzi Date: Tue, 7 May 2024 20:25:43 +0200 Subject: [PATCH] * feat(rbac): Implement role based access control -define roles and permissions for vendors and buyers -assign roles and permissions to users during registration or profile update -enforce role-based access control throughout the application -write comprehensive unit tests [Delivers #34] * feat(rbac): integrate rbac into user registration -integrate role based access control into user registration [Delivers #34] * feat(rbac): integrate rbac into user registration -integrate role based access control into user registration [Delivers #34] --------- Co-authored-by: ambroisegithub Social Logins (#45) * squashing commits implementing routes for auth create passport callback function adding new user from Google creating new user check if user is exist in db implementing cookie session Fix error of TypeError: req.session.regenerate is not a function using Passport fix secret keys remove Google client secret keys working on facebook strategy get email from fb login and update the scope after verification save the user into db add profile image in db fixing minor bugs fix minor bugs in codes after rebasing & updating some fts link social login with userModel Addong Google client keys & FB client key into yml send confrim email after register a new user send email after register from facebook fix minor bugs * fix minor errors * remove lints errors user register register user test register user testing fix register user testing fix register user testing fix Authentication for User Added slint changes removed mocha added new features added new features Solved comflicts changed file added changes added new Test added new Test resolved test cases resolved test cases implemented two-factor authentication for enhanced security implemented two-factor authentication for enhanced security check whether the usertype is vendor to proceed with 2FA test the 2fa authentication add new tests for buyers login bug-fixes fixing bugs to remove conflicts with develop ft-password-recover-and-documentation This PR corrects some bugs on the user password recover function and add the documentation in th swagger bug-fixes fixing bugs on the recover password endpoints ft-password-rover Thi PR add a password recover by email feature, it also have a new email templates to send recovering token to email, and finally it resolve color contrast issue on the button nside the email template ft-password-recover-and-documentation This PR corrects some bugs on the user password recover function and add the documentation in th swagger bug-fixes fixing bugs on the recover password endpoints bug-fixes bug-fixes --- src/__test__/userController.test.ts | 102 +--------------------------- src/docs/userRegisterDocs.ts | 81 ++++++++++++++++++++++ 2 files changed, 82 insertions(+), 101 deletions(-) diff --git a/src/__test__/userController.test.ts b/src/__test__/userController.test.ts index 948f6fdc..3a7139df 100644 --- a/src/__test__/userController.test.ts +++ b/src/__test__/userController.test.ts @@ -3,7 +3,7 @@ import app from '../app'; import { afterAllHook, beforeAllHook } from './testSetup'; import jwt from 'jsonwebtoken'; import dbConnection from '../database'; -import UserModel from '../database/models/userModel'; +import UserModel from '../database/models/userModel'; import dotenv from 'dotenv'; dotenv.config(); @@ -335,103 +335,3 @@ describe('User Login Tests', () => { expect(loginResponse.body.message).toBe('User Not Found'); }); }); - -describe('Password Recover Tests', () => { - - it('should generate a password reset token and send an email', async () => { - const userData = { - firstName: 'Test', - lastName: 'User', - email: 'test@gmail.com', - password: 'TestPassword123', - userType: 'vendor' - }; - - // Register a user - await request(app).post('/api/v1/user/register').send(userData); - - // Find the registered user in the database - const recoverUser = await userRepository.findOne({ where: { email: userData.email } }); - - // Check if the user is found - if (recoverUser) { - // Generate a recover token using the user's email - - - // Send a request to the recover endpoint - const response = await request(app) - .post('/api/v1/user/recover') - .send({ email: recoverUser.email }); - - // Verify the response - expect(response.status).toBe(200); - expect(response.body.message).toEqual('Password reset token generated successfully'); - } else { - // Throw an error if the user is not found - throw new Error('User not found'); - } - }); - - it('should return a 404 error if the user email is not found', async () => { - const nonExistingEmail = 'nonexisting@example.com'; - - // Send a request to the recover endpoint with a non-existing email - const response = await request(app) - .post('/api/v1/user/recover') - .send({ email: nonExistingEmail }); - - // Verify the response - expect(response.status).toBe(404); - expect(response.body.message).toEqual('User not found'); - }); - - - it('should update user password with the provided reset token', async () => { - const newPassword = 'NewTestPassword123'; - - // Generate a user and a recover token - const userData = { - firstName: 'Test', - lastName: 'User', - email: 'test@gmail.com', - password: 'TestPassword123', - userType: 'vendor' - }; - - await request(app).post('/api/v1/user/register').send(userData); - - const recoverUser = await userRepository.findOne({ where: { email: userData.email } }); - - if (recoverUser) { - const recoverToken = jwt.sign({ email: recoverUser.email }, process.env.JWT_SECRET as jwt.Secret, { expiresIn: '1h' }); - - const response = await request(app) - .post(`/api/v1/user/recover/confirm?recoverToken=${recoverToken}`) - .send({ password: newPassword }); - - expect(response.status).toBe(200); - expect(response.body.message).toEqual('Password updated successfully'); - - const updatedUser = await userRepository.findOne({ where: { email: userData.email } }); - expect(updatedUser).toBeDefined(); - } else { - throw new Error('User not found'); - } - }); - - it('should return a 401 error for an invalid reset token', async () => { - const invalidResetToken = undefined; - - // Send a request to the updateNewPassword endpoint with an invalid reset token - const response = await request(app) - .post('/api/v1/user/recover/confirm') - .query({ recoverToken: invalidResetToken }) - .send({ password: 'new-password' }); - - // Verify the response - expect(response.status).toBe(404); - expect(response.body.message).toEqual('Invalid or expired token'); - }); - -}); - diff --git a/src/docs/userRegisterDocs.ts b/src/docs/userRegisterDocs.ts index 327cec30..7fb7e7e1 100644 --- a/src/docs/userRegisterDocs.ts +++ b/src/docs/userRegisterDocs.ts @@ -169,6 +169,87 @@ * '500': * description: An error occurred while deleting the record. */ +/** + * @swagger + * /api/v1/user/updateProfile/{id}: + * put: + * summary: Update user profile + * tags: + * - User + * parameters: + * - in: path + * name: id + * required: true + * description: ID of the user to update + * schema: + * type: integer + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * firstName: + * type: string + * description: The updated first name of the user. + * lastName: + * type: string + * description: The updated last name of the user. + * email: + * type: string + * format: email + * description: The updated email address of the user. + * oldPassword: + * type: string + * format: password + * description: The old password of the user for verification. + * newPassword: + * type: string + * format: password + * description: The new password of the user (optional). + * responses: + * '200': + * description: User profile updated successfully. + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * description: A message indicating successful profile update. + * '400': + * description: Bad request or validation errors. + * content: + * application/json: + * schema: + * type: object + * properties: + * error: + * type: string + * description: Error message indicating the reason for the bad request. + * '404': + * description: Not Found - User not found. + * content: + * application/json: + * schema: + * type: object + * properties: + * error: + * type: string + * description: A message indicating the user was not found. + * '500': + * description: Internal server error. + * content: + * application/json: + * schema: + * type: object + * properties: + * error: + * type: string + * description: A message indicating an internal server error occurred. + */ /** * @swagger