Skip to content

Commit

Permalink
[Finishes #187354251] Update user password
Browse files Browse the repository at this point in the history
  • Loading branch information
P-Rwirangira committed May 1, 2024
1 parent 6de33c7 commit 3c6f7b5
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 7 deletions.
48 changes: 47 additions & 1 deletion src/controllers/authController.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
import { Request, Response, NextFunction } from 'express';
import passport from 'passport';
import jwt from 'jsonwebtoken';
import bcrypt from 'bcrypt';
import User, { UserAttributes } from '../database/models/user';
import { sendInternalErrorResponse, validateFields } from '../validations';
import logger from '../logs/config';
import { UUID } from 'crypto';

const authenticateViaGoogle = (req: Request, res: Response, next: NextFunction) => {
passport.authenticate('google', (err: unknown, user: UserAttributes | null) => {
Expand Down Expand Up @@ -93,5 +96,48 @@ const login = async (req: Request, res: Response): Promise<void> => {
sendInternalErrorResponse(res, err);
}
};
const updatePassword = async (req: Request, res: Response): Promise<void> => {
try {
const { oldPassword, newPassword } = req.body;

// Access decoded user information from the request object
const user = req?.user as {
id: UUID;
password: string;
};

// Check if old password matches
const match = await bcrypt.compare(oldPassword, user.password);
if (!match) {
res.status(400).json({
ok: false,
message: 'The old password is incorrect!',
});
return;
}

// Generate salt and hash new password
const saltRound = await bcrypt.genSalt(10);
const hashedNewPassword = await bcrypt.hash(newPassword, saltRound);

// Update user's password
await User.update(
{ password: hashedNewPassword },
{
where: {
id: user.id,
},
}
);

res.status(200).json({
ok: true,
message: 'Successfully updated user password!',
});
} catch (error) {
logger.error('Error updating user:', error);
sendInternalErrorResponse(res, error);
}
};

export { login, authenticateViaGoogle };
export { login, updatePassword, authenticateViaGoogle };
85 changes: 82 additions & 3 deletions src/docs/auth.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

paths:

/api/auth/google:
Expand Down Expand Up @@ -53,6 +54,84 @@ paths:
500:
description: Internal server error

tags:
- name: Login
description: Login a user
/api/auth/update-password:
put:
summary: Update user password
description: Updates the password of the authenticated user.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
oldPassword:
type: string
description: The current password of the user.
newPassword:
type: string
description: The new password to be set for the user.
required:
- oldPassword
- newPassword
responses:
'200':
description: Successfully updated user password.
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
description: Indicates if the operation was successful.
example: true
message:
type: string
description: A message indicating the status of the operation.
example: Successfully updated user password!
'400':
description: Bad request. Indicates that the provided token is invalid or old password is incorrect, or the user is not found.
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
description: Indicates if the operation was successful.
example: false
message:
type: string
description: A message indicating the reason for the failure.
example: Invalid token
'401':
description: Unauthorized. Indicates that no token was provided.
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
description: Indicates if the operation was successful.
example: false
message:
type: string
description: A message indicating the reason for the failure.
example: Unauthorized
'500':
description: Internal Server Error. Indicates an unexpected error occurred.
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
description: Indicates if the operation was successful.
example: false
message:
type: string
description: A message indicating the reason for the failure.
example: Internal Server Error
1 change: 1 addition & 0 deletions src/middlewares/authMiddlewares.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-misused-promises */
import { Request, Response, NextFunction } from 'express';
import { config } from 'dotenv';
Expand Down
8 changes: 5 additions & 3 deletions src/routes/authRoute.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/no-misused-promises */
import { Router } from 'express';
import passport from 'passport';
import { authenticateViaGoogle } from '../controllers/authController';
import { login } from '../controllers/authController';

import { authenticateViaGoogle, login, updatePassword } from '../controllers/authController';
import { isAuthenticated } from '../middlewares/authMiddlewares';
const router = Router();
// redirect user to google for authentication
router.get(
Expand All @@ -18,4 +18,6 @@ router.get('/google/callback', authenticateViaGoogle);
// Route to login a user
router.post('/login', login);

router.put('/update-password', isAuthenticated, updatePassword);

export default router;

0 comments on commit 3c6f7b5

Please sign in to comment.