@oneuptime/common 10.5.4 → 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/GlobalConfig.ts +28 -0
- package/Models/DatabaseModels/IncidentEpisodeMember.ts +29 -0
- package/Models/DatabaseModels/ProjectSmtpConfig.ts +62 -6
- 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 +6 -0
- package/Server/Services/AlertEpisodeMemberService.ts +23 -0
- package/Server/Services/IncidentEpisodeMemberService.ts +23 -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/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/build/dist/Models/DatabaseModels/AlertEpisodeMember.js +30 -0
- package/build/dist/Models/DatabaseModels/AlertEpisodeMember.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/ProjectSmtpConfig.js +59 -6
- package/build/dist/Models/DatabaseModels/ProjectSmtpConfig.js.map +1 -1
- 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 +6 -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/IncidentEpisodeMemberService.js +20 -0
- package/build/dist/Server/Services/IncidentEpisodeMemberService.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/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/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: [
|
|
@@ -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: [
|
|
@@ -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 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
|
+
}
|
|
@@ -357,6 +357,9 @@ import { RenameStatusPageZhToZhCN1779827700000 } from "./1779827700000-RenameSta
|
|
|
357
357
|
import { MigrationName1779879993421 } from "./1779879993421-MigrationName";
|
|
358
358
|
import { MigrationName1779882573463 } from "./1779882573463-MigrationName";
|
|
359
359
|
import { AddLabelGroupByToGroupingRules1779971548393 } from "./1779971548393-AddLabelGroupByToGroupingRules";
|
|
360
|
+
import { AddTransportTypeToProjectSmtpConfig1779975064262 } from "./1779975064262-AddTransportTypeToProjectSmtpConfig";
|
|
361
|
+
import { AddSmtpTransportTypeToGlobalConfig1779976190561 } from "./1779976190561-AddSmtpTransportTypeToGlobalConfig";
|
|
362
|
+
import { MigrationName1779980428744 } from "./1779980428744-MigrationName";
|
|
360
363
|
|
|
361
364
|
export default [
|
|
362
365
|
InitialMigration,
|
|
@@ -718,4 +721,7 @@ export default [
|
|
|
718
721
|
MigrationName1779879993421,
|
|
719
722
|
MigrationName1779882573463,
|
|
720
723
|
AddLabelGroupByToGroupingRules1779971548393,
|
|
724
|
+
AddTransportTypeToProjectSmtpConfig1779975064262,
|
|
725
|
+
AddSmtpTransportTypeToGlobalConfig1779976190561,
|
|
726
|
+
MigrationName1779980428744,
|
|
721
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
|
|
|
@@ -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/IncidentEpisodeMember";
|
|
8
9
|
import Incident from "../../Models/DatabaseModels/Incident";
|
|
9
10
|
import IncidentEpisode from "../../Models/DatabaseModels/IncidentEpisode";
|
|
@@ -64,6 +65,28 @@ export class Service extends DatabaseService<Model> {
|
|
|
64
65
|
createBy.data.addedAt = OneUptimeDate.getCurrentDate();
|
|
65
66
|
}
|
|
66
67
|
|
|
68
|
+
/*
|
|
69
|
+
* If this is the very first incident in the episode (the founder), the
|
|
70
|
+
* "episode created" notification already covers it. Mark the member as
|
|
71
|
+
* "already notified" so the IncidentAdded-to-episode cron skips it. This
|
|
72
|
+
* avoids double-notifying owners when an episode is born with its first
|
|
73
|
+
* incident.
|
|
74
|
+
*/
|
|
75
|
+
if (createBy.data.isOwnerNotifiedOfIncidentAdded === undefined) {
|
|
76
|
+
const existingMemberCount: PositiveNumber = await this.countBy({
|
|
77
|
+
query: {
|
|
78
|
+
incidentEpisodeId: createBy.data.incidentEpisodeId,
|
|
79
|
+
},
|
|
80
|
+
props: {
|
|
81
|
+
isRoot: true,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
if (existingMemberCount.toNumber() === 0) {
|
|
86
|
+
createBy.data.isOwnerNotifiedOfIncidentAdded = true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
67
90
|
return { createBy, carryForward: null };
|
|
68
91
|
}
|
|
69
92
|
|
|
@@ -45,12 +45,24 @@ export class MailService extends BaseService {
|
|
|
45
45
|
|
|
46
46
|
if (options && options.mailServer) {
|
|
47
47
|
body["SMTP_ID"] = options.mailServer.id?.toString();
|
|
48
|
+
// host/port/secure are optional on EmailServer because HTTP-API
|
|
49
|
+
// transports (e.g. Microsoft Graph) don't use them. Only serialize the
|
|
50
|
+
// SMTP-only fields when they're actually present.
|
|
51
|
+
body["SMTP_TRANSPORT_TYPE"] =
|
|
52
|
+
options.mailServer.transportType || undefined;
|
|
48
53
|
body["SMTP_USERNAME"] = options.mailServer.username || undefined;
|
|
49
54
|
body["SMTP_EMAIL"] = options.mailServer.fromEmail.toString();
|
|
50
55
|
body["SMTP_FROM_NAME"] = options.mailServer.fromName;
|
|
51
|
-
body["SMTP_IS_SECURE"] =
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
body["SMTP_IS_SECURE"] =
|
|
57
|
+
options.mailServer.secure === undefined
|
|
58
|
+
? undefined
|
|
59
|
+
: options.mailServer.secure;
|
|
60
|
+
body["SMTP_PORT"] = options.mailServer.port
|
|
61
|
+
? options.mailServer.port.toNumber()
|
|
62
|
+
: undefined;
|
|
63
|
+
body["SMTP_HOST"] = options.mailServer.host
|
|
64
|
+
? options.mailServer.host.toString()
|
|
65
|
+
: undefined;
|
|
54
66
|
body["SMTP_PASSWORD"] = options.mailServer.password || undefined;
|
|
55
67
|
body["SMTP_AUTH_TYPE"] = options.mailServer.authType || undefined;
|
|
56
68
|
body["SMTP_CLIENT_ID"] = options.mailServer.clientId || undefined;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import DatabaseService from "./DatabaseService";
|
|
2
2
|
import EmailServer from "../../Types/Email/EmailServer";
|
|
3
|
+
import MailTransportType from "../../Types/Email/MailTransportType";
|
|
3
4
|
import SMTPAuthenticationType from "../../Types/Email/SMTPAuthenticationType";
|
|
4
5
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
5
6
|
import URL from "../../Types/API/URL";
|
|
@@ -21,17 +22,28 @@ export class Service extends DatabaseService<Model> {
|
|
|
21
22
|
throw new BadDataException("Project SMTP config id is not set");
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (!projectSmtpConfig.port) {
|
|
29
|
-
throw new BadDataException("Project SMTP config port is not set");
|
|
30
|
-
}
|
|
25
|
+
const transportType: MailTransportType =
|
|
26
|
+
projectSmtpConfig.transportType || MailTransportType.SMTP;
|
|
31
27
|
|
|
32
|
-
|
|
28
|
+
/*
|
|
29
|
+
* Get auth type, default to UsernamePassword for backward compatibility.
|
|
30
|
+
* Microsoft Graph always uses OAuth (Client Credentials) regardless of what
|
|
31
|
+
* the user picked — but we still let the existing OAuth validation apply.
|
|
32
|
+
*/
|
|
33
33
|
const authType: SMTPAuthenticationType =
|
|
34
|
-
|
|
34
|
+
transportType === MailTransportType.MicrosoftGraph
|
|
35
|
+
? SMTPAuthenticationType.OAuth
|
|
36
|
+
: projectSmtpConfig.authType || SMTPAuthenticationType.UsernamePassword;
|
|
37
|
+
|
|
38
|
+
if (transportType === MailTransportType.SMTP) {
|
|
39
|
+
if (!projectSmtpConfig.hostname) {
|
|
40
|
+
throw new BadDataException("Project SMTP config host is not set");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!projectSmtpConfig.port) {
|
|
44
|
+
throw new BadDataException("Project SMTP config port is not set");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
35
47
|
|
|
36
48
|
// Validate based on auth type
|
|
37
49
|
if (authType === SMTPAuthenticationType.UsernamePassword) {
|
|
@@ -43,7 +55,14 @@ export class Service extends DatabaseService<Model> {
|
|
|
43
55
|
throw new BadDataException("Project SMTP config password is not set");
|
|
44
56
|
}
|
|
45
57
|
} else if (authType === SMTPAuthenticationType.OAuth) {
|
|
46
|
-
|
|
58
|
+
/*
|
|
59
|
+
* For Microsoft Graph, username is optional — we fall back to fromEmail
|
|
60
|
+
* as the sender mailbox. For SMTP+XOAUTH2, username is required.
|
|
61
|
+
*/
|
|
62
|
+
if (
|
|
63
|
+
transportType === MailTransportType.SMTP &&
|
|
64
|
+
!projectSmtpConfig.username
|
|
65
|
+
) {
|
|
47
66
|
throw new BadDataException(
|
|
48
67
|
"Project SMTP config username (email address) is not set for OAuth",
|
|
49
68
|
);
|
|
@@ -85,6 +104,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
85
104
|
|
|
86
105
|
return {
|
|
87
106
|
id: projectSmtpConfig.id!,
|
|
107
|
+
transportType: transportType,
|
|
88
108
|
host: projectSmtpConfig.hostname,
|
|
89
109
|
port: projectSmtpConfig.port,
|
|
90
110
|
username: projectSmtpConfig.username,
|
|
@@ -684,6 +684,7 @@ Stay informed about service availability! 🚀`;
|
|
|
684
684
|
name: true,
|
|
685
685
|
smtpConfig: {
|
|
686
686
|
_id: true,
|
|
687
|
+
transportType: true,
|
|
687
688
|
hostname: true,
|
|
688
689
|
port: true,
|
|
689
690
|
username: true,
|
|
@@ -915,6 +916,7 @@ Stay informed about service availability! 🚀`;
|
|
|
915
916
|
name: true,
|
|
916
917
|
smtpConfig: {
|
|
917
918
|
_id: true,
|
|
919
|
+
transportType: true,
|
|
918
920
|
hostname: true,
|
|
919
921
|
port: true,
|
|
920
922
|
username: true,
|
|
@@ -1347,6 +1349,7 @@ Stay informed about service availability! 🚀`;
|
|
|
1347
1349
|
allowSubscribersToChooseEventTypes: true,
|
|
1348
1350
|
smtpConfig: {
|
|
1349
1351
|
_id: true,
|
|
1352
|
+
transportType: true,
|
|
1350
1353
|
hostname: true,
|
|
1351
1354
|
port: true,
|
|
1352
1355
|
username: true,
|
|
@@ -706,6 +706,12 @@ export class Service extends DatabaseService<UserNotificationSetting> {
|
|
|
706
706
|
projectId,
|
|
707
707
|
NotificationSettingEventType.SEND_ALERT_EPISODE_STATE_CHANGED_OWNER_NOTIFICATION,
|
|
708
708
|
);
|
|
709
|
+
|
|
710
|
+
await this.addNotificationSettingIfNotExists(
|
|
711
|
+
userId,
|
|
712
|
+
projectId,
|
|
713
|
+
NotificationSettingEventType.SEND_ALERT_ADDED_TO_EPISODE_OWNER_NOTIFICATION,
|
|
714
|
+
);
|
|
709
715
|
}
|
|
710
716
|
|
|
711
717
|
private async addIncidentEpisodeNotificationSettings(
|
|
@@ -723,6 +729,12 @@ export class Service extends DatabaseService<UserNotificationSetting> {
|
|
|
723
729
|
projectId,
|
|
724
730
|
NotificationSettingEventType.SEND_INCIDENT_EPISODE_STATE_CHANGED_OWNER_NOTIFICATION,
|
|
725
731
|
);
|
|
732
|
+
|
|
733
|
+
await this.addNotificationSettingIfNotExists(
|
|
734
|
+
userId,
|
|
735
|
+
projectId,
|
|
736
|
+
NotificationSettingEventType.SEND_INCIDENT_ADDED_TO_EPISODE_OWNER_NOTIFICATION,
|
|
737
|
+
);
|
|
726
738
|
}
|
|
727
739
|
|
|
728
740
|
private async addNotificationSettingIfNotExists(
|
|
@@ -94,6 +94,8 @@ const templateIdByEventType: Record<
|
|
|
94
94
|
WhatsAppTemplateIds.AlertEpisodeStateChangedOwnerNotification,
|
|
95
95
|
[NotificationSettingEventType.SEND_ALERT_EPISODE_OWNER_ADDED_NOTIFICATION]:
|
|
96
96
|
WhatsAppTemplateIds.AlertEpisodeOwnerAddedNotification,
|
|
97
|
+
[NotificationSettingEventType.SEND_ALERT_ADDED_TO_EPISODE_OWNER_NOTIFICATION]:
|
|
98
|
+
WhatsAppTemplateIds.AlertAddedToEpisodeOwnerNotification,
|
|
97
99
|
[NotificationSettingEventType.SEND_INCIDENT_EPISODE_CREATED_OWNER_NOTIFICATION]:
|
|
98
100
|
WhatsAppTemplateIds.IncidentEpisodeCreatedOwnerNotification,
|
|
99
101
|
[NotificationSettingEventType.SEND_INCIDENT_EPISODE_NOTE_POSTED_OWNER_NOTIFICATION]:
|
|
@@ -102,6 +104,8 @@ const templateIdByEventType: Record<
|
|
|
102
104
|
WhatsAppTemplateIds.IncidentEpisodeStateChangedOwnerNotification,
|
|
103
105
|
[NotificationSettingEventType.SEND_INCIDENT_EPISODE_OWNER_ADDED_NOTIFICATION]:
|
|
104
106
|
WhatsAppTemplateIds.IncidentEpisodeOwnerAddedNotification,
|
|
107
|
+
[NotificationSettingEventType.SEND_INCIDENT_ADDED_TO_EPISODE_OWNER_NOTIFICATION]:
|
|
108
|
+
WhatsAppTemplateIds.IncidentAddedToEpisodeOwnerNotification,
|
|
105
109
|
[NotificationSettingEventType.SEND_MONITOR_OWNER_ADDED_NOTIFICATION]:
|
|
106
110
|
WhatsAppTemplateIds.MonitorOwnerAddedNotification,
|
|
107
111
|
[NotificationSettingEventType.SEND_MONITOR_CREATED_OWNER_NOTIFICATION]:
|
|
@@ -3,20 +3,38 @@ import URL from "../API/URL";
|
|
|
3
3
|
import Email from "../Email";
|
|
4
4
|
import ObjectID from "../ObjectID";
|
|
5
5
|
import Port from "../Port";
|
|
6
|
+
import MailTransportType from "./MailTransportType";
|
|
6
7
|
import OAuthProviderType from "./OAuthProviderType";
|
|
7
8
|
import SMTPAuthenticationType from "./SMTPAuthenticationType";
|
|
8
9
|
|
|
9
10
|
export default interface EmailServer {
|
|
10
11
|
id?: ObjectID | undefined; // If this is custom SMTP, this is the ID of the SMTP config. Otherwise, it's undefined
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* Transport selection.
|
|
15
|
+
* Defaults to SMTP when undefined for backwards compatibility with existing
|
|
16
|
+
* EmailServer constructions.
|
|
17
|
+
*/
|
|
18
|
+
transportType?: MailTransportType | undefined;
|
|
19
|
+
|
|
20
|
+
/*
|
|
21
|
+
* SMTP transport fields. Required when transportType === SMTP (or undefined).
|
|
22
|
+
* Not used for HTTP-API transports like MicrosoftGraph.
|
|
23
|
+
*/
|
|
24
|
+
host?: Hostname | undefined;
|
|
25
|
+
port?: Port | undefined;
|
|
26
|
+
secure?: boolean | undefined;
|
|
27
|
+
|
|
13
28
|
username: string | undefined;
|
|
14
29
|
password: string | undefined;
|
|
15
|
-
secure: boolean;
|
|
16
30
|
fromEmail: Email;
|
|
17
31
|
fromName: string;
|
|
18
32
|
|
|
19
|
-
|
|
33
|
+
/*
|
|
34
|
+
* OAuth 2.0 fields. Used by:
|
|
35
|
+
* - SMTP transport when authType === OAuth (XOAUTH2)
|
|
36
|
+
* - HTTP-API transports (always — they always authenticate via OAuth2)
|
|
37
|
+
*/
|
|
20
38
|
authType?: SMTPAuthenticationType | undefined;
|
|
21
39
|
clientId?: string | undefined; // OAuth Application Client ID
|
|
22
40
|
clientSecret?: string | undefined; // OAuth Application Client Secret
|
|
@@ -47,11 +47,13 @@ enum EmailTemplateType {
|
|
|
47
47
|
AlertEpisodeOwnerStateChanged = "AlertEpisodeOwnerStateChanged.hbs",
|
|
48
48
|
AlertEpisodeOwnerNotePosted = "AlertEpisodeOwnerNotePosted.hbs",
|
|
49
49
|
AlertEpisodeOwnerResourceCreated = "AlertEpisodeOwnerResourceCreated.hbs",
|
|
50
|
+
AlertEpisodeOwnerAlertAdded = "AlertEpisodeOwnerAlertAdded.hbs",
|
|
50
51
|
|
|
51
52
|
IncidentEpisodeOwnerAdded = "IncidentEpisodeOwnerAdded.hbs",
|
|
52
53
|
IncidentEpisodeOwnerStateChanged = "IncidentEpisodeOwnerStateChanged.hbs",
|
|
53
54
|
IncidentEpisodeOwnerNotePosted = "IncidentEpisodeOwnerNotePosted.hbs",
|
|
54
55
|
IncidentEpisodeOwnerResourceCreated = "IncidentEpisodeOwnerResourceCreated.hbs",
|
|
56
|
+
IncidentEpisodeOwnerIncidentAdded = "IncidentEpisodeOwnerIncidentAdded.hbs",
|
|
55
57
|
|
|
56
58
|
SubscriberEpisodeCreated = "SubscriberEpisodeCreated.hbs",
|
|
57
59
|
SubscriberEpisodeStateChanged = "SubscriberEpisodeStateChanged.hbs",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport type for delivering email.
|
|
3
|
+
*
|
|
4
|
+
* - SMTP: traditional SMTP server (with optional XOAUTH2 / username+password / no auth)
|
|
5
|
+
* - MicrosoftGraph: Microsoft 365 mailbox via Microsoft Graph API
|
|
6
|
+
* (POST /v1.0/users/{sender}/sendMail). Required when the tenant has SMTP AUTH
|
|
7
|
+
* disabled — the Azure AD app only needs Mail.Send (application) permission.
|
|
8
|
+
*
|
|
9
|
+
* Adding a new HTTP-API provider (Gmail, SES, etc.) means adding a new enum value
|
|
10
|
+
* and a matching MailProvider implementation. See
|
|
11
|
+
* App/FeatureSet/Notification/Services/MailProviders.
|
|
12
|
+
*/
|
|
13
|
+
enum MailTransportType {
|
|
14
|
+
SMTP = "SMTP",
|
|
15
|
+
MicrosoftGraph = "Microsoft Graph",
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default MailTransportType;
|