Skip to content

Commit 9e887ce

Browse files
committed
feat: handle not found + deny (delete) user
1 parent 56a6eb8 commit 9e887ce

2 files changed

Lines changed: 60 additions & 5 deletions

File tree

apps/backend/src/auth/auth.controller.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,28 @@ export class AuthController {
5959
}
6060
}
6161

62+
@Post('/admin-deny')
63+
@UseGuards(AuthGuard('jwt'))
64+
@UseInterceptors(CurrentUserInterceptor)
65+
async adminDeny(
66+
@Req() req: any,
67+
@Body() body: { email: string },
68+
): Promise<void> {
69+
if (req.user.status !== Status.ADMIN) {
70+
throw new ForbiddenException('Only admins can deny users');
71+
}
72+
try {
73+
await this.authService.deleteUser(body.email);
74+
} catch (e) {
75+
console.error('Admin deny error:', e);
76+
throw new BadRequestException(e.message);
77+
}
78+
const dbUsers = await this.usersService.find(body.email);
79+
if (dbUsers.length > 0) {
80+
await this.usersService.remove(dbUsers[0].id);
81+
}
82+
}
83+
6284
@Get('/users')
6385
@UseGuards(AuthGuard('jwt'))
6486
@UseInterceptors(CurrentUserInterceptor)

apps/frontend/src/containers/dashboard/UserManagement.tsx

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,23 @@ interface CombinedUser {
2020

2121
const ROWS_PER_PAGE = 13;
2222

23-
function RoleBadge({ role }: { role: string | null | undefined }) {
24-
if (!role) return null;
23+
function RoleBadge({
24+
role,
25+
isApproved,
26+
}: {
27+
role: string | null | undefined;
28+
isApproved?: boolean;
29+
}) {
30+
if (!role) {
31+
if (isApproved) {
32+
return (
33+
<span className="inline-flex items-center px-3 py-1 rounded-full text-sm leading-6 whitespace-nowrap bg-gray-100 text-gray-500 italic">
34+
Not Found
35+
</span>
36+
);
37+
}
38+
return null;
39+
}
2540
const isAdmin = role === 'ADMIN';
2641
return (
2742
<span
@@ -80,6 +95,17 @@ export const UserManagement: React.FC = () => {
8095
}
8196
};
8297

98+
const handleDeny = async (email: string) => {
99+
try {
100+
await (apiClient as any).axiosInstance.post('/api/auth/admin-deny', {
101+
email,
102+
});
103+
fetchUsers();
104+
} catch (err: any) {
105+
alert('Error: ' + err.message);
106+
}
107+
};
108+
83109
const filteredUsers = users
84110
.filter((u) =>
85111
activeTab === 'pending'
@@ -210,7 +236,10 @@ export const UserManagement: React.FC = () => {
210236
</div>
211237
</td>
212238
<td className="px-2">
213-
<RoleBadge role={user.dbUser?.status} />
239+
<RoleBadge
240+
role={user.dbUser?.status}
241+
isApproved={activeTab === 'approved'}
242+
/>
214243
</td>
215244
<td className="px-2 text-right">
216245
<div className="flex items-center justify-end gap-2 shrink-0">
@@ -227,6 +256,7 @@ export const UserManagement: React.FC = () => {
227256
</Button>
228257
<Button
229258
variant="outline"
259+
onClick={() => handleDeny(user.email)}
230260
className="rounded-[10px] px-3 py-1 h-auto text-sm leading-6 border-[#e5e5e5] text-black bg-white hover:bg-gray-50"
231261
>
232262
Deny
@@ -240,8 +270,11 @@ export const UserManagement: React.FC = () => {
240270
>
241271
Edit Role
242272
</Button>
243-
<Button className="rounded-[10px] px-3 py-1 h-auto text-sm leading-6 bg-[#893C27] text-white hover:bg-[#6c2f1f] border-0">
244-
Revoke Approval
273+
<Button
274+
onClick={() => handleDeny(user.email)}
275+
className="rounded-[10px] px-3 py-1 h-auto text-sm leading-6 bg-[#893C27] text-white hover:bg-[#6c2f1f] border-0"
276+
>
277+
Delete User
245278
</Button>
246279
</>
247280
)}

0 commit comments

Comments
 (0)