-
Notifications
You must be signed in to change notification settings - Fork 0
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 #65 from atlp-rwanda/ft-update-user-status
feat-implement-user-status-update
- Loading branch information
Showing
16 changed files
with
565 additions
and
2 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 |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import { NextFunction, Request, Response } from "express"; | ||
import { checkUserStatus } from "../middlewares/isAllowed"; | ||
import { dbConnection } from '../startups/dbConnection'; | ||
import { getConnection } from 'typeorm'; | ||
import { User } from '../entities/User'; | ||
import { responseError } from '../utils/response.utils'; | ||
import { v4 as uuid } from 'uuid'; | ||
|
||
jest.mock('../utils/response.utils'); | ||
|
||
let reqMock: Partial<Request>; | ||
let resMock: Partial<Response>; | ||
let nextMock: NextFunction; | ||
|
||
const activeUserId = uuid(); | ||
const suspendedUserId = uuid(); | ||
|
||
beforeAll(async () => { | ||
const connection = await dbConnection(); | ||
|
||
const userRepository = connection?.getRepository(User); | ||
|
||
const activeUser = new User(); | ||
activeUser.id = activeUserId; | ||
activeUser.firstName = 'John2'; | ||
activeUser.lastName = 'Doe'; | ||
activeUser.email = '[email protected]'; | ||
activeUser.password = 'password'; | ||
activeUser.gender = 'Male'; | ||
activeUser.phoneNumber = '12347'; | ||
activeUser.photoUrl = 'https://example.com/photo.jpg'; | ||
|
||
await userRepository?.save(activeUser); | ||
|
||
const suspendedUser = new User(); | ||
suspendedUser.id = suspendedUserId; | ||
suspendedUser.firstName = 'John2'; | ||
suspendedUser.lastName = 'Doe'; | ||
suspendedUser.email = '[email protected]'; | ||
suspendedUser.password = 'password'; | ||
suspendedUser.gender = 'Male'; | ||
suspendedUser.status = 'suspended'; | ||
suspendedUser.phoneNumber = '12349'; | ||
suspendedUser.photoUrl = 'https://example.com/photo.jpg'; | ||
|
||
await userRepository?.save(suspendedUser); | ||
}); | ||
|
||
afterAll(async () => { | ||
const connection = getConnection(); | ||
const userRepository = connection.getRepository(User); | ||
Check warning on line 51 in src/__test__/isAllowed.test.ts GitHub Actions / build-lint-test-coverage
|
||
|
||
// Close the connection to the test database | ||
await connection.close(); | ||
}); | ||
|
||
describe('Middleware - checkUserStatus', () => { | ||
beforeEach(() => { | ||
reqMock = {}; | ||
resMock = { | ||
status: jest.fn().mockReturnThis(), | ||
json: jest.fn() | ||
}; | ||
nextMock = jest.fn(); | ||
}); | ||
|
||
it('should return 401 if user is not authenticated', async () => { | ||
await checkUserStatus(reqMock as Request, resMock as Response, nextMock); | ||
expect(responseError).toHaveBeenCalledWith(resMock, 401, 'Authentication required'); | ||
}); | ||
|
||
it('should return 401 if user is not found', async () => { | ||
reqMock = { user: { id: uuid() } }; | ||
|
||
await checkUserStatus(reqMock as Request, resMock as Response, nextMock); | ||
|
||
expect(responseError).toHaveBeenCalledWith(resMock, 401, 'User not found'); | ||
}); | ||
|
||
it('should pass if user status is active', async () => { | ||
reqMock = { user: { id: activeUserId } }; | ||
await checkUserStatus(reqMock as Request, resMock as Response, nextMock); | ||
expect(nextMock).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should return 403 if user status is suspended', async () => { | ||
reqMock = { user: { id: suspendedUserId } }; | ||
await checkUserStatus(reqMock as Request, resMock as Response, nextMock); | ||
expect(responseError).toHaveBeenCalledWith(resMock, 403, 'You have been suspended. Please contact our support team.'); | ||
}); | ||
}); |
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,165 @@ | ||
import request from 'supertest'; | ||
import jwt from 'jsonwebtoken'; | ||
import { app, server } from '../index'; | ||
import {getRepository } from 'typeorm'; | ||
import { getConnection } from 'typeorm'; | ||
import { dbConnection } from '../startups/dbConnection'; | ||
import { User } from '../entities/User'; | ||
import { v4 as uuid } from 'uuid'; | ||
|
||
const adminUserId = uuid(); | ||
|
||
const jwtSecretKey = process.env.JWT_SECRET || ""; | ||
|
||
beforeAll(async () => { | ||
const connection = await dbConnection(); | ||
|
||
const userRepository = connection?.getRepository(User); | ||
|
||
const adminUser = new User(); | ||
adminUser.id = adminUserId; | ||
adminUser.firstName = 'remjsa'; | ||
adminUser.lastName = 'djkchd'; | ||
adminUser.email = '[email protected]'; | ||
adminUser.password = 'passwordadmin'; | ||
adminUser.userType = 'Admin'; | ||
adminUser.gender = 'Male'; | ||
adminUser.phoneNumber = '126380996347'; | ||
adminUser.photoUrl = 'https://example.com/photo.jpg'; | ||
|
||
await userRepository?.save(adminUser); | ||
|
||
adminUser.role = 'ADMIN'; | ||
adminUser.verified = true; | ||
await userRepository?.save(adminUser); | ||
}); | ||
|
||
afterAll(async () => { | ||
const connection = getConnection(); | ||
const userRepository = connection.getRepository(User); | ||
Check warning on line 39 in src/__test__/userStatus.test.ts GitHub Actions / build-lint-test-coverage
|
||
|
||
// Close the connection to the test database | ||
await connection.close(); | ||
server.close(); | ||
}); | ||
|
||
const data = { | ||
id: adminUserId, | ||
email: "[email protected]" | ||
}; | ||
|
||
const testUser = { | ||
firstName: 'John', | ||
lastName: 'Doe', | ||
email: '[email protected]', | ||
password: 'password', | ||
gender: 'Male', | ||
phoneNumber: '4223567890', | ||
photoUrl: 'https://example.com/photo.jpg', | ||
}; | ||
|
||
describe('POST /user/deactivate', () => { | ||
it('should deactivate a user', async () => { | ||
await request(app) | ||
.post('/user/register') | ||
.send(testUser); | ||
|
||
const token = jwt.sign(data,jwtSecretKey); | ||
|
||
const response = await request(app) | ||
.post(`/user/deactivate`) | ||
.set("Cookie", `token=${token}`) | ||
.send({email: `${testUser.email}`}); | ||
expect(response.status).toBe(200); | ||
expect(response.body.message).toBe('User deactivated successfully'); | ||
}); | ||
|
||
it('should return 404 when email is not submitted', async ()=> { | ||
|
||
const token = jwt.sign(data,jwtSecretKey); | ||
const response = await request(app) | ||
.post(`/user/deactivate`) | ||
.set("Cookie", `token=${token}`) | ||
|
||
expect(response.status).toBe(404); | ||
expect(response.body.error).toBe('Email is needed'); | ||
}) | ||
it('should return message "User is already suspended" if user is already suspended', async () => { | ||
|
||
const token = jwt.sign(data,jwtSecretKey); | ||
const response = await request(app) | ||
.post(`/user/deactivate`) | ||
.set("Cookie", `token=${token}`) | ||
.send({email: `${testUser.email}`}); | ||
|
||
expect(response.status).toBe(200); | ||
expect(response.body.message).toBe('User is already suspended'); | ||
}); | ||
|
||
it('should return 404 if user not found when deactivating', async () => { | ||
|
||
const token = jwt.sign(data,jwtSecretKey); | ||
const response = await request(app) | ||
.post(`/user/deactivate`) | ||
.set("Cookie", `token=${token}`) | ||
.send({email: "[email protected]"}); | ||
|
||
expect(response.status).toBe(404); | ||
expect(response.body.error).toBe('User not found'); | ||
}); | ||
|
||
}); | ||
|
||
describe('POST /user/activate', () => { | ||
it('should activate a user', async () => { | ||
const token = jwt.sign(data,jwtSecretKey); | ||
|
||
const response = await request(app) | ||
.post(`/user/activate`) | ||
.set("Cookie", `token=${token}`) | ||
.send({email: `${testUser.email}`}); | ||
|
||
expect(response.status).toBe(200); | ||
expect(response.body.message).toBe('User activated successfully'); | ||
|
||
}); | ||
|
||
it('should return 404 when email is not submitted', async ()=> { | ||
const token = jwt.sign(data,jwtSecretKey); | ||
const response = await request(app) | ||
.post(`/user/activate`) | ||
.set("Cookie", `token=${token}`) | ||
|
||
expect(response.status).toBe(404); | ||
expect(response.body.error).toBe('Email is needed'); | ||
}) | ||
|
||
it('should return message "User is already active" if user is already active', async () => { | ||
const token = jwt.sign(data,jwtSecretKey); | ||
const response = await request(app) | ||
.post(`/user/activate`) | ||
.set("Cookie", `token=${token}`) | ||
.send({email: `${testUser.email}`}); | ||
|
||
expect(response.status).toBe(200); | ||
expect(response.body.message).toBe('User is already active'); | ||
|
||
const userRepository = getRepository(User); | ||
const user = await userRepository.findOne({ where: { email: testUser.email } }); | ||
if (user) { | ||
await userRepository.remove(user); | ||
} | ||
}); | ||
|
||
it('should return 404 if user not found when activating', async () => { | ||
const token = jwt.sign(data,jwtSecretKey); | ||
const response = await request(app) | ||
.post('/user/activate') | ||
.set("Cookie", `token=${token}`) | ||
.send({email: "[email protected]"}); | ||
|
||
expect(response.status).toBe(404); | ||
expect(response.body.error).toBe('User not found'); | ||
}); | ||
|
||
}); |
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,2 +1 @@ | ||
|
||
export * from './authController'; | ||
export * from './authController'; |
Empty file.
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,19 @@ | ||
import jwt from 'jsonwebtoken'; | ||
import dotenv from 'dotenv'; | ||
|
||
dotenv.config(); | ||
|
||
const jwtSecretKey = process.env.JWT_SECRET; | ||
|
||
if (!jwtSecretKey) { | ||
throw new Error('JWT_SECRET is not defined in the environment variables.'); | ||
} | ||
|
||
export const verifiedToken = (token: string): any => { | ||
try { | ||
return jwt.verify(token, jwtSecretKey); | ||
} catch (err) { | ||
console.error(err); | ||
return null; | ||
} | ||
}; |
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.