@oneuptime/common 10.5.3 → 10.5.6
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/Models/DatabaseModels/AlertEpisodeMember.ts +29 -0
- package/Models/DatabaseModels/AlertGroupingRule.ts +76 -0
- package/Models/DatabaseModels/GlobalConfig.ts +28 -0
- package/Models/DatabaseModels/IncidentEpisodeMember.ts +29 -0
- package/Models/DatabaseModels/IncidentGroupingRule.ts +76 -0
- package/Models/DatabaseModels/ProjectSmtpConfig.ts +62 -6
- package/Server/Infrastructure/Postgres/SchemaMigrations/1779971548393-AddLabelGroupByToGroupingRules.ts +37 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1779975064262-AddTransportTypeToProjectSmtpConfig.ts +37 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1779976190561-AddSmtpTransportTypeToGlobalConfig.ts +19 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1779980428744-MigrationName.ts +23 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
- package/Server/Services/AlertEpisodeMemberService.ts +23 -0
- package/Server/Services/AlertGroupingEngineService.ts +83 -0
- package/Server/Services/IncidentEpisodeMemberService.ts +23 -0
- package/Server/Services/IncidentGroupingEngineService.ts +99 -0
- package/Server/Services/MailService.ts +15 -3
- package/Server/Services/ProjectSmtpConfigService.ts +30 -10
- package/Server/Services/StatusPagePrivateUserService.ts +1 -0
- package/Server/Services/StatusPageSubscriberService.ts +3 -0
- package/Server/Services/UserNotificationSettingService.ts +12 -0
- package/Server/Utils/WhatsAppTemplateUtil.ts +4 -0
- package/Tests/Server/Services/AlertGroupingEngineService.test.ts +28 -0
- package/Tests/Server/Services/AlertGroupingRuleService.test.ts +14 -0
- package/Types/Email/EmailServer.ts +22 -4
- package/Types/Email/EmailTemplateType.ts +2 -0
- package/Types/Email/MailTransportType.ts +18 -0
- package/Types/NotificationSetting/NotificationSettingEventType.ts +2 -0
- package/Types/WhatsApp/WhatsAppTemplates.ts +10 -0
- package/UI/Components/Accordion/Accordion.tsx +12 -4
- package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js +30 -0
- package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertGroupingRule.js +78 -0
- package/build/dist/Models/DatabaseModels/AlertGroupingRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +28 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js +30 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js +78 -0
- package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectSmtpConfig.js +59 -6
- package/build/dist/Models/DatabaseModels/ProjectSmtpConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779971548393-AddLabelGroupByToGroupingRules.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779971548393-AddLabelGroupByToGroupingRules.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779975064262-AddTransportTypeToProjectSmtpConfig.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779975064262-AddTransportTypeToProjectSmtpConfig.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779976190561-AddSmtpTransportTypeToGlobalConfig.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779976190561-AddSmtpTransportTypeToGlobalConfig.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779980428744-MigrationName.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779980428744-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeMemberService.js +20 -0
- package/build/dist/Server/Services/AlertEpisodeMemberService.js.map +1 -1
- package/build/dist/Server/Services/AlertGroupingEngineService.js +85 -0
- package/build/dist/Server/Services/AlertGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeMemberService.js +20 -0
- package/build/dist/Server/Services/IncidentEpisodeMemberService.js.map +1 -1
- package/build/dist/Server/Services/IncidentGroupingEngineService.js +95 -0
- package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/MailService.js +15 -3
- package/build/dist/Server/Services/MailService.js.map +1 -1
- package/build/dist/Server/Services/ProjectSmtpConfigService.js +24 -8
- package/build/dist/Server/Services/ProjectSmtpConfigService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserService.js +1 -0
- package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberService.js +3 -0
- package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationSettingService.js +2 -0
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Utils/WhatsAppTemplateUtil.js +2 -0
- package/build/dist/Server/Utils/WhatsAppTemplateUtil.js.map +1 -1
- package/build/dist/Tests/Server/Services/AlertGroupingEngineService.test.js +21 -0
- package/build/dist/Tests/Server/Services/AlertGroupingEngineService.test.js.map +1 -1
- package/build/dist/Tests/Server/Services/AlertGroupingRuleService.test.js +12 -0
- package/build/dist/Tests/Server/Services/AlertGroupingRuleService.test.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +2 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Email/MailTransportType.js +19 -0
- package/build/dist/Types/Email/MailTransportType.js.map +1 -0
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +2 -0
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
- package/build/dist/Types/WhatsApp/WhatsAppTemplates.js +6 -0
- package/build/dist/Types/WhatsApp/WhatsAppTemplates.js.map +1 -1
- package/build/dist/UI/Components/Accordion/Accordion.js +4 -4
- package/build/dist/UI/Components/Accordion/Accordion.js.map +1 -1
- package/package.json +1 -1
|
@@ -626,6 +626,35 @@ export default class AlertEpisodeMember extends BaseModel {
|
|
|
626
626
|
})
|
|
627
627
|
public createdByUserId?: ObjectID = undefined;
|
|
628
628
|
|
|
629
|
+
@ColumnAccessControl({
|
|
630
|
+
create: [],
|
|
631
|
+
read: [
|
|
632
|
+
Permission.ProjectOwner,
|
|
633
|
+
Permission.ProjectAdmin,
|
|
634
|
+
Permission.ProjectMember,
|
|
635
|
+
Permission.Viewer,
|
|
636
|
+
Permission.AlertAdmin,
|
|
637
|
+
Permission.AlertMember,
|
|
638
|
+
Permission.AlertViewer,
|
|
639
|
+
Permission.ReadAlertEpisodeMember,
|
|
640
|
+
],
|
|
641
|
+
update: [],
|
|
642
|
+
})
|
|
643
|
+
@TableColumn({
|
|
644
|
+
isDefaultValueColumn: true,
|
|
645
|
+
required: true,
|
|
646
|
+
type: TableColumnType.Boolean,
|
|
647
|
+
title: "Is Owner Notified of Alert Added to Episode",
|
|
648
|
+
description:
|
|
649
|
+
"Has the owner been notified that this alert was added to the episode?",
|
|
650
|
+
})
|
|
651
|
+
@Column({
|
|
652
|
+
type: ColumnType.Boolean,
|
|
653
|
+
nullable: false,
|
|
654
|
+
default: false,
|
|
655
|
+
})
|
|
656
|
+
public isOwnerNotifiedOfAlertAdded?: boolean = undefined;
|
|
657
|
+
|
|
629
658
|
@ColumnAccessControl({
|
|
630
659
|
create: [],
|
|
631
660
|
read: [
|
|
@@ -811,6 +811,82 @@ export default class AlertGroupingRule extends BaseModel {
|
|
|
811
811
|
})
|
|
812
812
|
public groupByAlertTitle?: boolean = undefined;
|
|
813
813
|
|
|
814
|
+
@ColumnAccessControl({
|
|
815
|
+
create: [
|
|
816
|
+
Permission.ProjectOwner,
|
|
817
|
+
Permission.ProjectAdmin,
|
|
818
|
+
Permission.CreateAlertGroupingRule,
|
|
819
|
+
],
|
|
820
|
+
read: [
|
|
821
|
+
Permission.ProjectOwner,
|
|
822
|
+
Permission.ProjectAdmin,
|
|
823
|
+
Permission.ProjectMember,
|
|
824
|
+
Permission.Viewer,
|
|
825
|
+
Permission.AlertAdmin,
|
|
826
|
+
Permission.AlertMember,
|
|
827
|
+
Permission.AlertViewer,
|
|
828
|
+
Permission.ReadAlertGroupingRule,
|
|
829
|
+
],
|
|
830
|
+
update: [
|
|
831
|
+
Permission.ProjectOwner,
|
|
832
|
+
Permission.ProjectAdmin,
|
|
833
|
+
Permission.EditAlertGroupingRule,
|
|
834
|
+
],
|
|
835
|
+
})
|
|
836
|
+
@TableColumn({
|
|
837
|
+
required: false,
|
|
838
|
+
type: TableColumnType.Boolean,
|
|
839
|
+
title: "Group By Alert Labels",
|
|
840
|
+
description:
|
|
841
|
+
"When enabled, alerts with different sets of labels will be grouped into separate episodes (exact set match). When disabled, alert labels are ignored for grouping.",
|
|
842
|
+
defaultValue: false,
|
|
843
|
+
isDefaultValueColumn: true,
|
|
844
|
+
})
|
|
845
|
+
@Column({
|
|
846
|
+
type: ColumnType.Boolean,
|
|
847
|
+
nullable: false,
|
|
848
|
+
default: false,
|
|
849
|
+
})
|
|
850
|
+
public groupByAlertLabels?: boolean = undefined;
|
|
851
|
+
|
|
852
|
+
@ColumnAccessControl({
|
|
853
|
+
create: [
|
|
854
|
+
Permission.ProjectOwner,
|
|
855
|
+
Permission.ProjectAdmin,
|
|
856
|
+
Permission.CreateAlertGroupingRule,
|
|
857
|
+
],
|
|
858
|
+
read: [
|
|
859
|
+
Permission.ProjectOwner,
|
|
860
|
+
Permission.ProjectAdmin,
|
|
861
|
+
Permission.ProjectMember,
|
|
862
|
+
Permission.Viewer,
|
|
863
|
+
Permission.AlertAdmin,
|
|
864
|
+
Permission.AlertMember,
|
|
865
|
+
Permission.AlertViewer,
|
|
866
|
+
Permission.ReadAlertGroupingRule,
|
|
867
|
+
],
|
|
868
|
+
update: [
|
|
869
|
+
Permission.ProjectOwner,
|
|
870
|
+
Permission.ProjectAdmin,
|
|
871
|
+
Permission.EditAlertGroupingRule,
|
|
872
|
+
],
|
|
873
|
+
})
|
|
874
|
+
@TableColumn({
|
|
875
|
+
required: false,
|
|
876
|
+
type: TableColumnType.Boolean,
|
|
877
|
+
title: "Group By Monitor Labels",
|
|
878
|
+
description:
|
|
879
|
+
"When enabled, alerts whose monitors have different sets of labels will be grouped into separate episodes (exact set match). When disabled, monitor labels are ignored for grouping.",
|
|
880
|
+
defaultValue: false,
|
|
881
|
+
isDefaultValueColumn: true,
|
|
882
|
+
})
|
|
883
|
+
@Column({
|
|
884
|
+
type: ColumnType.Boolean,
|
|
885
|
+
nullable: false,
|
|
886
|
+
default: false,
|
|
887
|
+
})
|
|
888
|
+
public groupByMonitorLabels?: boolean = undefined;
|
|
889
|
+
|
|
814
890
|
@ColumnAccessControl({
|
|
815
891
|
create: [
|
|
816
892
|
Permission.ProjectOwner,
|
|
@@ -10,6 +10,7 @@ import TableColumn from "../../Types/Database/TableColumn";
|
|
|
10
10
|
import TableColumnType from "../../Types/Database/TableColumnType";
|
|
11
11
|
import TableMetadata from "../../Types/Database/TableMetadata";
|
|
12
12
|
import Email from "../../Types/Email";
|
|
13
|
+
import MailTransportType from "../../Types/Email/MailTransportType";
|
|
13
14
|
import OAuthProviderType from "../../Types/Email/OAuthProviderType";
|
|
14
15
|
import SMTPAuthenticationType from "../../Types/Email/SMTPAuthenticationType";
|
|
15
16
|
import IconProp from "../../Types/Icon/IconProp";
|
|
@@ -208,6 +209,33 @@ export default class GlobalConfig extends GlobalConfigModel {
|
|
|
208
209
|
})
|
|
209
210
|
public smtpFromName?: string = undefined;
|
|
210
211
|
|
|
212
|
+
/*
|
|
213
|
+
* Transport selection for the global SMTP. Defaults to SMTP for backwards
|
|
214
|
+
* compatibility. 'Microsoft Graph' bypasses SMTP entirely and posts to
|
|
215
|
+
* https://graph.microsoft.com/v1.0/users/{from}/sendMail — useful for tenants
|
|
216
|
+
* that have SMTP AUTH disabled.
|
|
217
|
+
*/
|
|
218
|
+
|
|
219
|
+
@ColumnAccessControl({
|
|
220
|
+
create: [],
|
|
221
|
+
read: [],
|
|
222
|
+
update: [],
|
|
223
|
+
})
|
|
224
|
+
@TableColumn({
|
|
225
|
+
type: TableColumnType.ShortText,
|
|
226
|
+
title: "SMTP Transport",
|
|
227
|
+
description:
|
|
228
|
+
"How OneUptime delivers mail using the global SMTP config. 'SMTP' uses the host/port. 'Microsoft Graph' sends via the Microsoft Graph REST API.",
|
|
229
|
+
defaultValue: MailTransportType.SMTP,
|
|
230
|
+
})
|
|
231
|
+
@Column({
|
|
232
|
+
type: ColumnType.ShortText,
|
|
233
|
+
length: ColumnLength.ShortText,
|
|
234
|
+
nullable: true,
|
|
235
|
+
default: MailTransportType.SMTP,
|
|
236
|
+
})
|
|
237
|
+
public smtpTransportType?: MailTransportType = undefined;
|
|
238
|
+
|
|
211
239
|
// SMTP OAuth 2.0 Settings.
|
|
212
240
|
|
|
213
241
|
@ColumnAccessControl({
|
|
@@ -627,6 +627,35 @@ export default class IncidentEpisodeMember extends BaseModel {
|
|
|
627
627
|
})
|
|
628
628
|
public createdByUserId?: ObjectID = undefined;
|
|
629
629
|
|
|
630
|
+
@ColumnAccessControl({
|
|
631
|
+
create: [],
|
|
632
|
+
read: [
|
|
633
|
+
Permission.ProjectOwner,
|
|
634
|
+
Permission.ProjectAdmin,
|
|
635
|
+
Permission.ProjectMember,
|
|
636
|
+
Permission.Viewer,
|
|
637
|
+
Permission.IncidentAdmin,
|
|
638
|
+
Permission.IncidentMember,
|
|
639
|
+
Permission.IncidentViewer,
|
|
640
|
+
Permission.ReadIncidentEpisodeMember,
|
|
641
|
+
],
|
|
642
|
+
update: [],
|
|
643
|
+
})
|
|
644
|
+
@TableColumn({
|
|
645
|
+
isDefaultValueColumn: true,
|
|
646
|
+
required: true,
|
|
647
|
+
type: TableColumnType.Boolean,
|
|
648
|
+
title: "Is Owner Notified of Incident Added to Episode",
|
|
649
|
+
description:
|
|
650
|
+
"Has the owner been notified that this incident was added to the episode?",
|
|
651
|
+
})
|
|
652
|
+
@Column({
|
|
653
|
+
type: ColumnType.Boolean,
|
|
654
|
+
nullable: false,
|
|
655
|
+
default: false,
|
|
656
|
+
})
|
|
657
|
+
public isOwnerNotifiedOfIncidentAdded?: boolean = undefined;
|
|
658
|
+
|
|
630
659
|
@ColumnAccessControl({
|
|
631
660
|
create: [],
|
|
632
661
|
read: [
|
|
@@ -815,6 +815,82 @@ export default class IncidentGroupingRule extends BaseModel {
|
|
|
815
815
|
})
|
|
816
816
|
public groupByIncidentTitle?: boolean = undefined;
|
|
817
817
|
|
|
818
|
+
@ColumnAccessControl({
|
|
819
|
+
create: [
|
|
820
|
+
Permission.ProjectOwner,
|
|
821
|
+
Permission.ProjectAdmin,
|
|
822
|
+
Permission.CreateIncidentGroupingRule,
|
|
823
|
+
],
|
|
824
|
+
read: [
|
|
825
|
+
Permission.ProjectOwner,
|
|
826
|
+
Permission.ProjectAdmin,
|
|
827
|
+
Permission.ProjectMember,
|
|
828
|
+
Permission.Viewer,
|
|
829
|
+
Permission.IncidentAdmin,
|
|
830
|
+
Permission.IncidentMember,
|
|
831
|
+
Permission.IncidentViewer,
|
|
832
|
+
Permission.ReadIncidentGroupingRule,
|
|
833
|
+
],
|
|
834
|
+
update: [
|
|
835
|
+
Permission.ProjectOwner,
|
|
836
|
+
Permission.ProjectAdmin,
|
|
837
|
+
Permission.EditIncidentGroupingRule,
|
|
838
|
+
],
|
|
839
|
+
})
|
|
840
|
+
@TableColumn({
|
|
841
|
+
required: false,
|
|
842
|
+
type: TableColumnType.Boolean,
|
|
843
|
+
title: "Group By Incident Labels",
|
|
844
|
+
description:
|
|
845
|
+
"When enabled, incidents with different sets of labels will be grouped into separate episodes (exact set match). When disabled, incident labels are ignored for grouping.",
|
|
846
|
+
defaultValue: false,
|
|
847
|
+
isDefaultValueColumn: true,
|
|
848
|
+
})
|
|
849
|
+
@Column({
|
|
850
|
+
type: ColumnType.Boolean,
|
|
851
|
+
nullable: false,
|
|
852
|
+
default: false,
|
|
853
|
+
})
|
|
854
|
+
public groupByIncidentLabels?: boolean = undefined;
|
|
855
|
+
|
|
856
|
+
@ColumnAccessControl({
|
|
857
|
+
create: [
|
|
858
|
+
Permission.ProjectOwner,
|
|
859
|
+
Permission.ProjectAdmin,
|
|
860
|
+
Permission.CreateIncidentGroupingRule,
|
|
861
|
+
],
|
|
862
|
+
read: [
|
|
863
|
+
Permission.ProjectOwner,
|
|
864
|
+
Permission.ProjectAdmin,
|
|
865
|
+
Permission.ProjectMember,
|
|
866
|
+
Permission.Viewer,
|
|
867
|
+
Permission.IncidentAdmin,
|
|
868
|
+
Permission.IncidentMember,
|
|
869
|
+
Permission.IncidentViewer,
|
|
870
|
+
Permission.ReadIncidentGroupingRule,
|
|
871
|
+
],
|
|
872
|
+
update: [
|
|
873
|
+
Permission.ProjectOwner,
|
|
874
|
+
Permission.ProjectAdmin,
|
|
875
|
+
Permission.EditIncidentGroupingRule,
|
|
876
|
+
],
|
|
877
|
+
})
|
|
878
|
+
@TableColumn({
|
|
879
|
+
required: false,
|
|
880
|
+
type: TableColumnType.Boolean,
|
|
881
|
+
title: "Group By Monitor Labels",
|
|
882
|
+
description:
|
|
883
|
+
"When enabled, incidents whose monitors have different sets of labels will be grouped into separate episodes (exact set match). When disabled, monitor labels are ignored for grouping.",
|
|
884
|
+
defaultValue: false,
|
|
885
|
+
isDefaultValueColumn: true,
|
|
886
|
+
})
|
|
887
|
+
@Column({
|
|
888
|
+
type: ColumnType.Boolean,
|
|
889
|
+
nullable: false,
|
|
890
|
+
default: false,
|
|
891
|
+
})
|
|
892
|
+
public groupByMonitorLabels?: boolean = undefined;
|
|
893
|
+
|
|
818
894
|
@ColumnAccessControl({
|
|
819
895
|
create: [
|
|
820
896
|
Permission.ProjectOwner,
|
|
@@ -17,6 +17,7 @@ import TableMetadata from "../../Types/Database/TableMetadata";
|
|
|
17
17
|
import TenantColumn from "../../Types/Database/TenantColumn";
|
|
18
18
|
import UniqueColumnBy from "../../Types/Database/UniqueColumnBy";
|
|
19
19
|
import Email from "../../Types/Email";
|
|
20
|
+
import MailTransportType from "../../Types/Email/MailTransportType";
|
|
20
21
|
import OAuthProviderType from "../../Types/Email/OAuthProviderType";
|
|
21
22
|
import SMTPAuthenticationType from "../../Types/Email/SMTPAuthenticationType";
|
|
22
23
|
import IconProp from "../../Types/Icon/IconProp";
|
|
@@ -478,12 +479,15 @@ export default class ProjectSmtpConfig extends BaseModel {
|
|
|
478
479
|
],
|
|
479
480
|
})
|
|
480
481
|
@TableColumn({
|
|
481
|
-
required:
|
|
482
|
+
required: false,
|
|
482
483
|
type: TableColumnType.ShortText,
|
|
484
|
+
title: "Hostname",
|
|
485
|
+
description:
|
|
486
|
+
"SMTP server hostname. Required when Transport is SMTP. Not used by HTTP-API transports like Microsoft Graph.",
|
|
483
487
|
example: "smtp.gmail.com",
|
|
484
488
|
})
|
|
485
489
|
@Column({
|
|
486
|
-
nullable:
|
|
490
|
+
nullable: true,
|
|
487
491
|
type: ColumnType.ShortText,
|
|
488
492
|
length: ColumnLength.ShortText,
|
|
489
493
|
transformer: Hostname.getDatabaseTransformer(),
|
|
@@ -513,12 +517,15 @@ export default class ProjectSmtpConfig extends BaseModel {
|
|
|
513
517
|
],
|
|
514
518
|
})
|
|
515
519
|
@TableColumn({
|
|
516
|
-
required:
|
|
520
|
+
required: false,
|
|
517
521
|
type: TableColumnType.Number,
|
|
522
|
+
title: "Port",
|
|
523
|
+
description:
|
|
524
|
+
"SMTP server port. Required when Transport is SMTP. Not used by HTTP-API transports.",
|
|
518
525
|
example: 587,
|
|
519
526
|
})
|
|
520
527
|
@Column({
|
|
521
|
-
nullable:
|
|
528
|
+
nullable: true,
|
|
522
529
|
type: ColumnType.Number,
|
|
523
530
|
transformer: Port.getDatabaseTransformer(),
|
|
524
531
|
})
|
|
@@ -616,18 +623,67 @@ export default class ProjectSmtpConfig extends BaseModel {
|
|
|
616
623
|
],
|
|
617
624
|
})
|
|
618
625
|
@TableColumn({
|
|
619
|
-
required:
|
|
626
|
+
required: false,
|
|
620
627
|
type: TableColumnType.Boolean,
|
|
628
|
+
title: "Use SSL / TLS",
|
|
629
|
+
description:
|
|
630
|
+
"Enable secure SMTP connection. Used only for SMTP transport — HTTP-API transports always use HTTPS.",
|
|
621
631
|
defaultValue: true,
|
|
622
632
|
example: true,
|
|
623
633
|
})
|
|
624
634
|
@Column({
|
|
625
|
-
nullable:
|
|
635
|
+
nullable: true,
|
|
626
636
|
type: ColumnType.Boolean,
|
|
627
637
|
default: true,
|
|
628
638
|
})
|
|
629
639
|
public secure?: boolean = undefined;
|
|
630
640
|
|
|
641
|
+
/*
|
|
642
|
+
* Transport type selects how mail is actually delivered.
|
|
643
|
+
* SMTP (default) uses the host/port above. HTTP-API transports (e.g. Microsoft
|
|
644
|
+
* Graph) ignore host/port and call the provider's REST API directly using the
|
|
645
|
+
* OAuth credentials below.
|
|
646
|
+
*/
|
|
647
|
+
|
|
648
|
+
@ColumnAccessControl({
|
|
649
|
+
create: [
|
|
650
|
+
Permission.ProjectOwner,
|
|
651
|
+
Permission.ProjectAdmin,
|
|
652
|
+
Permission.CreateProjectSMTPConfig,
|
|
653
|
+
],
|
|
654
|
+
read: [
|
|
655
|
+
Permission.ProjectOwner,
|
|
656
|
+
Permission.ProjectAdmin,
|
|
657
|
+
Permission.ProjectMember,
|
|
658
|
+
Permission.Viewer,
|
|
659
|
+
Permission.SettingsAdmin,
|
|
660
|
+
Permission.SettingsMember,
|
|
661
|
+
Permission.SettingsViewer,
|
|
662
|
+
Permission.ReadProjectSMTPConfig,
|
|
663
|
+
],
|
|
664
|
+
update: [
|
|
665
|
+
Permission.ProjectOwner,
|
|
666
|
+
Permission.ProjectAdmin,
|
|
667
|
+
Permission.EditProjectSMTPConfig,
|
|
668
|
+
],
|
|
669
|
+
})
|
|
670
|
+
@TableColumn({
|
|
671
|
+
required: true,
|
|
672
|
+
type: TableColumnType.ShortText,
|
|
673
|
+
title: "Transport",
|
|
674
|
+
description:
|
|
675
|
+
"How OneUptime delivers mail for this config. 'SMTP' uses the hostname/port. 'Microsoft Graph' sends via the Microsoft Graph REST API — use this when your Microsoft 365 tenant has SMTP AUTH disabled.",
|
|
676
|
+
defaultValue: MailTransportType.SMTP,
|
|
677
|
+
example: "SMTP",
|
|
678
|
+
})
|
|
679
|
+
@Column({
|
|
680
|
+
nullable: false,
|
|
681
|
+
type: ColumnType.ShortText,
|
|
682
|
+
length: ColumnLength.ShortText,
|
|
683
|
+
default: MailTransportType.SMTP,
|
|
684
|
+
})
|
|
685
|
+
public transportType?: MailTransportType = undefined;
|
|
686
|
+
|
|
631
687
|
// OAuth 2.0 Configuration Fields
|
|
632
688
|
|
|
633
689
|
@ColumnAccessControl({
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class AddLabelGroupByToGroupingRules1779971548393
|
|
4
|
+
implements MigrationInterface
|
|
5
|
+
{
|
|
6
|
+
public name: string = "AddLabelGroupByToGroupingRules1779971548393";
|
|
7
|
+
|
|
8
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
9
|
+
await queryRunner.query(
|
|
10
|
+
`ALTER TABLE "IncidentGroupingRule" ADD "groupByIncidentLabels" boolean NOT NULL DEFAULT false`,
|
|
11
|
+
);
|
|
12
|
+
await queryRunner.query(
|
|
13
|
+
`ALTER TABLE "IncidentGroupingRule" ADD "groupByMonitorLabels" boolean NOT NULL DEFAULT false`,
|
|
14
|
+
);
|
|
15
|
+
await queryRunner.query(
|
|
16
|
+
`ALTER TABLE "AlertGroupingRule" ADD "groupByAlertLabels" boolean NOT NULL DEFAULT false`,
|
|
17
|
+
);
|
|
18
|
+
await queryRunner.query(
|
|
19
|
+
`ALTER TABLE "AlertGroupingRule" ADD "groupByMonitorLabels" boolean NOT NULL DEFAULT false`,
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
24
|
+
await queryRunner.query(
|
|
25
|
+
`ALTER TABLE "AlertGroupingRule" DROP COLUMN "groupByMonitorLabels"`,
|
|
26
|
+
);
|
|
27
|
+
await queryRunner.query(
|
|
28
|
+
`ALTER TABLE "AlertGroupingRule" DROP COLUMN "groupByAlertLabels"`,
|
|
29
|
+
);
|
|
30
|
+
await queryRunner.query(
|
|
31
|
+
`ALTER TABLE "IncidentGroupingRule" DROP COLUMN "groupByMonitorLabels"`,
|
|
32
|
+
);
|
|
33
|
+
await queryRunner.query(
|
|
34
|
+
`ALTER TABLE "IncidentGroupingRule" DROP COLUMN "groupByIncidentLabels"`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class AddTransportTypeToProjectSmtpConfig1779975064262
|
|
4
|
+
implements MigrationInterface
|
|
5
|
+
{
|
|
6
|
+
name = "AddTransportTypeToProjectSmtpConfig1779975064262";
|
|
7
|
+
|
|
8
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
9
|
+
await queryRunner.query(
|
|
10
|
+
`ALTER TABLE "ProjectSMTPConfig" ADD "transportType" character varying(100) NOT NULL DEFAULT 'SMTP'`,
|
|
11
|
+
);
|
|
12
|
+
await queryRunner.query(
|
|
13
|
+
`ALTER TABLE "ProjectSMTPConfig" ALTER COLUMN "hostname" DROP NOT NULL`,
|
|
14
|
+
);
|
|
15
|
+
await queryRunner.query(
|
|
16
|
+
`ALTER TABLE "ProjectSMTPConfig" ALTER COLUMN "port" DROP NOT NULL`,
|
|
17
|
+
);
|
|
18
|
+
await queryRunner.query(
|
|
19
|
+
`ALTER TABLE "ProjectSMTPConfig" ALTER COLUMN "secure" DROP NOT NULL`,
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
24
|
+
await queryRunner.query(
|
|
25
|
+
`ALTER TABLE "ProjectSMTPConfig" ALTER COLUMN "secure" SET NOT NULL`,
|
|
26
|
+
);
|
|
27
|
+
await queryRunner.query(
|
|
28
|
+
`ALTER TABLE "ProjectSMTPConfig" ALTER COLUMN "port" SET NOT NULL`,
|
|
29
|
+
);
|
|
30
|
+
await queryRunner.query(
|
|
31
|
+
`ALTER TABLE "ProjectSMTPConfig" ALTER COLUMN "hostname" SET NOT NULL`,
|
|
32
|
+
);
|
|
33
|
+
await queryRunner.query(
|
|
34
|
+
`ALTER TABLE "ProjectSMTPConfig" DROP COLUMN "transportType"`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class AddSmtpTransportTypeToGlobalConfig1779976190561
|
|
4
|
+
implements MigrationInterface
|
|
5
|
+
{
|
|
6
|
+
name = "AddSmtpTransportTypeToGlobalConfig1779976190561";
|
|
7
|
+
|
|
8
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
9
|
+
await queryRunner.query(
|
|
10
|
+
`ALTER TABLE "GlobalConfig" ADD "smtpTransportType" character varying(100) DEFAULT 'SMTP'`,
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
15
|
+
await queryRunner.query(
|
|
16
|
+
`ALTER TABLE "GlobalConfig" DROP COLUMN "smtpTransportType"`,
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class MigrationName1779980428744 implements MigrationInterface {
|
|
4
|
+
public name = "MigrationName1779980428744";
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(
|
|
8
|
+
`ALTER TABLE "AlertEpisodeMember" ADD "isOwnerNotifiedOfAlertAdded" boolean NOT NULL DEFAULT false`,
|
|
9
|
+
);
|
|
10
|
+
await queryRunner.query(
|
|
11
|
+
`ALTER TABLE "IncidentEpisodeMember" ADD "isOwnerNotifiedOfIncidentAdded" boolean NOT NULL DEFAULT false`,
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
16
|
+
await queryRunner.query(
|
|
17
|
+
`ALTER TABLE "IncidentEpisodeMember" DROP COLUMN "isOwnerNotifiedOfIncidentAdded"`,
|
|
18
|
+
);
|
|
19
|
+
await queryRunner.query(
|
|
20
|
+
`ALTER TABLE "AlertEpisodeMember" DROP COLUMN "isOwnerNotifiedOfAlertAdded"`,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -356,6 +356,10 @@ import { ExpandOwnerRuleInheritFlags1779823516881 } from "./1779823516881-Expand
|
|
|
356
356
|
import { RenameStatusPageZhToZhCN1779827700000 } from "./1779827700000-RenameStatusPageZhToZhCN";
|
|
357
357
|
import { MigrationName1779879993421 } from "./1779879993421-MigrationName";
|
|
358
358
|
import { MigrationName1779882573463 } from "./1779882573463-MigrationName";
|
|
359
|
+
import { AddLabelGroupByToGroupingRules1779971548393 } from "./1779971548393-AddLabelGroupByToGroupingRules";
|
|
360
|
+
import { AddTransportTypeToProjectSmtpConfig1779975064262 } from "./1779975064262-AddTransportTypeToProjectSmtpConfig";
|
|
361
|
+
import { AddSmtpTransportTypeToGlobalConfig1779976190561 } from "./1779976190561-AddSmtpTransportTypeToGlobalConfig";
|
|
362
|
+
import { MigrationName1779980428744 } from "./1779980428744-MigrationName";
|
|
359
363
|
|
|
360
364
|
export default [
|
|
361
365
|
InitialMigration,
|
|
@@ -716,4 +720,8 @@ export default [
|
|
|
716
720
|
RenameStatusPageZhToZhCN1779827700000,
|
|
717
721
|
MigrationName1779879993421,
|
|
718
722
|
MigrationName1779882573463,
|
|
723
|
+
AddLabelGroupByToGroupingRules1779971548393,
|
|
724
|
+
AddTransportTypeToProjectSmtpConfig1779975064262,
|
|
725
|
+
AddSmtpTransportTypeToGlobalConfig1779976190561,
|
|
726
|
+
MigrationName1779980428744,
|
|
719
727
|
];
|
|
@@ -4,6 +4,7 @@ import { OnCreate, OnDelete } from "../Types/Database/Hooks";
|
|
|
4
4
|
import DatabaseService from "./DatabaseService";
|
|
5
5
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
6
6
|
import ObjectID from "../../Types/ObjectID";
|
|
7
|
+
import PositiveNumber from "../../Types/PositiveNumber";
|
|
7
8
|
import Model from "../../Models/DatabaseModels/AlertEpisodeMember";
|
|
8
9
|
import Alert from "../../Models/DatabaseModels/Alert";
|
|
9
10
|
import AlertEpisode from "../../Models/DatabaseModels/AlertEpisode";
|
|
@@ -62,6 +63,28 @@ export class Service extends DatabaseService<Model> {
|
|
|
62
63
|
createBy.data.addedAt = OneUptimeDate.getCurrentDate();
|
|
63
64
|
}
|
|
64
65
|
|
|
66
|
+
/*
|
|
67
|
+
* If this is the very first alert in the episode (the founder), the
|
|
68
|
+
* "episode created" notification already covers it. Mark the member as
|
|
69
|
+
* "already notified" so the AlertAdded-to-episode cron skips it. This
|
|
70
|
+
* avoids double-notifying owners when an episode is born with its first
|
|
71
|
+
* alert.
|
|
72
|
+
*/
|
|
73
|
+
if (createBy.data.isOwnerNotifiedOfAlertAdded === undefined) {
|
|
74
|
+
const existingMemberCount: PositiveNumber = await this.countBy({
|
|
75
|
+
query: {
|
|
76
|
+
alertEpisodeId: createBy.data.alertEpisodeId,
|
|
77
|
+
},
|
|
78
|
+
props: {
|
|
79
|
+
isRoot: true,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
if (existingMemberCount.toNumber() === 0) {
|
|
84
|
+
createBy.data.isOwnerNotifiedOfAlertAdded = true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
65
88
|
return { createBy, carryForward: null };
|
|
66
89
|
}
|
|
67
90
|
|
|
@@ -16,6 +16,7 @@ import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
|
16
16
|
import OneUptimeDate from "../../Types/Date";
|
|
17
17
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
18
18
|
import AlertGroupingRuleService from "./AlertGroupingRuleService";
|
|
19
|
+
import AlertService from "./AlertService";
|
|
19
20
|
import AlertEpisodeService from "./AlertEpisodeService";
|
|
20
21
|
import AlertEpisodeMemberService from "./AlertEpisodeMemberService";
|
|
21
22
|
import AlertEpisodeOwnerUserService from "./AlertEpisodeOwnerUserService";
|
|
@@ -91,6 +92,8 @@ class AlertGroupingEngineServiceClass {
|
|
|
91
92
|
groupByMonitor: true,
|
|
92
93
|
groupBySeverity: true,
|
|
93
94
|
groupByAlertTitle: true,
|
|
95
|
+
groupByAlertLabels: true,
|
|
96
|
+
groupByMonitorLabels: true,
|
|
94
97
|
// Time settings
|
|
95
98
|
enableTimeWindow: true,
|
|
96
99
|
timeWindowMinutes: true,
|
|
@@ -555,10 +558,84 @@ class AlertGroupingEngineServiceClass {
|
|
|
555
558
|
parts.push(`title:${normalizedTitle}`);
|
|
556
559
|
}
|
|
557
560
|
|
|
561
|
+
// Group by alert labels (exact set match) - only if explicitly enabled
|
|
562
|
+
if (rule.groupByAlertLabels && alert.id) {
|
|
563
|
+
const alertLabels: Array<Label> = await this.getAlertLabels(alert);
|
|
564
|
+
const sortedLabelIds: Array<string> = alertLabels
|
|
565
|
+
.map((l: Label) => {
|
|
566
|
+
return l.id?.toString() || "";
|
|
567
|
+
})
|
|
568
|
+
.filter((id: string) => {
|
|
569
|
+
return id.length > 0;
|
|
570
|
+
})
|
|
571
|
+
.sort();
|
|
572
|
+
parts.push(`alertLabels:${sortedLabelIds.join(",")}`);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// Group by monitor labels (exact set match) - only if explicitly enabled
|
|
576
|
+
if (rule.groupByMonitorLabels && alert.monitorId) {
|
|
577
|
+
const monitorLabels: Array<Label> = await this.getMonitorLabels(
|
|
578
|
+
alert.monitorId,
|
|
579
|
+
);
|
|
580
|
+
const sortedLabelIds: Array<string> = monitorLabels
|
|
581
|
+
.map((l: Label) => {
|
|
582
|
+
return l.id?.toString() || "";
|
|
583
|
+
})
|
|
584
|
+
.filter((id: string) => {
|
|
585
|
+
return id.length > 0;
|
|
586
|
+
})
|
|
587
|
+
.sort();
|
|
588
|
+
parts.push(`monitorLabels:${sortedLabelIds.join(",")}`);
|
|
589
|
+
}
|
|
590
|
+
|
|
558
591
|
// If no group by options are enabled, all matching alerts go into a single episode
|
|
559
592
|
return parts.join("|") || "default";
|
|
560
593
|
}
|
|
561
594
|
|
|
595
|
+
@CaptureSpan()
|
|
596
|
+
private async getAlertLabels(alert: Alert): Promise<Array<Label>> {
|
|
597
|
+
// If labels are already loaded on the alert, use them
|
|
598
|
+
if (alert.labels && Array.isArray(alert.labels)) {
|
|
599
|
+
return alert.labels;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
if (!alert.id) {
|
|
603
|
+
return [];
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// Re-load alert with labels
|
|
607
|
+
const reloadedAlert: Alert | null = await AlertService.findOneById({
|
|
608
|
+
id: alert.id,
|
|
609
|
+
select: {
|
|
610
|
+
labels: {
|
|
611
|
+
_id: true,
|
|
612
|
+
},
|
|
613
|
+
},
|
|
614
|
+
props: {
|
|
615
|
+
isRoot: true,
|
|
616
|
+
},
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
return reloadedAlert?.labels || [];
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
@CaptureSpan()
|
|
623
|
+
private async getMonitorLabels(monitorId: ObjectID): Promise<Array<Label>> {
|
|
624
|
+
const monitor: Monitor | null = await MonitorService.findOneById({
|
|
625
|
+
id: monitorId,
|
|
626
|
+
select: {
|
|
627
|
+
labels: {
|
|
628
|
+
_id: true,
|
|
629
|
+
},
|
|
630
|
+
},
|
|
631
|
+
props: {
|
|
632
|
+
isRoot: true,
|
|
633
|
+
},
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
return monitor?.labels || [];
|
|
637
|
+
}
|
|
638
|
+
|
|
562
639
|
@CaptureSpan()
|
|
563
640
|
private async findMatchingActiveEpisode(
|
|
564
641
|
projectId: ObjectID,
|
|
@@ -793,6 +870,12 @@ class AlertGroupingEngineServiceClass {
|
|
|
793
870
|
if (rule.groupByAlertTitle) {
|
|
794
871
|
groupByParts.push("Alert Title");
|
|
795
872
|
}
|
|
873
|
+
if (rule.groupByAlertLabels) {
|
|
874
|
+
groupByParts.push("Alert Labels");
|
|
875
|
+
}
|
|
876
|
+
if (rule.groupByMonitorLabels) {
|
|
877
|
+
groupByParts.push("Monitor Labels");
|
|
878
|
+
}
|
|
796
879
|
|
|
797
880
|
const groupByDescription: string =
|
|
798
881
|
groupByParts.length > 0
|