Skip to content

Commit 2adfd3c

Browse files
authored
Merge pull request Ajared#68 from Ajared/feat/user-mgt
2 parents 4e27483 + 47a68da commit 2adfd3c

5 files changed

Lines changed: 496 additions & 0 deletions

File tree

backend/src/modules/admin/admin.controller.spec.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ const mockUserService = {
2222
reactivateUser: jest.fn().mockResolvedValue(undefined),
2323
listUsers: jest.fn().mockResolvedValue({ data: [], total: 0 }),
2424
assignLocationToUser: jest.fn().mockResolvedValue(undefined),
25+
deleteUser: jest.fn().mockResolvedValue(undefined),
26+
updateUserRole: jest.fn().mockResolvedValue(undefined),
27+
verifyUser: jest.fn().mockResolvedValue(undefined),
28+
verifyUsersBulk: jest.fn().mockResolvedValue(undefined),
2529
};
2630

2731
const mockAdminService = {
@@ -272,4 +276,86 @@ describe('AdminController', () => {
272276
await expect(controller.getStoreById(storeId)).rejects.toThrow(error);
273277
});
274278
});
279+
280+
describe('deleteUser', () => {
281+
it('should call userService.deleteUser with correct id and return the expected result', async () => {
282+
const userId = '123e4567-e89b-42d3-a456-426614174000';
283+
const req = {
284+
user: { sub: '123e4567-e89b-42d3-a456-426614174001' },
285+
} as Request & {
286+
user: { sub: string };
287+
};
288+
const expectedResult = {
289+
message: 'User Deletion operation successful',
290+
};
291+
mockUserService.deleteUser.mockResolvedValueOnce(expectedResult);
292+
293+
const result = await controller.deleteUser(userId, req);
294+
295+
expect(mockUserService.deleteUser).toHaveBeenCalledWith(
296+
userId,
297+
req.user.sub,
298+
);
299+
expect(result).toEqual(expectedResult);
300+
});
301+
302+
it('should handle errors from userService.deleteUser', async () => {
303+
const userId = '123e4567-e89b-42d3-a456-426614174000';
304+
const req = {
305+
user: { sub: '123e4567-e89b-42d3-a456-426614174001' },
306+
} as Request & {
307+
user: { sub: string };
308+
};
309+
const error = new Error('Deletion failed');
310+
mockUserService.deleteUser.mockRejectedValueOnce(error);
311+
312+
await expect(controller.deleteUser(userId, req)).rejects.toThrow(error);
313+
});
314+
});
315+
316+
describe('updateUserRole', () => {
317+
it('should call userService.updateUserRole with correct arguments and return the expected result', async () => {
318+
const userId = '123e4567-e89b-42d3-a456-426614174000';
319+
const updateUserRoleDto = { role: 'admin' as any };
320+
const req = {
321+
user: { sub: '123e4567-e89b-42d3-a456-426614174001' },
322+
} as Request & {
323+
user: { sub: string };
324+
};
325+
const expectedResult = {
326+
message: 'User Role Update operation successful',
327+
data: { id: userId, role: 'admin' },
328+
};
329+
mockUserService.updateUserRole.mockResolvedValueOnce(expectedResult);
330+
331+
const result = await controller.updateUserRole(
332+
userId,
333+
updateUserRoleDto,
334+
req,
335+
);
336+
337+
expect(mockUserService.updateUserRole).toHaveBeenCalledWith(
338+
userId,
339+
'admin',
340+
req.user.sub,
341+
);
342+
expect(result).toEqual(expectedResult);
343+
});
344+
345+
it('should handle errors from userService.updateUserRole', async () => {
346+
const userId = '123e4567-e89b-42d3-a456-426614174000';
347+
const updateUserRoleDto = { role: 'admin' as any };
348+
const req = {
349+
user: { sub: '123e4567-e89b-42d3-a456-426614174001' },
350+
} as Request & {
351+
user: { sub: string };
352+
};
353+
const error = new Error('Role update failed');
354+
mockUserService.updateUserRole.mockRejectedValueOnce(error);
355+
356+
await expect(
357+
controller.updateUserRole(userId, updateUserRoleDto, req),
358+
).rejects.toThrow(error);
359+
});
360+
});
275361
});

backend/src/modules/admin/admin.controller.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { UserRole } from '~/modules/user/constants/user.constant';
88
import {
99
Body,
1010
Controller,
11+
Delete,
1112
Get,
1213
HttpCode,
1314
HttpStatus,
@@ -25,6 +26,7 @@ import {
2526
AssignLocationDto,
2627
UserQueryValidator,
2728
BulkApproveUsersDto,
29+
UpdateUserRoleDto,
2830
} from '../user/dto/user.dto';
2931

3032
@Controller('admin')
@@ -112,4 +114,29 @@ export class AdminController {
112114
async getStoreById(@Param('id') id: string) {
113115
return this.adminService.getStoreById(id);
114116
}
117+
118+
@Mutation()
119+
@HttpCode(HttpStatus.OK)
120+
@Delete('users/:userId')
121+
async deleteUser(
122+
@Param('userId') userId: string,
123+
@Req() req: Request & { user: { sub: string } },
124+
) {
125+
return this.userService.deleteUser(userId, req.user.sub);
126+
}
127+
128+
@Mutation()
129+
@HttpCode(HttpStatus.OK)
130+
@Post('users/:userId/role')
131+
async updateUserRole(
132+
@Param('userId') userId: string,
133+
@Body() updateUserRoleDto: UpdateUserRoleDto,
134+
@Req() req: Request & { user: { sub: string } },
135+
) {
136+
return this.userService.updateUserRole(
137+
userId,
138+
updateUserRoleDto.role,
139+
req.user.sub,
140+
);
141+
}
115142
}

backend/src/modules/user/dto/user.dto.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
IsArray,
1010
IsUUID,
1111
} from 'class-validator';
12+
import { UserRole } from '../constants/user.constant';
1213
import { QueryValidator } from '~/helpers/query.helper';
1314
import { AuthProvider } from '~/modules/auth/constants/auth.constant';
1415

@@ -69,3 +70,9 @@ export class BulkApproveUsersDto {
6970
@IsUUID('4', { each: true })
7071
userIds: string[];
7172
}
73+
74+
export class UpdateUserRoleDto {
75+
@IsEnum(UserRole)
76+
@IsNotEmpty()
77+
role: UserRole;
78+
}

0 commit comments

Comments
 (0)