@hed-hog/core 0.0.278 → 0.0.285

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +60 -0
  2. package/dist/auth/auth.controller.d.ts +3 -3
  3. package/dist/auth/auth.service.d.ts +8 -8
  4. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +12 -0
  5. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts.map +1 -1
  6. package/dist/dashboard/dashboard-core/dashboard-core.controller.js +9 -0
  7. package/dist/dashboard/dashboard-core/dashboard-core.controller.js.map +1 -1
  8. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +12 -0
  9. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts.map +1 -1
  10. package/dist/dashboard/dashboard-core/dashboard-core.service.js +25 -0
  11. package/dist/dashboard/dashboard-core/dashboard-core.service.js.map +1 -1
  12. package/dist/file/file.controller.d.ts +2 -2
  13. package/dist/file/file.service.d.ts +4 -4
  14. package/dist/role/guards/role.guard.d.ts.map +1 -1
  15. package/dist/role/guards/role.guard.js +1 -1
  16. package/dist/role/guards/role.guard.js.map +1 -1
  17. package/dist/session/session.controller.d.ts +1 -1
  18. package/dist/session/session.service.d.ts +3 -3
  19. package/dist/user/user.controller.d.ts +2 -2
  20. package/dist/user/user.service.d.ts +6 -6
  21. package/hedhog/data/dashboard_component.yaml +95 -77
  22. package/hedhog/data/dashboard_component_role.yaml +91 -79
  23. package/hedhog/data/dashboard_item.yaml +121 -101
  24. package/hedhog/data/route.yaml +8 -0
  25. package/hedhog/frontend/app/ai_agent/page.tsx.ejs +69 -62
  26. package/hedhog/frontend/app/dashboard/[slug]/dashboard-content.tsx.ejs +23 -12
  27. package/hedhog/frontend/app/dashboard/components/draggable-grid.tsx.ejs +80 -5
  28. package/hedhog/frontend/app/dashboard/components/widgets/account-security.tsx.ejs +33 -29
  29. package/hedhog/frontend/app/dashboard/components/widgets/activity-timeline.tsx.ejs +18 -14
  30. package/hedhog/frontend/app/dashboard/components/widgets/email-notifications.tsx.ejs +39 -32
  31. package/hedhog/frontend/app/dashboard/components/widgets/login-history-chart.tsx.ejs +22 -19
  32. package/hedhog/frontend/app/dashboard/components/widgets/menus-card.tsx.ejs +58 -0
  33. package/hedhog/frontend/app/dashboard/components/widgets/routes-card.tsx.ejs +58 -0
  34. package/hedhog/frontend/app/dashboard/components/widgets/stat-access-level.tsx.ejs +18 -18
  35. package/hedhog/frontend/app/dashboard/components/widgets/stat-actions-today.tsx.ejs +18 -18
  36. package/hedhog/frontend/app/dashboard/components/widgets/stat-consecutive-days.tsx.ejs +18 -18
  37. package/hedhog/frontend/app/dashboard/components/widgets/stat-online-time.tsx.ejs +18 -18
  38. package/hedhog/frontend/app/dashboard/components/widgets/user-roles.tsx.ejs +15 -11
  39. package/hedhog/frontend/app/dashboard/components/widgets/user-sessions.tsx.ejs +39 -37
  40. package/hedhog/frontend/app/dashboard/dashboard.css.ejs +20 -4
  41. package/hedhog/frontend/app/mail/log/page.tsx.ejs +36 -47
  42. package/hedhog/frontend/app/mail/template/page.tsx.ejs +176 -126
  43. package/hedhog/frontend/app/menu/page.tsx.ejs +45 -39
  44. package/hedhog/frontend/app/roles/page.tsx.ejs +45 -46
  45. package/hedhog/frontend/app/users/page.tsx.ejs +70 -73
  46. package/hedhog/frontend/messages/en.json +15 -2
  47. package/hedhog/frontend/messages/pt.json +15 -2
  48. package/package.json +4 -4
  49. package/src/dashboard/dashboard-core/dashboard-core.controller.ts +5 -0
  50. package/src/dashboard/dashboard-core/dashboard-core.service.ts +34 -0
  51. package/src/role/guards/role.guard.ts +9 -8
@@ -1,6 +1,8 @@
1
1
  'use client';
2
2
 
3
3
  import {
4
+ EmptyState,
5
+ Page,
4
6
  PageHeader,
5
7
  PaginationFooter,
6
8
  SearchBar,
@@ -25,13 +27,6 @@ import {
25
27
  CardHeader,
26
28
  CardTitle,
27
29
  } from '@/components/ui/card';
28
- import {
29
- Dialog,
30
- DialogContent,
31
- DialogDescription,
32
- DialogHeader,
33
- DialogTitle,
34
- } from '@/components/ui/dialog';
35
30
  import {
36
31
  Form,
37
32
  FormControl,
@@ -422,7 +417,7 @@ export default function UserPage() {
422
417
  ];
423
418
 
424
419
  return (
425
- <div className="flex flex-col h-screen px-4">
420
+ <Page>
426
421
  <PageHeader
427
422
  breadcrumbs={[{ label: 'Home', href: '/' }, { label: t('users') }]}
428
423
  actions={[
@@ -487,10 +482,9 @@ export default function UserPage() {
487
482
  { label: t('filterOptionBlocked'), value: 'blocked' },
488
483
  ],
489
484
  }}
490
- className="mt-4"
491
485
  />
492
486
 
493
- <div className="flex-1 pt-4">
487
+ <div className="flex-1 ">
494
488
  {isLoading && (
495
489
  <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
496
490
  {Array.from({ length: 3 }).map((_, i) => (
@@ -522,7 +516,13 @@ export default function UserPage() {
522
516
  )}
523
517
 
524
518
  {(paginate?.data?.length || 0) === 0 ? (
525
- <p className="text-sm text-muted-foreground">{t('noUsersFound')}</p>
519
+ <EmptyState
520
+ icon={<Users className="h-12 w-12" />}
521
+ title={t('noUsersFound')}
522
+ description={t('description')}
523
+ actionLabel={t('buttonAddUser')}
524
+ onAction={() => setIsDialogOpen(true)}
525
+ />
526
526
  ) : (
527
527
  <div className="grid gap-4 grid-cols-1 lg:grid-cols-2 xl:grid-cols-3">
528
528
  {paginate?.data?.map((user: User) => (
@@ -679,17 +679,17 @@ export default function UserPage() {
679
679
  />
680
680
  </div>
681
681
 
682
- <Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
683
- <DialogContent className="sm:max-w-lg">
684
- <DialogHeader>
685
- <DialogTitle>{t('dialogAddUserTitle')}</DialogTitle>
686
- <DialogDescription>{t('description')}</DialogDescription>
687
- </DialogHeader>
682
+ <Sheet open={isDialogOpen} onOpenChange={setIsDialogOpen}>
683
+ <SheetContent className="w-full sm:max-w-lg overflow-y-auto gap-0">
684
+ <SheetHeader>
685
+ <SheetTitle>{t('dialogAddUserTitle')}</SheetTitle>
686
+ <SheetDescription>{t('description')}</SheetDescription>
687
+ </SheetHeader>
688
688
  <div className="w-full border-t pt-1 mt-1" />
689
689
  <Form {...form}>
690
690
  <form
691
691
  onSubmit={form.handleSubmit(onSubmit)}
692
- className="space-y-4"
692
+ className="px-4 gap-4 w-full flex flex-col pt-2"
693
693
  >
694
694
  <FormField
695
695
  control={form.control}
@@ -772,8 +772,8 @@ export default function UserPage() {
772
772
  </Button>
773
773
  </form>
774
774
  </Form>
775
- </DialogContent>
776
- </Dialog>
775
+ </SheetContent>
776
+ </Sheet>
777
777
 
778
778
  {editingUser && (
779
779
  <Sheet
@@ -1157,36 +1157,29 @@ export default function UserPage() {
1157
1157
  </Button>
1158
1158
  </div>
1159
1159
 
1160
- <Dialog
1160
+ <AlertDialog
1161
1161
  open={openDeleteModal}
1162
1162
  onOpenChange={setOpenDeleteModal}
1163
1163
  >
1164
- <DialogContent className="sm:max-w-lg">
1165
- <DialogHeader>
1166
- <DialogTitle>{t('dialogDeleteUserTitle')}</DialogTitle>
1167
- <DialogDescription>
1164
+ <AlertDialogContent>
1165
+ <AlertDialogHeader>
1166
+ <AlertDialogTitle>
1167
+ {t('dialogDeleteUserTitle')}
1168
+ </AlertDialogTitle>
1169
+ <AlertDialogDescription>
1168
1170
  {t('dialogDeleteUserDescription')}
1169
- </DialogDescription>
1170
- </DialogHeader>
1171
- <hr className="mt-4" />
1172
- <div className="flex justify-end">
1173
- <Button
1174
- type="button"
1175
- className="px-4 w-28 h-12 py-2 bg-gray-300 text-black hover:bg-gray-300 hover:text-black rounded-sm mr-2 text-md"
1176
- onClick={() => setOpenDeleteModal(false)}
1177
- >
1171
+ </AlertDialogDescription>
1172
+ </AlertDialogHeader>
1173
+ <AlertDialogFooter>
1174
+ <AlertDialogCancel>
1178
1175
  {t('deleteUserCancel')}
1179
- </Button>
1180
- <Button
1181
- onClick={onDelete}
1182
- variant="destructive"
1183
- className="px-4 w-32 h-12 py-2 text-white hover:text-white rounded-sm text-md cursor-pointer"
1184
- >
1176
+ </AlertDialogCancel>
1177
+ <AlertDialogAction onClick={onDelete}>
1185
1178
  {t('deleteUserConfirm')}
1186
- </Button>
1187
- </div>
1188
- </DialogContent>
1189
- </Dialog>
1179
+ </AlertDialogAction>
1180
+ </AlertDialogFooter>
1181
+ </AlertDialogContent>
1182
+ </AlertDialog>
1190
1183
  </TabsContent>
1191
1184
 
1192
1185
  <TabsContent value="edit" className="space-y-4 mt-4 p-4 pt-0">
@@ -1232,27 +1225,29 @@ export default function UserPage() {
1232
1225
  value="credentials"
1233
1226
  className="space-y-4 mt-4 p-4 pt-0"
1234
1227
  >
1235
- <Card className="border-amber-200 bg-amber-50/50">
1236
- <CardHeader className="pb-2">
1237
- <CardTitle className="text-sm">
1228
+ <div className="space-y-3 rounded-lg border p-4">
1229
+ <div>
1230
+ <h4 className="text-sm font-semibold">
1238
1231
  {t('passwordResetTitle')}
1239
- </CardTitle>
1240
- <CardDescription>
1232
+ </h4>
1233
+ <p className="text-xs text-muted-foreground mt-1">
1241
1234
  {t('passwordResetDescription')}
1242
- </CardDescription>
1243
- </CardHeader>
1244
- <CardContent className="flex flex-col gap-3">
1245
- <div className="text-xs text-muted-foreground">
1246
- {t('passwordResetNotice')}
1247
- </div>
1248
- <div>
1249
- <Button type="button" onClick={openResetPasswordDialog}>
1250
- <RefreshCcw className="h-4 w-4 mr-2" />
1251
- {t('buttonResetPassword')}
1252
- </Button>
1253
- </div>
1254
- </CardContent>
1255
- </Card>
1235
+ </p>
1236
+ </div>
1237
+ <p className="text-xs text-muted-foreground">
1238
+ {t('passwordResetNotice')}
1239
+ </p>
1240
+ <div className="flex flex-col gap-2">
1241
+ <Button
1242
+ type="button"
1243
+ onClick={openResetPasswordDialog}
1244
+ className="w-full sm:w-fit"
1245
+ >
1246
+ <RefreshCcw className="h-4 w-4 mr-2" />
1247
+ {t('buttonResetPassword')}
1248
+ </Button>
1249
+ </div>
1250
+ </div>
1256
1251
 
1257
1252
  <div className="space-y-3">
1258
1253
  <h4 className="text-sm font-medium">
@@ -1422,7 +1417,7 @@ export default function UserPage() {
1422
1417
  </AlertDialogContent>
1423
1418
  </AlertDialog>
1424
1419
 
1425
- <Dialog
1420
+ <AlertDialog
1426
1421
  open={isResetResultDialogOpen}
1427
1422
  onOpenChange={(open) => {
1428
1423
  setIsResetResultDialogOpen(open);
@@ -1432,13 +1427,15 @@ export default function UserPage() {
1432
1427
  }
1433
1428
  }}
1434
1429
  >
1435
- <DialogContent className="sm:max-w-lg">
1436
- <DialogHeader>
1437
- <DialogTitle>{t('passwordResultTitle')}</DialogTitle>
1438
- <DialogDescription>
1430
+ <AlertDialogContent>
1431
+ <AlertDialogHeader>
1432
+ <AlertDialogTitle>
1433
+ {t('passwordResultTitle')}
1434
+ </AlertDialogTitle>
1435
+ <AlertDialogDescription>
1439
1436
  {t('passwordResultDescription')}
1440
- </DialogDescription>
1441
- </DialogHeader>
1437
+ </AlertDialogDescription>
1438
+ </AlertDialogHeader>
1442
1439
 
1443
1440
  <div className="space-y-3">
1444
1441
  <div className="relative">
@@ -1484,8 +1481,8 @@ export default function UserPage() {
1484
1481
  </Button>
1485
1482
  </div>
1486
1483
  </div>
1487
- </DialogContent>
1488
- </Dialog>
1484
+ </AlertDialogContent>
1485
+ </AlertDialog>
1489
1486
  </TabsContent>
1490
1487
 
1491
1488
  <TabsContent
@@ -1573,6 +1570,6 @@ export default function UserPage() {
1573
1570
  </Sheet>
1574
1571
  )}
1575
1572
  </div>
1576
- </div>
1573
+ </Page>
1577
1574
  );
1578
1575
  }
@@ -329,6 +329,9 @@
329
329
  "newTemplate": "New Template",
330
330
  "title": "Email Templates",
331
331
  "description": "Manage your email templates",
332
+ "searchPlaceholder": "Search templates by slug or subject...",
333
+ "noTemplatesFound": "No templates found",
334
+ "noTemplatesHint": "Create your first template to start sending emails.",
332
335
  "tableSlug": "Slug",
333
336
  "tableSubject": "Subject",
334
337
  "tableVariables": "Variables",
@@ -849,6 +852,8 @@
849
852
  "noLogsFound": "No email logs found",
850
853
  "adjustSearch": "Try adjusting your search terms",
851
854
  "noEmailsSent": "No emails have been sent yet",
855
+ "clearSearch": "Clear search",
856
+ "refreshList": "Refresh list",
852
857
  "viewDetails": "View Details",
853
858
  "emailDetails": "Email Details",
854
859
  "detailsDescription": "Complete information about the sent email",
@@ -1044,10 +1049,12 @@
1044
1049
  "extraLarge": "Extra Large",
1045
1050
  "clearSize": "Clear Size",
1046
1051
  "heading": "Heading",
1052
+ "alignment": "Alignment",
1047
1053
  "alignLeft": "Align Left",
1048
1054
  "alignCenter": "Center",
1049
1055
  "alignRight": "Align Right",
1050
1056
  "justify": "Justify",
1057
+ "lists": "Lists",
1051
1058
  "bulletList": "Bullet List",
1052
1059
  "numberedList": "Numbered List",
1053
1060
  "addLink": "Add Link",
@@ -1061,6 +1068,7 @@
1061
1068
  "clearFormatting": "Clear Formatting",
1062
1069
  "undo": "Undo",
1063
1070
  "redo": "Redo",
1071
+ "more": "More",
1064
1072
  "advancedMode": "Advanced Mode (HTML)",
1065
1073
  "advancedModeTitle": "Advanced Mode - HTML Editor",
1066
1074
  "advancedModeDescription": "Edit HTML directly with syntax highlighting and automatic indentation",
@@ -1160,8 +1168,11 @@
1160
1168
  },
1161
1169
  "ForbiddenDialog": {
1162
1170
  "title": "Access Denied",
1163
- "defaultMessage": "You do not have permission to access this resource.",
1164
- "understood": "Understood"
1171
+ "defaultMessage": "You do not have access to request this resource.",
1172
+ "understood": "Understood",
1173
+ "statusCode": "Status",
1174
+ "method": "Method",
1175
+ "url": "URL"
1165
1176
  },
1166
1177
  "ForbiddenPage": {
1167
1178
  "message": "Forbidden: You don't have permission to access this page.",
@@ -1174,6 +1185,8 @@
1174
1185
  "sessionsToday": "Sessions Today",
1175
1186
  "emailsSent": "E-mails Sent",
1176
1187
  "permissions": "Permissions",
1188
+ "menus": "Menus",
1189
+ "routes": "Routes",
1177
1190
  "userGrowthTitle": "User Growth",
1178
1191
  "userGrowthDescription": "Monthly evolution of users and sessions",
1179
1192
  "users": "Users",
@@ -329,6 +329,9 @@
329
329
  "newTemplate": "Novo Template",
330
330
  "title": "Templates de E-mail",
331
331
  "description": "Gerencie seus templates de e-mail",
332
+ "searchPlaceholder": "Buscar templates por slug ou assunto...",
333
+ "noTemplatesFound": "Nenhum template encontrado",
334
+ "noTemplatesHint": "Crie o primeiro template para começar a enviar e-mails.",
332
335
  "tableSlug": "Slug",
333
336
  "tableSubject": "Assunto",
334
337
  "tableVariables": "Variáveis",
@@ -852,6 +855,8 @@
852
855
  "noLogsFound": "Nenhum log de e-mail encontrado",
853
856
  "adjustSearch": "Tente ajustar seus termos de busca",
854
857
  "noEmailsSent": "Nenhum e-mail foi enviado ainda",
858
+ "clearSearch": "Limpar busca",
859
+ "refreshList": "Atualizar lista",
855
860
  "viewDetails": "Ver Detalhes",
856
861
  "emailDetails": "Detalhes do E-mail",
857
862
  "detailsDescription": "Informações completas sobre o e-mail enviado",
@@ -1049,10 +1054,12 @@
1049
1054
  "extraLarge": "Extra Grande",
1050
1055
  "clearSize": "Limpar Tamanho",
1051
1056
  "heading": "Título",
1057
+ "alignment": "Alinhamento",
1052
1058
  "alignLeft": "Alinhar à Esquerda",
1053
1059
  "alignCenter": "Centralizar",
1054
1060
  "alignRight": "Alinhar à Direita",
1055
1061
  "justify": "Justificar",
1062
+ "lists": "Listas",
1056
1063
  "bulletList": "Lista com Marcadores",
1057
1064
  "numberedList": "Lista Numerada",
1058
1065
  "addLink": "Adicionar Link",
@@ -1066,6 +1073,7 @@
1066
1073
  "clearFormatting": "Limpar Formatação",
1067
1074
  "undo": "Desfazer",
1068
1075
  "redo": "Refazer",
1076
+ "more": "Mais",
1069
1077
  "advancedMode": "Modo Avançado (HTML)",
1070
1078
  "advancedModeTitle": "Modo Avançado - Editor HTML",
1071
1079
  "advancedModeDescription": "Edite o HTML diretamente com syntax highlighting e indentação automática",
@@ -1215,8 +1223,11 @@
1215
1223
  },
1216
1224
  "ForbiddenDialog": {
1217
1225
  "title": "Acesso Negado",
1218
- "defaultMessage": "Você não tem permissão para acessar este recurso.",
1219
- "understood": "Entendi"
1226
+ "defaultMessage": "Você não tem acesso para solicitar este recurso.",
1227
+ "understood": "Entendi",
1228
+ "statusCode": "Status",
1229
+ "method": "Método",
1230
+ "url": "URL"
1220
1231
  },
1221
1232
  "ForbiddenPage": {
1222
1233
  "message": "Proibido: Você não tem permissão para acessar esta página.",
@@ -1229,6 +1240,8 @@
1229
1240
  "sessionsToday": "Sessões Hoje",
1230
1241
  "emailsSent": "E-mails Enviados",
1231
1242
  "permissions": "Permissões",
1243
+ "menus": "Menus",
1244
+ "routes": "Rotas",
1232
1245
  "userGrowthTitle": "Crescimento de Usuários",
1233
1246
  "userGrowthDescription": "Evolução mensal de usuários e sessões",
1234
1247
  "users": "Usuários",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hed-hog/core",
3
- "version": "0.0.278",
3
+ "version": "0.0.285",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "dependencies": {
@@ -32,10 +32,10 @@
32
32
  "uuid": "^11.1.0",
33
33
  "@hed-hog/api-pagination": "0.0.6",
34
34
  "@hed-hog/api-types": "0.0.1",
35
- "@hed-hog/api-prisma": "0.0.5",
35
+ "@hed-hog/api": "0.0.4",
36
36
  "@hed-hog/api-mail": "0.0.8",
37
- "@hed-hog/api-locale": "0.0.13",
38
- "@hed-hog/api": "0.0.4"
37
+ "@hed-hog/api-prisma": "0.0.5",
38
+ "@hed-hog/api-locale": "0.0.13"
39
39
  },
40
40
  "exports": {
41
41
  ".": {
@@ -23,6 +23,11 @@ export class DashboardCoreController {
23
23
  return this.dashboardCoreService.getMailStatistics();
24
24
  }
25
25
 
26
+ @Get('stats/overview/system')
27
+ getSystemStatistics() {
28
+ return this.dashboardCoreService.getSystemStatistics();
29
+ }
30
+
26
31
  @Get('widgets/me')
27
32
  getWidgetsData(@User() user, @Locale() locale: string) {
28
33
  return this.dashboardCoreService.getWidgetsData(user.id, locale);
@@ -297,6 +297,40 @@ export class DashboardCoreService {
297
297
  };
298
298
  }
299
299
 
300
+ async getSystemStatistics() {
301
+ const now = new Date();
302
+ const currentMonthStart = new Date(now.getFullYear(), now.getMonth(), 1);
303
+ const lastMonthStart = new Date(now.getFullYear(), now.getMonth() - 1, 1);
304
+ const lastMonthEnd = new Date(now.getFullYear(), now.getMonth(), 0, 23, 59, 59);
305
+
306
+ const [
307
+ menusCount,
308
+ routesCount,
309
+ menusCurrentMonth,
310
+ menusLastMonth,
311
+ ] = await Promise.all([
312
+ this.prismaService.menu.count(),
313
+ this.prismaService.route.count(),
314
+ this.prismaService.menu.count({ where: { created_at: { gte: currentMonthStart } } }),
315
+ this.prismaService.menu.count({ where: { created_at: { gte: lastMonthStart, lte: lastMonthEnd } } }),
316
+ ]);
317
+
318
+ const menusChange = this.calculateChange(menusCurrentMonth, menusLastMonth);
319
+
320
+ return {
321
+ cards: {
322
+ menus: {
323
+ value: menusCount,
324
+ change: menusChange,
325
+ },
326
+ routes: {
327
+ value: routesCount,
328
+ change: null,
329
+ },
330
+ },
331
+ };
332
+ }
333
+
300
334
  async getUserLayout(userId: number, slug: string, localeCode: string) {
301
335
  const dashboard = await this.prismaService.dashboard.findFirst({ where: { slug } });
302
336
 
@@ -2,13 +2,14 @@ import { IS_PUBLIC_KEY, WITH_ROLE } from '@hed-hog/api';
2
2
  import { getLocaleText } from '@hed-hog/api-locale';
3
3
  import { PrismaService } from '@hed-hog/api-prisma';
4
4
  import {
5
- CanActivate,
6
- ExecutionContext,
7
- forwardRef,
8
- Inject,
9
- Injectable,
10
- RequestMethod,
11
- UnauthorizedException,
5
+ CanActivate,
6
+ ExecutionContext,
7
+ ForbiddenException,
8
+ forwardRef,
9
+ Inject,
10
+ Injectable,
11
+ RequestMethod,
12
+ UnauthorizedException,
12
13
  } from '@nestjs/common';
13
14
  import { METHOD_METADATA } from '@nestjs/common/constants';
14
15
  import { Reflector } from '@nestjs/core';
@@ -130,7 +131,7 @@ export class RoleGuard implements CanActivate {
130
131
  .replace('{{method}}', httpMethod)
131
132
  .replace('{{path}}', fullPath);
132
133
 
133
- throw new UnauthorizedException(message);
134
+ throw new ForbiddenException(message);
134
135
  }
135
136
 
136
137
  const hasPendingPasswordReset = await this.prisma.user_credential.findFirst({