-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #59 from atlp-rwanda/187419196-prompt-to-change-pa…
…ssword feat(change password):user should be prompted to change their password every x amount of time
- Loading branch information
Showing
25 changed files
with
215 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import request from "supertest"; | ||
import { mocked } from "jest-mock"; | ||
import { beforeAll, beforeEach, afterEach, afterAll, test } from "@jest/globals"; | ||
import app from "../src/utils/server"; | ||
import User from "../src/sequelize/models/users"; | ||
|
@@ -25,14 +26,15 @@ const userData: any = { | |
username: "testuser5", | ||
email: "[email protected]", | ||
password: "test12345", | ||
lastPasswordUpdateTime: new Date() | ||
}; | ||
|
||
|
||
const dummySeller = { | ||
name: "dummy1234", | ||
username: "username1234", | ||
email: "[email protected]", | ||
password: "1234567890", | ||
lastPasswordUpdateTime: "3000, 11, 18" | ||
}; | ||
const userTestData = { | ||
newPassword: "Test@123", | ||
|
@@ -62,7 +64,8 @@ const updateData:any = { | |
country: "Rwanda", | ||
} | ||
|
||
|
||
jest.mock('../src/jobs/isPasswordExpired'); | ||
|
||
describe("Testing user Routes", () => { | ||
beforeAll(async () => { | ||
try { | ||
|
@@ -103,7 +106,6 @@ describe("Testing user Routes", () => { | |
const response = await request(app) | ||
.post("/api/v1/users/register") | ||
.send(userData); | ||
|
||
expect(response.status).toBe(201); | ||
}, 20000); | ||
|
||
|
@@ -225,6 +227,7 @@ describe("Testing user Routes", () => { | |
roleId: 2, | ||
}) | ||
.set("Authorization", "Bearer " + adminToken); | ||
|
||
expect(response.status).toBe(200); | ||
|
||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
const passwordExpirationHtmlContent = (userName: string): string => { | ||
const htmlContent = ` | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Password Updated Confirmation</title> | ||
<style> | ||
body { | ||
font-family: Arial, sans-serif; | ||
line-height: 1.6; | ||
background-color: #f5f5f5; | ||
margin: 0; | ||
padding: 0; | ||
} | ||
.container { | ||
max-width: 600px; | ||
margin: 20px auto; | ||
padding: 20px; | ||
background-color: #fff; | ||
border-radius: 5px; | ||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); | ||
} | ||
h1 { | ||
color: #333; | ||
} | ||
p { | ||
color: #666; | ||
} | ||
.footer { | ||
margin-top: 20px; | ||
text-align: center; | ||
color: #999; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div class="container"> | ||
<h1>Password Expiration </h1> | ||
<p>Dear ${userName},</p> | ||
<p>Your password has been Expired. | ||
Vist our website to update it to continue using the system.</p> | ||
<p>Thank you.</p> | ||
<p style="color: #666;">Your Website Team</p> | ||
<div class="footer"> | ||
<p>This is an automated email. Please do not reply.</p> | ||
</div> | ||
</div> | ||
</body> | ||
</html> | ||
`; | ||
return htmlContent; | ||
}; | ||
|
||
export { passwordExpirationHtmlContent }; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import cron from 'node-cron'; | ||
import EventEmitter from 'events'; | ||
import { getAllUsers } from '../services/user.service'; | ||
import { env } from '../utils/env'; | ||
import { sendEmailService } from '../services/mail.service'; | ||
import { passwordExpirationHtmlContent } from '../email-templates/passwordExpiredNotification'; | ||
|
||
let latestExpiredUserData = new Set<any>(); | ||
export let expiredUserData = new Set<any>(); | ||
|
||
class UpdatePasswordEventsEmitter extends EventEmitter {}; | ||
export const passwordEventEmitter = new UpdatePasswordEventsEmitter(); | ||
|
||
export const isPasswordExpired = () =>{ | ||
const millseconddPerMin = 1000 * 60; | ||
cron.schedule('* * * * * *', async() => { | ||
const currentTime = Date.now(); | ||
const users = await getAllUsers(); | ||
const emailPromises = []; | ||
for (const user of users) { | ||
const lastPasswordUpdateTime:any = user.dataValues.lastPasswordUpdateTime; | ||
const timeDifference:any = currentTime - lastPasswordUpdateTime; | ||
if(timeDifference >= (millseconddPerMin * parseInt(env.password_expiration_time))&& !latestExpiredUserData.has(user.id)){ | ||
passwordEventEmitter.emit("password expired",user); | ||
latestExpiredUserData.add(user.id); | ||
emailPromises.push( | ||
sendEmailService(user, 'Password expired', passwordExpirationHtmlContent(user.name)) | ||
); | ||
}; | ||
}; | ||
await Promise.all(emailPromises); | ||
expiredUserData = new Set([...latestExpiredUserData]); | ||
}); | ||
} | ||
passwordEventEmitter.on("password expired", (user) => { | ||
expiredUserData.add(user); | ||
}); | ||
|
||
export const clearExpiredUserData = (userId:any) => { | ||
latestExpiredUserData.delete(userId); | ||
expiredUserData.delete(userId); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { Request,Response,NextFunction } from 'express'; | ||
import { isLoggedIn } from './isLoggedIn'; | ||
import { expiredUserData } from '../jobs/isPasswordExpired'; | ||
|
||
export const isPasswordOutOfDate = async(req:Request,res:Response,next:NextFunction) =>{ | ||
try { | ||
await isLoggedIn(req,res,() => {}); | ||
//@ts-ignore | ||
const loggedInUserId: any = req.user.id; | ||
const expiredUserIds = new Set([...expiredUserData].map((user: any) => user)); | ||
if (expiredUserIds.has(loggedInUserId)) { | ||
return res.status(403).json({ | ||
message: "Your password expired, Update it to continue" | ||
}); | ||
}; | ||
next(); | ||
} catch (error:any) { | ||
console.log('Error has occured',error.message); | ||
next(error) | ||
} | ||
} | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.