@hed-hog/core 0.0.353 → 0.0.354
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.
- package/dist/core.module.d.ts.map +1 -1
- package/dist/core.module.js +7 -4
- package/dist/core.module.js.map +1 -1
- package/dist/file/file.controller.d.ts +3 -3
- package/dist/file/file.controller.d.ts.map +1 -1
- package/dist/file/file.controller.js +7 -3
- package/dist/file/file.controller.js.map +1 -1
- package/dist/file/file.service.d.ts +1 -0
- package/dist/file/file.service.d.ts.map +1 -1
- package/dist/file/file.service.js +10 -1
- package/dist/file/file.service.js.map +1 -1
- package/dist/integration/services/outbox-polling.coordinator.d.ts.map +1 -1
- package/dist/integration/services/outbox-polling.coordinator.js +0 -1
- package/dist/integration/services/outbox-polling.coordinator.js.map +1 -1
- package/dist/locale/dto/create-locale.dto.d.ts +7 -0
- package/dist/locale/dto/create-locale.dto.d.ts.map +1 -0
- package/dist/locale/dto/create-locale.dto.js +37 -0
- package/dist/locale/dto/create-locale.dto.js.map +1 -0
- package/dist/locale/locale.controller.d.ts +26 -0
- package/dist/locale/locale.controller.d.ts.map +1 -0
- package/dist/locale/locale.controller.js +54 -0
- package/dist/locale/locale.controller.js.map +1 -0
- package/dist/locale/locale.module.d.ts +3 -0
- package/dist/locale/locale.module.d.ts.map +1 -0
- package/dist/locale/locale.module.js +31 -0
- package/dist/locale/locale.module.js.map +1 -0
- package/dist/locale/locale.service.d.ts +27 -0
- package/dist/locale/locale.service.d.ts.map +1 -0
- package/dist/locale/locale.service.js +55 -0
- package/dist/locale/locale.service.js.map +1 -0
- package/dist/mail-profile/mail-profile.controller.d.ts +3 -3
- package/dist/mail-profile/mail-profile.service.d.ts +3 -3
- package/dist/mail-sent/mail-sent.controller.d.ts +3 -3
- package/dist/mail-sent/mail-sent.service.d.ts +3 -3
- package/dist/notification/notification.service.d.ts +1 -0
- package/dist/notification/notification.service.d.ts.map +1 -1
- package/dist/notification/notification.service.js +36 -4
- package/dist/notification/notification.service.js.map +1 -1
- package/dist/setting/setting.service.d.ts.map +1 -1
- package/dist/setting/setting.service.js +2 -0
- package/dist/setting/setting.service.js.map +1 -1
- package/hedhog/data/route.yaml +24 -0
- package/hedhog/data/setting_group.yaml +20 -2
- package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +22 -22
- package/hedhog/frontend/app/dashboard/components/add-widget-selector-dialog.tsx.ejs +3 -3
- package/hedhog/frontend/app/integrations-webhooks/page.tsx.ejs +15 -21
- package/hedhog/frontend/app/mail/log/page.tsx.ejs +3 -3
- package/hedhog/frontend/app/mail/profiles/page.tsx.ejs +3 -6
- package/hedhog/frontend/app/mail/template/page.tsx.ejs +3 -6
- package/hedhog/frontend/messages/en.json +1 -0
- package/hedhog/frontend/messages/pt.json +1 -0
- package/package.json +3 -3
- package/src/core.module.ts +7 -4
- package/src/file/file.controller.ts +11 -6
- package/src/file/file.service.ts +15 -1
- package/src/integration/services/outbox-polling.coordinator.ts +0 -3
- package/src/locale/dto/create-locale.dto.ts +19 -0
- package/src/locale/locale.controller.ts +35 -0
- package/src/locale/locale.module.ts +18 -0
- package/src/locale/locale.service.ts +48 -0
- package/src/notification/notification.service.ts +51 -12
- package/src/setting/setting.service.ts +8 -6
|
@@ -32,9 +32,9 @@ import {
|
|
|
32
32
|
SelectTrigger,
|
|
33
33
|
SelectValue,
|
|
34
34
|
} from '@/components/ui/select';
|
|
35
|
+
import { ResizableSheetContent } from '@/components/ui/resizable-sheet-content';
|
|
35
36
|
import {
|
|
36
37
|
Sheet,
|
|
37
|
-
SheetContent,
|
|
38
38
|
SheetDescription,
|
|
39
39
|
SheetHeader,
|
|
40
40
|
SheetTitle,
|
|
@@ -1707,7 +1707,7 @@ export default function IntegrationsWebhooksPage() {
|
|
|
1707
1707
|
</Tabs>
|
|
1708
1708
|
|
|
1709
1709
|
<Sheet open={catalogOpen} onOpenChange={setCatalogOpen}>
|
|
1710
|
-
<
|
|
1710
|
+
<ResizableSheetContent sheetId="webhooks-catalog-form" defaultWidth={672}>
|
|
1711
1711
|
<SheetHeader>
|
|
1712
1712
|
<SheetTitle>
|
|
1713
1713
|
{catalogEdit ? t('editEvent') : t('newEvent')}
|
|
@@ -1764,7 +1764,7 @@ export default function IntegrationsWebhooksPage() {
|
|
|
1764
1764
|
t={t}
|
|
1765
1765
|
/>
|
|
1766
1766
|
</div>
|
|
1767
|
-
</
|
|
1767
|
+
</ResizableSheetContent>
|
|
1768
1768
|
</Sheet>
|
|
1769
1769
|
|
|
1770
1770
|
<Sheet
|
|
@@ -1782,7 +1782,7 @@ export default function IntegrationsWebhooksPage() {
|
|
|
1782
1782
|
}
|
|
1783
1783
|
}}
|
|
1784
1784
|
>
|
|
1785
|
-
<
|
|
1785
|
+
<ResizableSheetContent sheetId="webhooks-incoming-form" defaultWidth={1024}>
|
|
1786
1786
|
<SheetHeader>
|
|
1787
1787
|
<SheetTitle>
|
|
1788
1788
|
{incomingEdit ? t('editIncoming') : t('newIncoming')}
|
|
@@ -2272,10 +2272,7 @@ export default function IntegrationsWebhooksPage() {
|
|
|
2272
2272
|
}
|
|
2273
2273
|
}}
|
|
2274
2274
|
>
|
|
2275
|
-
<
|
|
2276
|
-
side="right"
|
|
2277
|
-
className="w-full overflow-y-auto sm:max-w-3xl"
|
|
2278
|
-
>
|
|
2275
|
+
<ResizableSheetContent sheetId="webhooks-action-form" defaultWidth={768}>
|
|
2279
2276
|
<SheetHeader>
|
|
2280
2277
|
<SheetTitle>
|
|
2281
2278
|
{actionEdit ? t('updated') : t('addAction')}
|
|
@@ -2659,13 +2656,13 @@ export default function IntegrationsWebhooksPage() {
|
|
|
2659
2656
|
t={t}
|
|
2660
2657
|
/>
|
|
2661
2658
|
</div>
|
|
2662
|
-
</
|
|
2659
|
+
</ResizableSheetContent>
|
|
2663
2660
|
</Sheet>
|
|
2664
|
-
</
|
|
2661
|
+
</ResizableSheetContent>
|
|
2665
2662
|
</Sheet>
|
|
2666
2663
|
|
|
2667
2664
|
<Sheet open={eventWebhookOpen} onOpenChange={setEventWebhookOpen}>
|
|
2668
|
-
<
|
|
2665
|
+
<ResizableSheetContent sheetId="webhooks-event-webhook-form" defaultWidth={1024}>
|
|
2669
2666
|
<SheetHeader>
|
|
2670
2667
|
<SheetTitle>
|
|
2671
2668
|
{eventWebhookEdit ? t('editEventWebhook') : t('newEventWebhook')}
|
|
@@ -2844,7 +2841,7 @@ export default function IntegrationsWebhooksPage() {
|
|
|
2844
2841
|
t={t}
|
|
2845
2842
|
/>
|
|
2846
2843
|
</div>
|
|
2847
|
-
</
|
|
2844
|
+
</ResizableSheetContent>
|
|
2848
2845
|
</Sheet>
|
|
2849
2846
|
|
|
2850
2847
|
<Sheet
|
|
@@ -2859,7 +2856,7 @@ export default function IntegrationsWebhooksPage() {
|
|
|
2859
2856
|
}
|
|
2860
2857
|
}}
|
|
2861
2858
|
>
|
|
2862
|
-
<
|
|
2859
|
+
<ResizableSheetContent sheetId="webhooks-mail-profile-editor" defaultWidth={896}>
|
|
2863
2860
|
<SheetHeader>
|
|
2864
2861
|
<SheetTitle>Editar perfil de e-mail</SheetTitle>
|
|
2865
2862
|
<SheetDescription>
|
|
@@ -3130,7 +3127,7 @@ export default function IntegrationsWebhooksPage() {
|
|
|
3130
3127
|
)}
|
|
3131
3128
|
</div>
|
|
3132
3129
|
</div>
|
|
3133
|
-
</
|
|
3130
|
+
</ResizableSheetContent>
|
|
3134
3131
|
</Sheet>
|
|
3135
3132
|
|
|
3136
3133
|
<Sheet
|
|
@@ -3143,7 +3140,7 @@ export default function IntegrationsWebhooksPage() {
|
|
|
3143
3140
|
}
|
|
3144
3141
|
}}
|
|
3145
3142
|
>
|
|
3146
|
-
<
|
|
3143
|
+
<ResizableSheetContent sheetId="webhooks-mail-template-editor" defaultWidth={896}>
|
|
3147
3144
|
<SheetHeader>
|
|
3148
3145
|
<SheetTitle>Editar template de e-mail</SheetTitle>
|
|
3149
3146
|
<SheetDescription>
|
|
@@ -3230,17 +3227,14 @@ export default function IntegrationsWebhooksPage() {
|
|
|
3230
3227
|
t={t}
|
|
3231
3228
|
/>
|
|
3232
3229
|
</div>
|
|
3233
|
-
</
|
|
3230
|
+
</ResizableSheetContent>
|
|
3234
3231
|
</Sheet>
|
|
3235
3232
|
|
|
3236
3233
|
<Sheet
|
|
3237
3234
|
open={Boolean(selectedLog)}
|
|
3238
3235
|
onOpenChange={(open) => !open && setSelectedLog(null)}
|
|
3239
3236
|
>
|
|
3240
|
-
<
|
|
3241
|
-
side="right"
|
|
3242
|
-
className="w-full overflow-y-auto sm:max-w-3xl"
|
|
3243
|
-
>
|
|
3237
|
+
<ResizableSheetContent sheetId="webhooks-log-detail" defaultWidth={768}>
|
|
3244
3238
|
<SheetHeader>
|
|
3245
3239
|
<SheetTitle>{t('logDetailTitle')}</SheetTitle>
|
|
3246
3240
|
<SheetDescription>
|
|
@@ -3415,7 +3409,7 @@ export default function IntegrationsWebhooksPage() {
|
|
|
3415
3409
|
) : null}
|
|
3416
3410
|
</div>
|
|
3417
3411
|
) : null}
|
|
3418
|
-
</
|
|
3412
|
+
</ResizableSheetContent>
|
|
3419
3413
|
</Sheet>
|
|
3420
3414
|
|
|
3421
3415
|
<AlertDialog
|
|
@@ -14,9 +14,9 @@ import { Card, CardContent } from '@/components/ui/card';
|
|
|
14
14
|
import { Input } from '@/components/ui/input';
|
|
15
15
|
import { KpiCardsGrid, type KpiCardItem } from '@/components/ui/kpi-cards-grid';
|
|
16
16
|
import { ScrollArea } from '@/components/ui/scroll-area';
|
|
17
|
+
import { ResizableSheetContent } from '@/components/ui/resizable-sheet-content';
|
|
17
18
|
import {
|
|
18
19
|
Sheet,
|
|
19
|
-
SheetContent,
|
|
20
20
|
SheetDescription,
|
|
21
21
|
SheetHeader,
|
|
22
22
|
SheetTitle,
|
|
@@ -564,7 +564,7 @@ export default function MailLogPage() {
|
|
|
564
564
|
|
|
565
565
|
{selectedLog && (
|
|
566
566
|
<Sheet open={isDetailSheetOpen} onOpenChange={setIsDetailSheetOpen}>
|
|
567
|
-
<
|
|
567
|
+
<ResizableSheetContent sheetId="mail-log-detail" defaultWidth={672}>
|
|
568
568
|
<SheetHeader>
|
|
569
569
|
<SheetTitle>{t('emailDetails')}</SheetTitle>
|
|
570
570
|
<SheetDescription>{t('detailsDescription')}</SheetDescription>
|
|
@@ -709,7 +709,7 @@ export default function MailLogPage() {
|
|
|
709
709
|
</div>
|
|
710
710
|
</div>
|
|
711
711
|
</ScrollArea>
|
|
712
|
-
</
|
|
712
|
+
</ResizableSheetContent>
|
|
713
713
|
</Sheet>
|
|
714
714
|
)}
|
|
715
715
|
</Page>
|
|
@@ -30,9 +30,9 @@ import {
|
|
|
30
30
|
SelectTrigger,
|
|
31
31
|
SelectValue,
|
|
32
32
|
} from '@/components/ui/select';
|
|
33
|
+
import { ResizableSheetContent } from '@/components/ui/resizable-sheet-content';
|
|
33
34
|
import {
|
|
34
35
|
Sheet,
|
|
35
|
-
SheetContent,
|
|
36
36
|
SheetDescription,
|
|
37
37
|
SheetHeader,
|
|
38
38
|
SheetTitle,
|
|
@@ -462,10 +462,7 @@ export default function MailProfilesPage() {
|
|
|
462
462
|
/>
|
|
463
463
|
|
|
464
464
|
<Sheet open={isDialogOpen} onOpenChange={setIsDialogOpen}>
|
|
465
|
-
<
|
|
466
|
-
side="right"
|
|
467
|
-
className="w-full max-w-[95vw] overflow-y-auto sm:max-w-4xl"
|
|
468
|
-
>
|
|
465
|
+
<ResizableSheetContent sheetId="mail-profile-editor" defaultWidth={896}>
|
|
469
466
|
<SheetHeader>
|
|
470
467
|
<SheetTitle>
|
|
471
468
|
{editMode ? t('editProfile') : t('newProfileTitle')}
|
|
@@ -795,7 +792,7 @@ export default function MailProfilesPage() {
|
|
|
795
792
|
)}
|
|
796
793
|
</div>
|
|
797
794
|
</form>
|
|
798
|
-
</
|
|
795
|
+
</ResizableSheetContent>
|
|
799
796
|
</Sheet>
|
|
800
797
|
|
|
801
798
|
<AlertDialog
|
|
@@ -39,9 +39,9 @@ import {
|
|
|
39
39
|
SelectTrigger,
|
|
40
40
|
SelectValue,
|
|
41
41
|
} from '@/components/ui/select';
|
|
42
|
+
import { ResizableSheetContent } from '@/components/ui/resizable-sheet-content';
|
|
42
43
|
import {
|
|
43
44
|
Sheet,
|
|
44
|
-
SheetContent,
|
|
45
45
|
SheetDescription,
|
|
46
46
|
SheetHeader,
|
|
47
47
|
SheetTitle,
|
|
@@ -892,10 +892,7 @@ export default function EmailTemplatesPage() {
|
|
|
892
892
|
/>
|
|
893
893
|
|
|
894
894
|
<Sheet open={isDialogOpen} onOpenChange={setIsDialogOpen}>
|
|
895
|
-
<
|
|
896
|
-
side="right"
|
|
897
|
-
className="w-full max-w-[95vw] overflow-y-auto sm:max-w-6xl"
|
|
898
|
-
>
|
|
895
|
+
<ResizableSheetContent sheetId="mail-template-editor" defaultWidth={1152}>
|
|
899
896
|
<SheetHeader>
|
|
900
897
|
<SheetTitle>
|
|
901
898
|
{editMode ? t('editTemplate') : t('newTemplateTitle')}
|
|
@@ -1066,7 +1063,7 @@ export default function EmailTemplatesPage() {
|
|
|
1066
1063
|
</Button>
|
|
1067
1064
|
</div>
|
|
1068
1065
|
</form>
|
|
1069
|
-
</
|
|
1066
|
+
</ResizableSheetContent>
|
|
1070
1067
|
</Sheet>
|
|
1071
1068
|
|
|
1072
1069
|
<Dialog
|
|
@@ -1941,6 +1941,7 @@
|
|
|
1941
1941
|
"newConversation": "New Conversation",
|
|
1942
1942
|
"conversations": "Conversations",
|
|
1943
1943
|
"openConversations": "Open conversations",
|
|
1944
|
+
"closeConversations": "Close conversations",
|
|
1944
1945
|
"placeholder": "Type your message... (Enter to send, Shift+Enter for new line)",
|
|
1945
1946
|
"send": "Send",
|
|
1946
1947
|
"sending": "Sending...",
|
|
@@ -1996,6 +1996,7 @@
|
|
|
1996
1996
|
"newConversation": "Nova Conversa",
|
|
1997
1997
|
"conversations": "Conversas",
|
|
1998
1998
|
"openConversations": "Abrir conversas",
|
|
1999
|
+
"closeConversations": "Fechar conversas",
|
|
1999
2000
|
"placeholder": "Digite sua mensagem... (Enter para enviar, Shift+Enter para nova linha)",
|
|
2000
2001
|
"send": "Enviar",
|
|
2001
2002
|
"sending": "Enviando...",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hed-hog/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.354",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
35
35
|
"@hed-hog/api-locale": "0.0.14",
|
|
36
36
|
"@hed-hog/api-mail": "0.0.9",
|
|
37
|
+
"@hed-hog/api-pagination": "0.0.7",
|
|
37
38
|
"@hed-hog/api-types": "0.0.1",
|
|
38
39
|
"@hed-hog/api": "0.0.8",
|
|
39
|
-
"@hed-hog/api-prisma": "0.0.6"
|
|
40
|
-
"@hed-hog/api-pagination": "0.0.7"
|
|
40
|
+
"@hed-hog/api-prisma": "0.0.6"
|
|
41
41
|
},
|
|
42
42
|
"exports": {
|
|
43
43
|
".": {
|
package/src/core.module.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { LogInterceptor } from '@hed-hog/api';
|
|
2
2
|
import { LocaleModule } from '@hed-hog/api-locale';
|
|
3
|
-
import { AccessLogInterceptor } from './access-log/access-log.interceptor';
|
|
4
|
-
import { AccessLogModule } from './access-log/access-log.module';
|
|
5
|
-
import { AccessLogService } from './access-log/access-log.service';
|
|
6
3
|
import { MailModule as MailSendModule } from '@hed-hog/api-mail';
|
|
7
4
|
import { PaginationModule } from '@hed-hog/api-pagination';
|
|
8
5
|
import { PrismaModule, PrismaService } from '@hed-hog/api-prisma';
|
|
@@ -10,6 +7,9 @@ import { HttpModule } from '@nestjs/axios';
|
|
|
10
7
|
import { forwardRef, Global, Inject, MiddlewareConsumer, Module, NestModule, OnModuleInit } from '@nestjs/common';
|
|
11
8
|
import { ConfigModule } from '@nestjs/config';
|
|
12
9
|
import { APP_INTERCEPTOR, Reflector } from '@nestjs/core';
|
|
10
|
+
import { AccessLogInterceptor } from './access-log/access-log.interceptor';
|
|
11
|
+
import { AccessLogModule } from './access-log/access-log.module';
|
|
12
|
+
import { AccessLogService } from './access-log/access-log.service';
|
|
13
13
|
import { AiModule } from './ai/ai.module';
|
|
14
14
|
import { AuthModule } from './auth/auth.module';
|
|
15
15
|
import { SystemModule } from './core/system.module';
|
|
@@ -17,6 +17,7 @@ import { DashboardModule } from './dashboard/dashboard.module';
|
|
|
17
17
|
import { FileModule } from './file/file.module';
|
|
18
18
|
import { InstallModule } from './install/install.module';
|
|
19
19
|
import { IntegrationModule } from './integration/integration.module';
|
|
20
|
+
import { LocaleModule as CoreLocaleModule } from './locale/locale.module';
|
|
20
21
|
import { MailProfileModule } from './mail-profile/mail-profile.module';
|
|
21
22
|
import { MailSentModule } from './mail-sent/mail-sent.module';
|
|
22
23
|
import { MailModule } from './mail/mail.module';
|
|
@@ -24,6 +25,7 @@ import { McpChatModule } from './mcp-chat/mcp-chat.module';
|
|
|
24
25
|
import { McpModule } from './mcp/mcp.module';
|
|
25
26
|
import { MenuModule } from './menu/menu.module';
|
|
26
27
|
import { LocaleInjectionMiddleware } from './middlewares/locale-injection.middleware';
|
|
28
|
+
import { NotificationModule } from './notification/notification.module';
|
|
27
29
|
import { OAuthModule } from './oauth/oauth.module';
|
|
28
30
|
import { PdfModule } from './pdf/pdf.module';
|
|
29
31
|
import { ProfileModule } from './profile/profile.module';
|
|
@@ -40,7 +42,6 @@ import { IsEmailWithSettingsConstraint } from './validators/is-email-with-settin
|
|
|
40
42
|
import { IsPinCodeWithSettingConstraint } from './validators/is-pin-code-with-setting.validator';
|
|
41
43
|
import { IsStrongPasswordWithSettingsConstraint } from './validators/is-strong-password-with-settings.validator';
|
|
42
44
|
import { ValidatorServiceLocator } from './validators/service-locator';
|
|
43
|
-
import { NotificationModule } from './notification/notification.module';
|
|
44
45
|
import { WebhookIntegrationModule } from './webhook-integration/webhook-integration.module';
|
|
45
46
|
|
|
46
47
|
@Global()
|
|
@@ -60,6 +61,7 @@ import { WebhookIntegrationModule } from './webhook-integration/webhook-integrat
|
|
|
60
61
|
forwardRef(() => PrismaModule),
|
|
61
62
|
forwardRef(() => ScreenModule),
|
|
62
63
|
forwardRef(() => LocaleModule),
|
|
64
|
+
forwardRef(() => CoreLocaleModule),
|
|
63
65
|
forwardRef(() => UserModule),
|
|
64
66
|
forwardRef(() => SystemModule),
|
|
65
67
|
forwardRef(() => SettingModule),
|
|
@@ -90,6 +92,7 @@ import { WebhookIntegrationModule } from './webhook-integration/webhook-integrat
|
|
|
90
92
|
MenuModule,
|
|
91
93
|
ScreenModule,
|
|
92
94
|
LocaleModule,
|
|
95
|
+
CoreLocaleModule,
|
|
93
96
|
SettingModule,
|
|
94
97
|
FileModule,
|
|
95
98
|
SessionModule,
|
|
@@ -12,12 +12,13 @@ import {
|
|
|
12
12
|
ParseIntPipe,
|
|
13
13
|
Post,
|
|
14
14
|
Put,
|
|
15
|
+
Req,
|
|
15
16
|
Res,
|
|
16
17
|
UploadedFile,
|
|
17
18
|
UseInterceptors,
|
|
18
19
|
} from '@nestjs/common';
|
|
19
20
|
import { FileInterceptor } from '@nestjs/platform-express';
|
|
20
|
-
import { Response } from 'express';
|
|
21
|
+
import { Request, Response } from 'express';
|
|
21
22
|
import { readFileSync } from 'fs';
|
|
22
23
|
import Handlebars from 'handlebars';
|
|
23
24
|
import { join } from 'path';
|
|
@@ -53,12 +54,16 @@ export class FileController {
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
@Put('download/:id')
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
async getTempURL(
|
|
58
|
+
@Param('id', ParseIntPipe) id: number,
|
|
59
|
+
@Req() req: Request,
|
|
60
|
+
) {
|
|
61
|
+
const file = await this.fileService.get(id);
|
|
62
|
+
const token = this.fileService.createDownloadToken(file.path, 3600);
|
|
63
|
+
const origin = `${req.protocol}://${req.get('host')}`;
|
|
64
|
+
|
|
58
65
|
return {
|
|
59
|
-
|
|
60
|
-
(await this.fileService.get(id)).path,
|
|
61
|
-
),
|
|
66
|
+
url: `${origin}/file/download/${encodeURIComponent(token)}`,
|
|
62
67
|
};
|
|
63
68
|
}
|
|
64
69
|
|
package/src/file/file.service.ts
CHANGED
|
@@ -553,7 +553,7 @@ export class FileService implements OnModuleInit {
|
|
|
553
553
|
for (const file of files) {
|
|
554
554
|
await (await this.getProvider()).delete(file.path);
|
|
555
555
|
|
|
556
|
-
await this.prismaService.file.
|
|
556
|
+
await this.prismaService.file.deleteMany({
|
|
557
557
|
where: {
|
|
558
558
|
id: file.id,
|
|
559
559
|
},
|
|
@@ -702,4 +702,18 @@ export class FileService implements OnModuleInit {
|
|
|
702
702
|
|
|
703
703
|
return url;
|
|
704
704
|
}
|
|
705
|
+
|
|
706
|
+
createDownloadToken(filepath: string, expires = 3600) {
|
|
707
|
+
if (!filepath) {
|
|
708
|
+
throw new BadRequestException(`No file path provided`);
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
return this.jwtService.sign(
|
|
712
|
+
{ filepath },
|
|
713
|
+
{
|
|
714
|
+
secret: process.env.JWT_SECRET,
|
|
715
|
+
expiresIn: `${Math.max(1, Number(expires) || 3600)}s`,
|
|
716
|
+
},
|
|
717
|
+
);
|
|
718
|
+
}
|
|
705
719
|
}
|
|
@@ -118,9 +118,6 @@ export class OutboxPollingCoordinator {
|
|
|
118
118
|
} else {
|
|
119
119
|
// No items processed - use idle interval
|
|
120
120
|
nextDelayMs = settings.idlePollingIntervalMs;
|
|
121
|
-
this.logger.debug(
|
|
122
|
-
`No events processed, idle polling for ${nextDelayMs}ms`,
|
|
123
|
-
);
|
|
124
121
|
}
|
|
125
122
|
|
|
126
123
|
// Wait for next poll, but be ready for immediate wakeup
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { IsBoolean, IsOptional, IsString, MaxLength } from 'class-validator';
|
|
2
|
+
|
|
3
|
+
export class CreateLocaleDTO {
|
|
4
|
+
@IsString()
|
|
5
|
+
name: string;
|
|
6
|
+
|
|
7
|
+
@IsString()
|
|
8
|
+
@MaxLength(2)
|
|
9
|
+
code: string;
|
|
10
|
+
|
|
11
|
+
@IsString()
|
|
12
|
+
@MaxLength(2)
|
|
13
|
+
@IsOptional()
|
|
14
|
+
region?: string;
|
|
15
|
+
|
|
16
|
+
@IsBoolean()
|
|
17
|
+
@IsOptional()
|
|
18
|
+
enabled?: boolean;
|
|
19
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Role } from '@hed-hog/api';
|
|
2
|
+
import { Pagination, PaginationDTO } from '@hed-hog/api-pagination';
|
|
3
|
+
import {
|
|
4
|
+
Body,
|
|
5
|
+
Controller,
|
|
6
|
+
Get,
|
|
7
|
+
Inject,
|
|
8
|
+
Post,
|
|
9
|
+
Query,
|
|
10
|
+
forwardRef,
|
|
11
|
+
} from '@nestjs/common';
|
|
12
|
+
import { CreateLocaleDTO } from './dto/create-locale.dto';
|
|
13
|
+
import { LocaleService } from './locale.service';
|
|
14
|
+
|
|
15
|
+
@Role()
|
|
16
|
+
@Controller('core/locales')
|
|
17
|
+
export class LocaleController {
|
|
18
|
+
constructor(
|
|
19
|
+
@Inject(forwardRef(() => LocaleService))
|
|
20
|
+
private readonly localeService: LocaleService,
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
@Get()
|
|
24
|
+
async findAll(
|
|
25
|
+
@Pagination() paginationDto: PaginationDTO,
|
|
26
|
+
@Query('search') search?: string,
|
|
27
|
+
) {
|
|
28
|
+
return this.localeService.findAll(paginationDto, search);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@Post()
|
|
32
|
+
async create(@Body() dto: CreateLocaleDTO) {
|
|
33
|
+
return this.localeService.create(dto);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { PaginationModule } from '@hed-hog/api-pagination';
|
|
2
|
+
import { PrismaModule } from '@hed-hog/api-prisma';
|
|
3
|
+
import { Module, forwardRef } from '@nestjs/common';
|
|
4
|
+
import { AuthModule } from '../auth/auth.module';
|
|
5
|
+
import { LocaleController } from './locale.controller';
|
|
6
|
+
import { LocaleService } from './locale.service';
|
|
7
|
+
|
|
8
|
+
@Module({
|
|
9
|
+
providers: [LocaleService],
|
|
10
|
+
exports: [LocaleService],
|
|
11
|
+
controllers: [LocaleController],
|
|
12
|
+
imports: [
|
|
13
|
+
forwardRef(() => AuthModule),
|
|
14
|
+
forwardRef(() => PrismaModule),
|
|
15
|
+
forwardRef(() => PaginationModule),
|
|
16
|
+
],
|
|
17
|
+
})
|
|
18
|
+
export class LocaleModule {}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { PaginationDTO, PaginationService } from '@hed-hog/api-pagination';
|
|
2
|
+
import { PrismaService } from '@hed-hog/api-prisma';
|
|
3
|
+
import { Inject, Injectable, forwardRef } from '@nestjs/common';
|
|
4
|
+
import { CreateLocaleDTO } from './dto/create-locale.dto';
|
|
5
|
+
|
|
6
|
+
@Injectable()
|
|
7
|
+
export class LocaleService {
|
|
8
|
+
constructor(
|
|
9
|
+
@Inject(forwardRef(() => PrismaService))
|
|
10
|
+
private readonly prismaService: PrismaService,
|
|
11
|
+
@Inject(forwardRef(() => PaginationService))
|
|
12
|
+
private readonly paginationService: PaginationService,
|
|
13
|
+
) {}
|
|
14
|
+
|
|
15
|
+
async findAll(paginationDto: PaginationDTO, search?: string) {
|
|
16
|
+
const normalizedSearch = search ?? paginationDto.search;
|
|
17
|
+
const paginationParams: PaginationDTO = {
|
|
18
|
+
...paginationDto,
|
|
19
|
+
search: normalizedSearch,
|
|
20
|
+
};
|
|
21
|
+
const fields = ['name', 'code'];
|
|
22
|
+
const OR: any[] = this.prismaService.createInsensitiveSearch(
|
|
23
|
+
fields,
|
|
24
|
+
paginationParams,
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
return this.paginationService.paginate(
|
|
28
|
+
this.prismaService.locale,
|
|
29
|
+
paginationParams,
|
|
30
|
+
{
|
|
31
|
+
where: {
|
|
32
|
+
OR,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async create(dto: CreateLocaleDTO) {
|
|
39
|
+
return this.prismaService.locale.create({
|
|
40
|
+
data: {
|
|
41
|
+
name: dto.name,
|
|
42
|
+
code: dto.code,
|
|
43
|
+
region: dto.region ?? null,
|
|
44
|
+
enabled: dto.enabled ?? true,
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { PaginationService } from '@hed-hog/api-pagination';
|
|
2
2
|
import { PrismaService } from '@hed-hog/api-prisma';
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
BadRequestException,
|
|
5
|
+
ForbiddenException,
|
|
6
|
+
forwardRef,
|
|
7
|
+
Inject,
|
|
8
|
+
Injectable,
|
|
9
|
+
Logger,
|
|
10
|
+
NotFoundException,
|
|
11
|
+
OnModuleDestroy,
|
|
12
|
+
OnModuleInit,
|
|
12
13
|
} from '@nestjs/common';
|
|
13
14
|
import type { Request, Response } from 'express';
|
|
14
15
|
import { randomUUID } from 'node:crypto';
|
|
@@ -113,6 +114,9 @@ export class NotificationService implements OnModuleInit, OnModuleDestroy {
|
|
|
113
114
|
async markRead(userId: number, id: number) {
|
|
114
115
|
const notification = await this.assertOwnership(userId, id);
|
|
115
116
|
if (notification.auto_remove) {
|
|
117
|
+
if (this.isActiveAsyncNotification(notification)) {
|
|
118
|
+
throw new BadRequestException('Active async notifications cannot be deleted');
|
|
119
|
+
}
|
|
116
120
|
const deleted = await this.prisma.notification.delete({ where: { id } });
|
|
117
121
|
await this.broadcastNotificationEvent(userId, {
|
|
118
122
|
type: 'notification.updated',
|
|
@@ -133,7 +137,16 @@ export class NotificationService implements OnModuleInit, OnModuleDestroy {
|
|
|
133
137
|
|
|
134
138
|
async markAllRead(userId: number) {
|
|
135
139
|
await this.prisma.notification.deleteMany({
|
|
136
|
-
where: {
|
|
140
|
+
where: {
|
|
141
|
+
user_id: userId,
|
|
142
|
+
status: 'unread',
|
|
143
|
+
auto_remove: true,
|
|
144
|
+
OR: [
|
|
145
|
+
{ progress: null },
|
|
146
|
+
{ progress: { gte: 100 } },
|
|
147
|
+
{ finished_at: { not: null } },
|
|
148
|
+
],
|
|
149
|
+
},
|
|
137
150
|
});
|
|
138
151
|
const updated = await this.prisma.notification.updateMany({
|
|
139
152
|
where: { user_id: userId, status: 'unread' },
|
|
@@ -144,7 +157,10 @@ export class NotificationService implements OnModuleInit, OnModuleDestroy {
|
|
|
144
157
|
}
|
|
145
158
|
|
|
146
159
|
async delete(userId: number, id: number) {
|
|
147
|
-
await this.assertOwnership(userId, id);
|
|
160
|
+
const notification = await this.assertOwnership(userId, id);
|
|
161
|
+
if (this.isActiveAsyncNotification(notification)) {
|
|
162
|
+
throw new BadRequestException('Active async notifications cannot be deleted');
|
|
163
|
+
}
|
|
148
164
|
const deleted = await this.prisma.notification.delete({ where: { id } });
|
|
149
165
|
await this.broadcastNotificationEvent(userId, {
|
|
150
166
|
type: 'notification.updated',
|
|
@@ -155,7 +171,14 @@ export class NotificationService implements OnModuleInit, OnModuleDestroy {
|
|
|
155
171
|
|
|
156
172
|
async deleteAll(userId: number) {
|
|
157
173
|
const result = await this.prisma.notification.deleteMany({
|
|
158
|
-
where: {
|
|
174
|
+
where: {
|
|
175
|
+
user_id: userId,
|
|
176
|
+
OR: [
|
|
177
|
+
{ progress: null },
|
|
178
|
+
{ progress: { gte: 100 } },
|
|
179
|
+
{ finished_at: { not: null } },
|
|
180
|
+
],
|
|
181
|
+
},
|
|
159
182
|
});
|
|
160
183
|
await this.broadcastNotificationEvent(userId, { type: 'notification.updated' });
|
|
161
184
|
return result;
|
|
@@ -260,13 +283,29 @@ export class NotificationService implements OnModuleInit, OnModuleDestroy {
|
|
|
260
283
|
private async assertOwnership(userId: number, id: number) {
|
|
261
284
|
const notification = await this.prisma.notification.findUnique({
|
|
262
285
|
where: { id },
|
|
263
|
-
select: {
|
|
286
|
+
select: {
|
|
287
|
+
user_id: true,
|
|
288
|
+
auto_remove: true,
|
|
289
|
+
progress: true,
|
|
290
|
+
finished_at: true,
|
|
291
|
+
},
|
|
264
292
|
});
|
|
265
293
|
if (!notification) throw new NotFoundException();
|
|
266
294
|
if (notification.user_id !== userId) throw new ForbiddenException();
|
|
267
295
|
return notification;
|
|
268
296
|
}
|
|
269
297
|
|
|
298
|
+
private isActiveAsyncNotification(notification: {
|
|
299
|
+
progress: number | null;
|
|
300
|
+
finished_at: Date | null;
|
|
301
|
+
}) {
|
|
302
|
+
return (
|
|
303
|
+
notification.progress != null &&
|
|
304
|
+
notification.progress < 100 &&
|
|
305
|
+
notification.finished_at == null
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
270
309
|
private async broadcastNotificationEvent(
|
|
271
310
|
userId: number,
|
|
272
311
|
event: NotificationStreamEvent,
|
|
@@ -3,12 +3,12 @@ import { getLocaleText, LocaleService } from '@hed-hog/api-locale';
|
|
|
3
3
|
import { PaginationDTO, PaginationService } from '@hed-hog/api-pagination';
|
|
4
4
|
import { PrismaService, setting_type_0f055cd5ea_enum } from '@hed-hog/api-prisma';
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
BadRequestException,
|
|
7
|
+
forwardRef,
|
|
8
|
+
Inject,
|
|
9
|
+
Injectable,
|
|
10
|
+
Logger,
|
|
11
|
+
NotFoundException
|
|
12
12
|
} from '@nestjs/common';
|
|
13
13
|
import * as pako from 'pako';
|
|
14
14
|
import { IntegrationDeveloperApiService } from '../integration/services/integration-developer-api.service';
|
|
@@ -217,6 +217,8 @@ export class SettingService {
|
|
|
217
217
|
'disable-authentication-with-email-and-password',
|
|
218
218
|
'contact-allow-company-registration',
|
|
219
219
|
'operations.comment-edit-window',
|
|
220
|
+
'lms-video-conversion-enabled',
|
|
221
|
+
'lms-video-frame-capture-interval-seconds',
|
|
220
222
|
];
|
|
221
223
|
const setting = await this.getSettingValues(slugs);
|
|
222
224
|
return { locales, setting };
|