@oneuptime/common 9.5.6 → 9.5.8
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/AlertEpisode.ts +25 -0
- package/Models/DatabaseModels/AlertGroupingRule.ts +2 -2
- package/Models/DatabaseModels/IncidentEpisode.ts +25 -0
- package/Models/DatabaseModels/IncidentGroupingRule.ts +2 -2
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/OpenSourceDeployment.ts +140 -0
- package/Models/DatabaseModels/UserPush.ts +2 -1
- package/Server/API/OpenSourceDeploymentAPI.ts +73 -0
- package/Server/API/UserPushAPI.ts +51 -4
- package/Server/EnvironmentConfig.ts +3 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1770237245070-MigrationName.ts +7 -7
- package/Server/Infrastructure/Postgres/SchemaMigrations/1770668054908-MigrationName.ts +26 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1770728946893-MigrationName.ts +47 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1770732721195-MigrationName.ts +27 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Middleware/UserAuthorization.ts +14 -9
- package/Server/Services/AlertEpisodeMemberService.ts +10 -20
- package/Server/Services/AlertEpisodeService.ts +3 -2
- package/Server/Services/AlertGroupingEngineService.ts +1 -0
- package/Server/Services/IncidentEpisodeMemberService.ts +12 -20
- package/Server/Services/IncidentEpisodeService.ts +65 -3
- package/Server/Services/IncidentGroupingEngineService.ts +1 -0
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/OpenSourceDeploymentService.ts +10 -0
- package/Server/Services/PushNotificationService.ts +129 -27
- package/Server/Services/UserNotificationRuleService.ts +13 -3
- package/Server/Services/UserPushService.ts +2 -1
- package/Server/Utils/PushNotificationUtil.ts +56 -0
- package/Types/PushNotification/PushDeviceType.ts +7 -0
- package/Types/PushNotification/PushNotificationRequest.ts +3 -1
- package/UI/Components/Forms/BasicForm.tsx +8 -1
- package/UI/Components/Forms/Types/Field.ts +3 -0
- package/UI/Components/ModelDelete/ModelDelete.tsx +4 -1
- package/UI/Components/ModelDetail/CardModelDetail.tsx +4 -0
- package/UI/Components/ModelDetail/ModelDetail.tsx +4 -1
- package/UI/Components/Page/ModelPage.tsx +4 -1
- package/build/dist/Models/DatabaseModels/AlertEpisode.js +26 -0
- package/build/dist/Models/DatabaseModels/AlertEpisode.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertGroupingRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertGroupingRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js +26 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OpenSourceDeployment.js +167 -0
- package/build/dist/Models/DatabaseModels/OpenSourceDeployment.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserPush.js +2 -1
- package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
- package/build/dist/Server/API/OpenSourceDeploymentAPI.js +55 -0
- package/build/dist/Server/API/OpenSourceDeploymentAPI.js.map +1 -0
- package/build/dist/Server/API/UserPushAPI.js +34 -3
- package/build/dist/Server/API/UserPushAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +1 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770237245070-MigrationName.js +7 -7
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770237245070-MigrationName.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770668054908-MigrationName.js +36 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770668054908-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770728946893-MigrationName.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770728946893-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770732721195-MigrationName.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770732721195-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/Middleware/UserAuthorization.js +10 -4
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeMemberService.js +7 -13
- package/build/dist/Server/Services/AlertEpisodeMemberService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeService.js +3 -2
- package/build/dist/Server/Services/AlertEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/AlertGroupingEngineService.js +1 -0
- package/build/dist/Server/Services/AlertGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeMemberService.js +7 -13
- package/build/dist/Server/Services/IncidentEpisodeMemberService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js +43 -3
- package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/IncidentGroupingEngineService.js +1 -0
- package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/OpenSourceDeploymentService.js +9 -0
- package/build/dist/Server/Services/OpenSourceDeploymentService.js.map +1 -0
- package/build/dist/Server/Services/PushNotificationService.js +77 -21
- package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js +12 -9
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserPushService.js +2 -1
- package/build/dist/Server/Services/UserPushService.js.map +1 -1
- package/build/dist/Server/Utils/PushNotificationUtil.js +32 -8
- package/build/dist/Server/Utils/PushNotificationUtil.js.map +1 -1
- package/build/dist/Types/PushNotification/PushDeviceType.js +8 -0
- package/build/dist/Types/PushNotification/PushDeviceType.js.map +1 -0
- package/build/dist/UI/Components/Forms/BasicForm.js +3 -1
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/ModelDelete/ModelDelete.js +2 -1
- package/build/dist/UI/Components/ModelDelete/ModelDelete.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +2 -2
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/ModelDetail.js +2 -1
- package/build/dist/UI/Components/ModelDetail/ModelDetail.js.map +1 -1
- package/build/dist/UI/Components/Page/ModelPage.js +2 -1
- package/build/dist/UI/Components/Page/ModelPage.js.map +1 -1
- package/package.json +2 -1
|
@@ -543,6 +543,31 @@ export default class AlertEpisode extends BaseModel {
|
|
|
543
543
|
})
|
|
544
544
|
public resolvedAt?: Date = undefined;
|
|
545
545
|
|
|
546
|
+
@ColumnAccessControl({
|
|
547
|
+
create: [],
|
|
548
|
+
read: [
|
|
549
|
+
Permission.ProjectOwner,
|
|
550
|
+
Permission.ProjectAdmin,
|
|
551
|
+
Permission.ProjectMember,
|
|
552
|
+
Permission.ReadAlertEpisode,
|
|
553
|
+
Permission.ReadAllProjectResources,
|
|
554
|
+
],
|
|
555
|
+
update: [],
|
|
556
|
+
})
|
|
557
|
+
@Index()
|
|
558
|
+
@TableColumn({
|
|
559
|
+
type: TableColumnType.Date,
|
|
560
|
+
title: "All Alerts Resolved At",
|
|
561
|
+
description:
|
|
562
|
+
"When all alerts in this episode were first detected as resolved. Used for resolve delay calculation.",
|
|
563
|
+
})
|
|
564
|
+
@Column({
|
|
565
|
+
type: ColumnType.Date,
|
|
566
|
+
nullable: true,
|
|
567
|
+
unique: false,
|
|
568
|
+
})
|
|
569
|
+
public allAlertsResolvedAt?: Date = undefined;
|
|
570
|
+
|
|
546
571
|
@ColumnAccessControl({
|
|
547
572
|
create: [
|
|
548
573
|
Permission.ProjectOwner,
|
|
@@ -674,13 +674,13 @@ export default class AlertGroupingRule extends BaseModel {
|
|
|
674
674
|
title: "Group By Monitor",
|
|
675
675
|
description:
|
|
676
676
|
"When enabled, alerts from different monitors will be grouped into separate episodes. When disabled, alerts from any monitor can be grouped together.",
|
|
677
|
-
defaultValue:
|
|
677
|
+
defaultValue: false,
|
|
678
678
|
isDefaultValueColumn: true,
|
|
679
679
|
})
|
|
680
680
|
@Column({
|
|
681
681
|
type: ColumnType.Boolean,
|
|
682
682
|
nullable: false,
|
|
683
|
-
default:
|
|
683
|
+
default: false,
|
|
684
684
|
})
|
|
685
685
|
public groupByMonitor?: boolean = undefined;
|
|
686
686
|
|
|
@@ -542,6 +542,31 @@ export default class IncidentEpisode extends BaseModel {
|
|
|
542
542
|
})
|
|
543
543
|
public resolvedAt?: Date = undefined;
|
|
544
544
|
|
|
545
|
+
@ColumnAccessControl({
|
|
546
|
+
create: [],
|
|
547
|
+
read: [
|
|
548
|
+
Permission.ProjectOwner,
|
|
549
|
+
Permission.ProjectAdmin,
|
|
550
|
+
Permission.ProjectMember,
|
|
551
|
+
Permission.ReadIncidentEpisode,
|
|
552
|
+
Permission.ReadAllProjectResources,
|
|
553
|
+
],
|
|
554
|
+
update: [],
|
|
555
|
+
})
|
|
556
|
+
@Index()
|
|
557
|
+
@TableColumn({
|
|
558
|
+
type: TableColumnType.Date,
|
|
559
|
+
title: "All Incidents Resolved At",
|
|
560
|
+
description:
|
|
561
|
+
"When all incidents in this episode were first detected as resolved. Used for resolve delay calculation.",
|
|
562
|
+
})
|
|
563
|
+
@Column({
|
|
564
|
+
type: ColumnType.Date,
|
|
565
|
+
nullable: true,
|
|
566
|
+
unique: false,
|
|
567
|
+
})
|
|
568
|
+
public allIncidentsResolvedAt?: Date = undefined;
|
|
569
|
+
|
|
545
570
|
@ColumnAccessControl({
|
|
546
571
|
create: [
|
|
547
572
|
Permission.ProjectOwner,
|
|
@@ -678,13 +678,13 @@ export default class IncidentGroupingRule extends BaseModel {
|
|
|
678
678
|
title: "Group By Monitor",
|
|
679
679
|
description:
|
|
680
680
|
"When enabled, incidents from different monitors will be grouped into separate episodes. When disabled, incidents from any monitor can be grouped together.",
|
|
681
|
-
defaultValue:
|
|
681
|
+
defaultValue: false,
|
|
682
682
|
isDefaultValueColumn: true,
|
|
683
683
|
})
|
|
684
684
|
@Column({
|
|
685
685
|
type: ColumnType.Boolean,
|
|
686
686
|
nullable: false,
|
|
687
|
-
default:
|
|
687
|
+
default: false,
|
|
688
688
|
})
|
|
689
689
|
public groupByMonitor?: boolean = undefined;
|
|
690
690
|
|
|
@@ -98,6 +98,7 @@ import ProjectSmtpConfig from "./ProjectSmtpConfig";
|
|
|
98
98
|
import ProjectSSO from "./ProjectSso";
|
|
99
99
|
import PromoCode from "./PromoCode";
|
|
100
100
|
import EnterpriseLicense from "./EnterpriseLicense";
|
|
101
|
+
import OpenSourceDeployment from "./OpenSourceDeployment";
|
|
101
102
|
import Reseller from "./Reseller";
|
|
102
103
|
import ResellerPlan from "./ResellerPlan";
|
|
103
104
|
// ScheduledMaintenances
|
|
@@ -411,6 +412,7 @@ const AllModelTypes: Array<{
|
|
|
411
412
|
|
|
412
413
|
PromoCode,
|
|
413
414
|
EnterpriseLicense,
|
|
415
|
+
OpenSourceDeployment,
|
|
414
416
|
|
|
415
417
|
GlobalConfig,
|
|
416
418
|
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
|
2
|
+
import Route from "../../Types/API/Route";
|
|
3
|
+
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
|
|
4
|
+
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
|
|
5
|
+
import ColumnLength from "../../Types/Database/ColumnLength";
|
|
6
|
+
import ColumnType from "../../Types/Database/ColumnType";
|
|
7
|
+
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
|
|
8
|
+
import TableColumn from "../../Types/Database/TableColumn";
|
|
9
|
+
import TableColumnType from "../../Types/Database/TableColumnType";
|
|
10
|
+
import TableMetadata from "../../Types/Database/TableMetadata";
|
|
11
|
+
import IconProp from "../../Types/Icon/IconProp";
|
|
12
|
+
import { Column, Entity } from "typeorm";
|
|
13
|
+
|
|
14
|
+
@TableAccessControl({
|
|
15
|
+
create: [],
|
|
16
|
+
read: [],
|
|
17
|
+
update: [],
|
|
18
|
+
delete: [],
|
|
19
|
+
})
|
|
20
|
+
@CrudApiEndpoint(new Route("/open-source-deployment"))
|
|
21
|
+
@TableMetadata({
|
|
22
|
+
tableName: "OpenSourceDeployment",
|
|
23
|
+
singularName: "Open Source Deployment",
|
|
24
|
+
pluralName: "Open Source Deployments",
|
|
25
|
+
icon: IconProp.Globe,
|
|
26
|
+
tableDescription:
|
|
27
|
+
"Open source deployment registrations from self-hosted instances.",
|
|
28
|
+
})
|
|
29
|
+
@Entity({
|
|
30
|
+
name: "OpenSourceDeployment",
|
|
31
|
+
})
|
|
32
|
+
export default class OpenSourceDeployment extends BaseModel {
|
|
33
|
+
@ColumnAccessControl({
|
|
34
|
+
create: [],
|
|
35
|
+
read: [],
|
|
36
|
+
update: [],
|
|
37
|
+
})
|
|
38
|
+
@TableColumn({
|
|
39
|
+
required: true,
|
|
40
|
+
type: TableColumnType.Email,
|
|
41
|
+
title: "Email",
|
|
42
|
+
description: "Email address of the user who registered.",
|
|
43
|
+
})
|
|
44
|
+
@Column({
|
|
45
|
+
nullable: false,
|
|
46
|
+
type: ColumnType.Email,
|
|
47
|
+
length: ColumnLength.Email,
|
|
48
|
+
})
|
|
49
|
+
public email?: string = undefined;
|
|
50
|
+
|
|
51
|
+
@ColumnAccessControl({
|
|
52
|
+
create: [],
|
|
53
|
+
read: [],
|
|
54
|
+
update: [],
|
|
55
|
+
})
|
|
56
|
+
@TableColumn({
|
|
57
|
+
required: true,
|
|
58
|
+
type: TableColumnType.ShortText,
|
|
59
|
+
title: "Name",
|
|
60
|
+
description: "Full name of the user who registered.",
|
|
61
|
+
})
|
|
62
|
+
@Column({
|
|
63
|
+
nullable: false,
|
|
64
|
+
type: ColumnType.ShortText,
|
|
65
|
+
length: ColumnLength.ShortText,
|
|
66
|
+
})
|
|
67
|
+
public name?: string = undefined;
|
|
68
|
+
|
|
69
|
+
@ColumnAccessControl({
|
|
70
|
+
create: [],
|
|
71
|
+
read: [],
|
|
72
|
+
update: [],
|
|
73
|
+
})
|
|
74
|
+
@TableColumn({
|
|
75
|
+
required: false,
|
|
76
|
+
type: TableColumnType.ShortText,
|
|
77
|
+
title: "Company Name",
|
|
78
|
+
description: "Company name of the user who registered.",
|
|
79
|
+
})
|
|
80
|
+
@Column({
|
|
81
|
+
nullable: true,
|
|
82
|
+
type: ColumnType.ShortText,
|
|
83
|
+
length: ColumnLength.ShortText,
|
|
84
|
+
})
|
|
85
|
+
public companyName?: string = undefined;
|
|
86
|
+
|
|
87
|
+
@ColumnAccessControl({
|
|
88
|
+
create: [],
|
|
89
|
+
read: [],
|
|
90
|
+
update: [],
|
|
91
|
+
})
|
|
92
|
+
@TableColumn({
|
|
93
|
+
required: false,
|
|
94
|
+
type: TableColumnType.Phone,
|
|
95
|
+
title: "Company Phone Number",
|
|
96
|
+
description: "Phone number of the user who registered.",
|
|
97
|
+
})
|
|
98
|
+
@Column({
|
|
99
|
+
nullable: true,
|
|
100
|
+
type: ColumnType.Phone,
|
|
101
|
+
length: ColumnLength.Phone,
|
|
102
|
+
})
|
|
103
|
+
public companyPhoneNumber?: string = undefined;
|
|
104
|
+
|
|
105
|
+
@ColumnAccessControl({
|
|
106
|
+
create: [],
|
|
107
|
+
read: [],
|
|
108
|
+
update: [],
|
|
109
|
+
})
|
|
110
|
+
@TableColumn({
|
|
111
|
+
required: true,
|
|
112
|
+
type: TableColumnType.ShortText,
|
|
113
|
+
title: "Version",
|
|
114
|
+
description: "OneUptime version of the self-hosted instance.",
|
|
115
|
+
})
|
|
116
|
+
@Column({
|
|
117
|
+
nullable: false,
|
|
118
|
+
type: ColumnType.ShortText,
|
|
119
|
+
length: ColumnLength.ShortText,
|
|
120
|
+
})
|
|
121
|
+
public oneuptimeVersion?: string = undefined;
|
|
122
|
+
|
|
123
|
+
@ColumnAccessControl({
|
|
124
|
+
create: [],
|
|
125
|
+
read: [],
|
|
126
|
+
update: [],
|
|
127
|
+
})
|
|
128
|
+
@TableColumn({
|
|
129
|
+
required: false,
|
|
130
|
+
type: TableColumnType.ShortText,
|
|
131
|
+
title: "Instance URL",
|
|
132
|
+
description: "URL of the self-hosted instance.",
|
|
133
|
+
})
|
|
134
|
+
@Column({
|
|
135
|
+
nullable: true,
|
|
136
|
+
type: ColumnType.ShortText,
|
|
137
|
+
length: ColumnLength.ShortText,
|
|
138
|
+
})
|
|
139
|
+
public instanceUrl?: string = undefined;
|
|
140
|
+
}
|
|
@@ -16,6 +16,7 @@ import TenantColumn from "../../Types/Database/TenantColumn";
|
|
|
16
16
|
import IconProp from "../../Types/Icon/IconProp";
|
|
17
17
|
import ObjectID from "../../Types/ObjectID";
|
|
18
18
|
import Permission from "../../Types/Permission";
|
|
19
|
+
import PushDeviceType from "../../Types/PushNotification/PushDeviceType";
|
|
19
20
|
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
|
20
21
|
|
|
21
22
|
@TenantColumn("projectId")
|
|
@@ -122,7 +123,7 @@ class UserPush extends BaseModel {
|
|
|
122
123
|
unique: false,
|
|
123
124
|
nullable: false,
|
|
124
125
|
})
|
|
125
|
-
public deviceType?:
|
|
126
|
+
public deviceType?: PushDeviceType = undefined;
|
|
126
127
|
|
|
127
128
|
@ColumnAccessControl({
|
|
128
129
|
create: [Permission.CurrentUser],
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import OpenSourceDeployment from "../../Models/DatabaseModels/OpenSourceDeployment";
|
|
2
|
+
import { JSONObject } from "../../Types/JSON";
|
|
3
|
+
import URL from "../../Types/API/URL";
|
|
4
|
+
import API from "../../Utils/API";
|
|
5
|
+
import OpenSourceDeploymentService, {
|
|
6
|
+
Service as OpenSourceDeploymentServiceType,
|
|
7
|
+
} from "../Services/OpenSourceDeploymentService";
|
|
8
|
+
import { OpenSourceDeploymentWebhookUrl } from "../EnvironmentConfig";
|
|
9
|
+
import logger from "../Utils/Logger";
|
|
10
|
+
import Response from "../Utils/Response";
|
|
11
|
+
import {
|
|
12
|
+
ExpressRequest,
|
|
13
|
+
ExpressResponse,
|
|
14
|
+
NextFunction,
|
|
15
|
+
} from "../Utils/Express";
|
|
16
|
+
import BaseAPI from "./BaseAPI";
|
|
17
|
+
|
|
18
|
+
export default class OpenSourceDeploymentAPI extends BaseAPI<
|
|
19
|
+
OpenSourceDeployment,
|
|
20
|
+
OpenSourceDeploymentServiceType
|
|
21
|
+
> {
|
|
22
|
+
public constructor() {
|
|
23
|
+
super(OpenSourceDeployment, OpenSourceDeploymentService);
|
|
24
|
+
|
|
25
|
+
this.router.post(
|
|
26
|
+
`${new this.entityType().getCrudApiPath()?.toString()}/register`,
|
|
27
|
+
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
28
|
+
try {
|
|
29
|
+
const body: JSONObject = req.body;
|
|
30
|
+
|
|
31
|
+
const deployment: OpenSourceDeployment = new OpenSourceDeployment();
|
|
32
|
+
|
|
33
|
+
deployment.email = (body["email"] as string) || "";
|
|
34
|
+
deployment.name = (body["name"] as string) || "";
|
|
35
|
+
deployment.companyName = (body["companyName"] as string) || "";
|
|
36
|
+
deployment.companyPhoneNumber =
|
|
37
|
+
(body["companyPhoneNumber"] as string) || "";
|
|
38
|
+
deployment.oneuptimeVersion =
|
|
39
|
+
(body["oneuptimeVersion"] as string) || "unknown";
|
|
40
|
+
deployment.instanceUrl = (body["instanceUrl"] as string) || "";
|
|
41
|
+
|
|
42
|
+
await OpenSourceDeploymentService.create({
|
|
43
|
+
data: deployment,
|
|
44
|
+
props: {
|
|
45
|
+
isRoot: true,
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
if (OpenSourceDeploymentWebhookUrl) {
|
|
50
|
+
API.post({
|
|
51
|
+
url: URL.fromString(OpenSourceDeploymentWebhookUrl),
|
|
52
|
+
data: {
|
|
53
|
+
email: deployment.email?.toString() || "",
|
|
54
|
+
name: deployment.name?.toString() || "",
|
|
55
|
+
companyName: deployment.companyName?.toString() || "",
|
|
56
|
+
companyPhoneNumber:
|
|
57
|
+
deployment.companyPhoneNumber?.toString() || "",
|
|
58
|
+
oneuptimeVersion: deployment.oneuptimeVersion?.toString() || "",
|
|
59
|
+
instanceUrl: deployment.instanceUrl?.toString() || "",
|
|
60
|
+
},
|
|
61
|
+
}).catch((err: Error) => {
|
|
62
|
+
logger.error(err);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return Response.sendEmptySuccessResponse(req, res);
|
|
67
|
+
} catch (err) {
|
|
68
|
+
next(err);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -14,6 +14,7 @@ import Response from "../Utils/Response";
|
|
|
14
14
|
import BaseAPI from "./BaseAPI";
|
|
15
15
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
16
16
|
import ObjectID from "../../Types/ObjectID";
|
|
17
|
+
import PushDeviceType from "../../Types/PushNotification/PushDeviceType";
|
|
17
18
|
import UserPush from "../../Models/DatabaseModels/UserPush";
|
|
18
19
|
import PushNotificationMessage from "../../Types/PushNotification/PushNotificationMessage";
|
|
19
20
|
|
|
@@ -39,11 +40,17 @@ export default class UserPushAPI extends BaseAPI<
|
|
|
39
40
|
);
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
const validDeviceTypes: string[] = Object.values(PushDeviceType);
|
|
44
|
+
if (
|
|
45
|
+
!req.body.deviceType ||
|
|
46
|
+
!validDeviceTypes.includes(req.body.deviceType)
|
|
47
|
+
) {
|
|
43
48
|
return Response.sendErrorResponse(
|
|
44
49
|
req,
|
|
45
50
|
res,
|
|
46
|
-
new BadDataException(
|
|
51
|
+
new BadDataException(
|
|
52
|
+
"Device type must be one of: " + validDeviceTypes.join(", "),
|
|
53
|
+
),
|
|
47
54
|
);
|
|
48
55
|
}
|
|
49
56
|
|
|
@@ -86,7 +93,7 @@ export default class UserPushAPI extends BaseAPI<
|
|
|
86
93
|
userPush.deviceToken = req.body.deviceToken;
|
|
87
94
|
userPush.deviceType = req.body.deviceType;
|
|
88
95
|
userPush.deviceName = req.body.deviceName || "Unknown Device";
|
|
89
|
-
userPush.isVerified = true; //
|
|
96
|
+
userPush.isVerified = true; // Web, iOS, and Android devices are verified immediately
|
|
90
97
|
|
|
91
98
|
const savedDevice: UserPush = await this.service.create({
|
|
92
99
|
data: userPush,
|
|
@@ -105,6 +112,46 @@ export default class UserPushAPI extends BaseAPI<
|
|
|
105
112
|
},
|
|
106
113
|
);
|
|
107
114
|
|
|
115
|
+
this.router.post(
|
|
116
|
+
`/user-push/unregister`,
|
|
117
|
+
UserMiddleware.getUserMiddleware,
|
|
118
|
+
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
119
|
+
try {
|
|
120
|
+
req = req as OneUptimeRequest;
|
|
121
|
+
|
|
122
|
+
if (!req.body.deviceToken) {
|
|
123
|
+
return Response.sendErrorResponse(
|
|
124
|
+
req,
|
|
125
|
+
res,
|
|
126
|
+
new BadDataException("Device token is required"),
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const userId: ObjectID = (req as OneUptimeRequest).userAuthorization!
|
|
131
|
+
.userId!;
|
|
132
|
+
|
|
133
|
+
await this.service.deleteBy({
|
|
134
|
+
query: {
|
|
135
|
+
userId: userId,
|
|
136
|
+
deviceToken: req.body.deviceToken,
|
|
137
|
+
},
|
|
138
|
+
limit: 100,
|
|
139
|
+
skip: 0,
|
|
140
|
+
props: {
|
|
141
|
+
isRoot: true,
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
return Response.sendJsonObjectResponse(req, res, {
|
|
146
|
+
success: true,
|
|
147
|
+
message: "Device unregistered successfully",
|
|
148
|
+
});
|
|
149
|
+
} catch (error) {
|
|
150
|
+
return next(error);
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
);
|
|
154
|
+
|
|
108
155
|
this.router.post(
|
|
109
156
|
`/user-push/:deviceId/test-notification`,
|
|
110
157
|
UserMiddleware.getUserMiddleware,
|
|
@@ -186,7 +233,7 @@ export default class UserPushAPI extends BaseAPI<
|
|
|
186
233
|
},
|
|
187
234
|
],
|
|
188
235
|
message: testMessage,
|
|
189
|
-
deviceType: device.deviceType
|
|
236
|
+
deviceType: device.deviceType! as PushDeviceType,
|
|
190
237
|
},
|
|
191
238
|
{
|
|
192
239
|
isSensitive: false,
|
|
@@ -148,6 +148,9 @@ export const EncryptionSecret: ObjectID = new ObjectID(
|
|
|
148
148
|
process.env["ENCRYPTION_SECRET"] || "secret",
|
|
149
149
|
);
|
|
150
150
|
|
|
151
|
+
export const OpenSourceDeploymentWebhookUrl: string =
|
|
152
|
+
process.env["OPEN_SOURCE_DEPLOYMENT_WEBHOOK_URL"] || "";
|
|
153
|
+
|
|
151
154
|
export const AirtableApiKey: string = process.env["AIRTABLE_API_KEY"] || "";
|
|
152
155
|
|
|
153
156
|
export const AirtableBaseId: string = process.env["AIRTABLE_BASE_ID"] || "";
|
|
@@ -22,23 +22,23 @@ export class MigrationName1770237245070 implements MigrationInterface {
|
|
|
22
22
|
);
|
|
23
23
|
|
|
24
24
|
/*
|
|
25
|
-
* Backfill counters from
|
|
26
|
-
* Using
|
|
25
|
+
* Backfill counters from MAX number of each entity table (per project)
|
|
26
|
+
* Using MAX instead of COUNT to correctly handle deleted rows
|
|
27
27
|
*/
|
|
28
28
|
await queryRunner.query(
|
|
29
|
-
`UPDATE "Project" SET "incidentCounter" = sub.
|
|
29
|
+
`UPDATE "Project" SET "incidentCounter" = sub.max_num FROM (SELECT "projectId", COALESCE(MAX("incidentNumber"), 0) as max_num FROM "Incident" GROUP BY "projectId") sub WHERE "Project"."_id" = sub."projectId"`,
|
|
30
30
|
);
|
|
31
31
|
await queryRunner.query(
|
|
32
|
-
`UPDATE "Project" SET "alertCounter" = sub.
|
|
32
|
+
`UPDATE "Project" SET "alertCounter" = sub.max_num FROM (SELECT "projectId", COALESCE(MAX("alertNumber"), 0) as max_num FROM "Alert" GROUP BY "projectId") sub WHERE "Project"."_id" = sub."projectId"`,
|
|
33
33
|
);
|
|
34
34
|
await queryRunner.query(
|
|
35
|
-
`UPDATE "Project" SET "scheduledMaintenanceCounter" = sub.
|
|
35
|
+
`UPDATE "Project" SET "scheduledMaintenanceCounter" = sub.max_num FROM (SELECT "projectId", COALESCE(MAX("scheduledMaintenanceNumber"), 0) as max_num FROM "ScheduledMaintenance" GROUP BY "projectId") sub WHERE "Project"."_id" = sub."projectId"`,
|
|
36
36
|
);
|
|
37
37
|
await queryRunner.query(
|
|
38
|
-
`UPDATE "Project" SET "incidentEpisodeCounter" = sub.
|
|
38
|
+
`UPDATE "Project" SET "incidentEpisodeCounter" = sub.max_num FROM (SELECT "projectId", COALESCE(MAX("episodeNumber"), 0) as max_num FROM "IncidentEpisode" GROUP BY "projectId") sub WHERE "Project"."_id" = sub."projectId"`,
|
|
39
39
|
);
|
|
40
40
|
await queryRunner.query(
|
|
41
|
-
`UPDATE "Project" SET "alertEpisodeCounter" = sub.
|
|
41
|
+
`UPDATE "Project" SET "alertEpisodeCounter" = sub.max_num FROM (SELECT "projectId", COALESCE(MAX("episodeNumber"), 0) as max_num FROM "AlertEpisode" GROUP BY "projectId") sub WHERE "Project"."_id" = sub."projectId"`,
|
|
42
42
|
);
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
import CaptureSpan from "../../../Utils/Telemetry/CaptureSpan";
|
|
3
|
+
|
|
4
|
+
export class MigrationName1770668054908 implements MigrationInterface {
|
|
5
|
+
public name = "MigrationName1770668054908";
|
|
6
|
+
|
|
7
|
+
@CaptureSpan()
|
|
8
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
9
|
+
await queryRunner.query(
|
|
10
|
+
`ALTER TABLE "IncidentGroupingRule" ALTER COLUMN "groupByMonitor" SET DEFAULT false`,
|
|
11
|
+
);
|
|
12
|
+
await queryRunner.query(
|
|
13
|
+
`ALTER TABLE "AlertGroupingRule" ALTER COLUMN "groupByMonitor" SET DEFAULT false`,
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@CaptureSpan()
|
|
18
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
19
|
+
await queryRunner.query(
|
|
20
|
+
`ALTER TABLE "IncidentGroupingRule" ALTER COLUMN "groupByMonitor" SET DEFAULT true`,
|
|
21
|
+
);
|
|
22
|
+
await queryRunner.query(
|
|
23
|
+
`ALTER TABLE "AlertGroupingRule" ALTER COLUMN "groupByMonitor" SET DEFAULT true`,
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class MigrationName1770728946893 implements MigrationInterface {
|
|
4
|
+
public name = "MigrationName1770728946893";
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(
|
|
8
|
+
`ALTER TABLE "IncidentEpisode" ADD "allIncidentsResolvedAt" TIMESTAMP WITH TIME ZONE`,
|
|
9
|
+
);
|
|
10
|
+
await queryRunner.query(
|
|
11
|
+
`ALTER TABLE "AlertEpisode" ADD "allAlertsResolvedAt" TIMESTAMP WITH TIME ZONE`,
|
|
12
|
+
);
|
|
13
|
+
await queryRunner.query(
|
|
14
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
|
|
15
|
+
);
|
|
16
|
+
await queryRunner.query(
|
|
17
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
|
|
18
|
+
);
|
|
19
|
+
await queryRunner.query(
|
|
20
|
+
`CREATE INDEX "IDX_0610406e5c436c20a5068b1006" ON "IncidentEpisode" ("allIncidentsResolvedAt") `,
|
|
21
|
+
);
|
|
22
|
+
await queryRunner.query(
|
|
23
|
+
`CREATE INDEX "IDX_ea5d1f899fe52445dd6e0d0d55" ON "AlertEpisode" ("allAlertsResolvedAt") `,
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
28
|
+
await queryRunner.query(
|
|
29
|
+
`DROP INDEX "public"."IDX_ea5d1f899fe52445dd6e0d0d55"`,
|
|
30
|
+
);
|
|
31
|
+
await queryRunner.query(
|
|
32
|
+
`DROP INDEX "public"."IDX_0610406e5c436c20a5068b1006"`,
|
|
33
|
+
);
|
|
34
|
+
await queryRunner.query(
|
|
35
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
|
|
36
|
+
);
|
|
37
|
+
await queryRunner.query(
|
|
38
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
|
|
39
|
+
);
|
|
40
|
+
await queryRunner.query(
|
|
41
|
+
`ALTER TABLE "AlertEpisode" DROP COLUMN "allAlertsResolvedAt"`,
|
|
42
|
+
);
|
|
43
|
+
await queryRunner.query(
|
|
44
|
+
`ALTER TABLE "IncidentEpisode" DROP COLUMN "allIncidentsResolvedAt"`,
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class MigrationName1770732721195 implements MigrationInterface {
|
|
4
|
+
public name = "MigrationName1770732721195";
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(
|
|
8
|
+
`CREATE TABLE "OpenSourceDeployment" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "email" character varying(100) NOT NULL, "name" character varying(100) NOT NULL, "companyName" character varying(100), "companyPhoneNumber" character varying(30), "oneuptimeVersion" character varying(100) NOT NULL, "instanceUrl" character varying(100), CONSTRAINT "PK_cf6728c16db1c0c1b89f8ffc6dd" PRIMARY KEY ("_id"))`,
|
|
9
|
+
);
|
|
10
|
+
await queryRunner.query(
|
|
11
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
|
|
12
|
+
);
|
|
13
|
+
await queryRunner.query(
|
|
14
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
19
|
+
await queryRunner.query(
|
|
20
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
|
|
21
|
+
);
|
|
22
|
+
await queryRunner.query(
|
|
23
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
|
|
24
|
+
);
|
|
25
|
+
await queryRunner.query(`DROP TABLE "OpenSourceDeployment"`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -253,6 +253,9 @@ import { MigrationName1770232207959 } from "./1770232207959-MigrationName";
|
|
|
253
253
|
import { MigrationName1770237245069 } from "./1770237245069-MigrationName";
|
|
254
254
|
import { MigrationName1770237245070 } from "./1770237245070-MigrationName";
|
|
255
255
|
import { MigrationName1770407024682 } from "./1770407024682-MigrationName";
|
|
256
|
+
import { MigrationName1770668054908 } from "./1770668054908-MigrationName";
|
|
257
|
+
import { MigrationName1770728946893 } from "./1770728946893-MigrationName";
|
|
258
|
+
import { MigrationName1770732721195 } from "./1770732721195-MigrationName";
|
|
256
259
|
|
|
257
260
|
export default [
|
|
258
261
|
InitialMigration,
|
|
@@ -510,4 +513,7 @@ export default [
|
|
|
510
513
|
MigrationName1770237245069,
|
|
511
514
|
MigrationName1770237245070,
|
|
512
515
|
MigrationName1770407024682,
|
|
516
|
+
MigrationName1770668054908,
|
|
517
|
+
MigrationName1770728946893,
|
|
518
|
+
MigrationName1770732721195,
|
|
513
519
|
];
|
|
@@ -64,18 +64,23 @@ export default class UserMiddleware {
|
|
|
64
64
|
public static getAccessTokenFromExpressRequest(
|
|
65
65
|
req: ExpressRequest,
|
|
66
66
|
): string | undefined {
|
|
67
|
-
|
|
67
|
+
// 1. Try cookie (existing web dashboard flow)
|
|
68
|
+
const cookieToken: string | undefined =
|
|
69
|
+
CookieUtil.getCookieFromExpressRequest(req, CookieUtil.getUserTokenKey());
|
|
68
70
|
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
) {
|
|
72
|
-
accessToken = CookieUtil.getCookieFromExpressRequest(
|
|
73
|
-
req,
|
|
74
|
-
CookieUtil.getUserTokenKey(),
|
|
75
|
-
);
|
|
71
|
+
if (cookieToken) {
|
|
72
|
+
return cookieToken;
|
|
76
73
|
}
|
|
77
74
|
|
|
78
|
-
|
|
75
|
+
// 2. Fallback: Check Authorization: Bearer <token> header (mobile app flow)
|
|
76
|
+
const authHeader: string | undefined = req.headers["authorization"] as
|
|
77
|
+
| string
|
|
78
|
+
| undefined;
|
|
79
|
+
if (authHeader && authHeader.startsWith("Bearer ")) {
|
|
80
|
+
return authHeader.substring(7);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return undefined;
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
@CaptureSpan()
|