@oneuptime/common 7.0.3708 → 7.0.3716
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/Server/API/StatusPageAPI.ts +44 -1
- package/Server/API/UserOnCallLogTimelineAPI.ts +80 -1
- package/Server/Services/ScheduledMaintenanceService.ts +2 -1
- package/Server/Services/StatusPageSubscriberService.ts +160 -12
- package/Server/Services/UserNotificationRuleService.ts +2 -2
- package/Server/Views/AcknowledgeUserOnCallNotification.ejs +56 -0
- package/Server/Views/Message.ejs +51 -0
- package/Server/Views/Partials/Head.ejs +103 -0
- package/build/dist/Server/API/StatusPageAPI.js +19 -0
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/UserOnCallLogTimelineAPI.js +53 -3
- package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberService.js +116 -7
- package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js +2 -2
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/package.json +2 -2
|
@@ -1942,6 +1942,8 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
1942
1942
|
req.params["statusPageId"] as string,
|
|
1943
1943
|
);
|
|
1944
1944
|
|
|
1945
|
+
logger.debug(`Subscribing to status page with ID: ${objectId}`);
|
|
1946
|
+
|
|
1945
1947
|
if (
|
|
1946
1948
|
!(await this.service.hasReadAccess(
|
|
1947
1949
|
objectId,
|
|
@@ -1949,6 +1951,7 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
1949
1951
|
req,
|
|
1950
1952
|
))
|
|
1951
1953
|
) {
|
|
1954
|
+
logger.debug(`No read access to status page with ID: ${objectId}`);
|
|
1952
1955
|
throw new NotAuthenticatedException(
|
|
1953
1956
|
"You are not authenticated to access this status page",
|
|
1954
1957
|
);
|
|
@@ -1972,19 +1975,28 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
1972
1975
|
});
|
|
1973
1976
|
|
|
1974
1977
|
if (!statusPage) {
|
|
1978
|
+
logger.debug(`Status page not found with ID: ${objectId}`);
|
|
1975
1979
|
throw new BadDataException("Status Page not found");
|
|
1976
1980
|
}
|
|
1977
1981
|
|
|
1982
|
+
logger.debug(`Status page found: ${JSON.stringify(statusPage)}`);
|
|
1983
|
+
|
|
1978
1984
|
if (
|
|
1979
1985
|
req.body.data["subscriberEmail"] &&
|
|
1980
1986
|
!statusPage.enableEmailSubscribers
|
|
1981
1987
|
) {
|
|
1988
|
+
logger.debug(
|
|
1989
|
+
`Email subscribers not enabled for status page with ID: ${objectId}`,
|
|
1990
|
+
);
|
|
1982
1991
|
throw new BadDataException(
|
|
1983
1992
|
"Email subscribers not enabled for this status page.",
|
|
1984
1993
|
);
|
|
1985
1994
|
}
|
|
1986
1995
|
|
|
1987
1996
|
if (req.body.data["subscriberPhone"] && !statusPage.enableSmsSubscribers) {
|
|
1997
|
+
logger.debug(
|
|
1998
|
+
`SMS subscribers not enabled for status page with ID: ${objectId}`,
|
|
1999
|
+
);
|
|
1988
2000
|
throw new BadDataException(
|
|
1989
2001
|
"SMS subscribers not enabled for this status page.",
|
|
1990
2002
|
);
|
|
@@ -1996,6 +2008,9 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
1996
2008
|
!req.body.data["subscriberEmail"] &&
|
|
1997
2009
|
!req.body.data["subscriberPhone"]
|
|
1998
2010
|
) {
|
|
2011
|
+
logger.debug(
|
|
2012
|
+
`No email or phone provided for subscription to status page with ID: ${objectId}`,
|
|
2013
|
+
);
|
|
1999
2014
|
throw new BadDataException(
|
|
2000
2015
|
"Email or phone is required to subscribe to this status page.",
|
|
2001
2016
|
);
|
|
@@ -2014,12 +2029,18 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
2014
2029
|
let isUpdate: boolean = false;
|
|
2015
2030
|
|
|
2016
2031
|
if (!req.params["subscriberId"]) {
|
|
2032
|
+
logger.debug(
|
|
2033
|
+
`Creating new subscriber for status page with ID: ${objectId}`,
|
|
2034
|
+
);
|
|
2017
2035
|
statusPageSubscriber = new StatusPageSubscriber();
|
|
2018
2036
|
} else {
|
|
2019
2037
|
const subscriberId: ObjectID = new ObjectID(
|
|
2020
2038
|
req.params["subscriberId"] as string,
|
|
2021
2039
|
);
|
|
2022
2040
|
|
|
2041
|
+
logger.debug(
|
|
2042
|
+
`Updating existing subscriber with ID: ${subscriberId} for status page with ID: ${objectId}`,
|
|
2043
|
+
);
|
|
2023
2044
|
statusPageSubscriber = await StatusPageSubscriberService.findOneBy({
|
|
2024
2045
|
query: {
|
|
2025
2046
|
_id: subscriberId.toString(),
|
|
@@ -2030,6 +2051,7 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
2030
2051
|
});
|
|
2031
2052
|
|
|
2032
2053
|
if (!statusPageSubscriber) {
|
|
2054
|
+
logger.debug(`Subscriber not found with ID: ${subscriberId}`);
|
|
2033
2055
|
throw new BadDataException("Subscriber not found");
|
|
2034
2056
|
}
|
|
2035
2057
|
|
|
@@ -2037,10 +2059,12 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
2037
2059
|
}
|
|
2038
2060
|
|
|
2039
2061
|
if (email) {
|
|
2062
|
+
logger.debug(`Setting subscriber email: ${email}`);
|
|
2040
2063
|
statusPageSubscriber.subscriberEmail = email;
|
|
2041
2064
|
}
|
|
2042
2065
|
|
|
2043
2066
|
if (phone) {
|
|
2067
|
+
logger.debug(`Setting subscriber phone: ${phone}`);
|
|
2044
2068
|
statusPageSubscriber.subscriberPhone = phone;
|
|
2045
2069
|
}
|
|
2046
2070
|
|
|
@@ -2048,6 +2072,9 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
2048
2072
|
req.body.data["statusPageResources"] &&
|
|
2049
2073
|
!statusPage.allowSubscribersToChooseResources
|
|
2050
2074
|
) {
|
|
2075
|
+
logger.debug(
|
|
2076
|
+
`Subscribers not allowed to choose resources for status page with ID: ${objectId}`,
|
|
2077
|
+
);
|
|
2051
2078
|
throw new BadDataException(
|
|
2052
2079
|
"Subscribers are not allowed to choose resources for this status page.",
|
|
2053
2080
|
);
|
|
@@ -2057,6 +2084,9 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
2057
2084
|
req.body.data["statusPageEventTypes"] &&
|
|
2058
2085
|
!statusPage.allowSubscribersToChooseEventTypes
|
|
2059
2086
|
) {
|
|
2087
|
+
logger.debug(
|
|
2088
|
+
`Subscribers not allowed to choose event types for status page with ID: ${objectId}`,
|
|
2089
|
+
);
|
|
2060
2090
|
throw new BadDataException(
|
|
2061
2091
|
"Subscribers are not allowed to choose event types for this status page.",
|
|
2062
2092
|
);
|
|
@@ -2077,6 +2107,9 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
2077
2107
|
req.body.data["statusPageResources"] &&
|
|
2078
2108
|
req.body.data["statusPageResources"].length > 0
|
|
2079
2109
|
) {
|
|
2110
|
+
logger.debug(
|
|
2111
|
+
`Setting subscriber resources: ${JSON.stringify(req.body.data["statusPageResources"])}`,
|
|
2112
|
+
);
|
|
2080
2113
|
statusPageSubscriber.statusPageResources = req.body.data[
|
|
2081
2114
|
"statusPageResources"
|
|
2082
2115
|
] as Array<StatusPageResource>;
|
|
@@ -2086,6 +2119,9 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
2086
2119
|
req.body.data["statusPageEventTypes"] &&
|
|
2087
2120
|
req.body.data["statusPageEventTypes"].length > 0
|
|
2088
2121
|
) {
|
|
2122
|
+
logger.debug(
|
|
2123
|
+
`Setting subscriber event types: ${JSON.stringify(req.body.data["statusPageEventTypes"])}`,
|
|
2124
|
+
);
|
|
2089
2125
|
statusPageSubscriber.statusPageEventTypes = req.body.data[
|
|
2090
2126
|
"statusPageEventTypes"
|
|
2091
2127
|
] as Array<StatusPageEventType>;
|
|
@@ -2093,7 +2129,7 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
2093
2129
|
|
|
2094
2130
|
if (isUpdate) {
|
|
2095
2131
|
// check isUnsubscribed is set to false.
|
|
2096
|
-
|
|
2132
|
+
logger.debug(`Updating subscriber with ID: ${statusPageSubscriber.id}`);
|
|
2097
2133
|
statusPageSubscriber.isUnsubscribed = Boolean(
|
|
2098
2134
|
req.body.data["isUnsubscribed"],
|
|
2099
2135
|
);
|
|
@@ -2111,6 +2147,9 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
2111
2147
|
},
|
|
2112
2148
|
});
|
|
2113
2149
|
} else {
|
|
2150
|
+
logger.debug(
|
|
2151
|
+
`Creating new subscriber: ${JSON.stringify(statusPageSubscriber)}`,
|
|
2152
|
+
);
|
|
2114
2153
|
await StatusPageSubscriberService.create({
|
|
2115
2154
|
data: statusPageSubscriber,
|
|
2116
2155
|
props: {
|
|
@@ -2118,6 +2157,10 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
2118
2157
|
},
|
|
2119
2158
|
});
|
|
2120
2159
|
}
|
|
2160
|
+
|
|
2161
|
+
logger.debug(
|
|
2162
|
+
`Subscription process completed for status page with ID: ${objectId}`,
|
|
2163
|
+
);
|
|
2121
2164
|
}
|
|
2122
2165
|
|
|
2123
2166
|
public async getSubscriber(
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "../Utils/Express";
|
|
11
11
|
import Response from "../Utils/Response";
|
|
12
12
|
import BaseAPI from "./BaseAPI";
|
|
13
|
-
import { DashboardRoute } from "Common/ServiceRoute";
|
|
13
|
+
import { AppApiRoute, DashboardRoute } from "Common/ServiceRoute";
|
|
14
14
|
import Hostname from "Common/Types/API/Hostname";
|
|
15
15
|
import Protocol from "Common/Types/API/Protocol";
|
|
16
16
|
import URL from "Common/Types/API/URL";
|
|
@@ -20,6 +20,7 @@ import { JSONObject } from "Common/Types/JSON";
|
|
|
20
20
|
import ObjectID from "Common/Types/ObjectID";
|
|
21
21
|
import UserNotificationStatus from "Common/Types/UserNotification/UserNotificationStatus";
|
|
22
22
|
import UserOnCallLogTimeline from "Common/Models/DatabaseModels/UserOnCallLogTimeline";
|
|
23
|
+
import Route from "../../Types/API/Route";
|
|
23
24
|
|
|
24
25
|
export default class UserNotificationLogTimelineAPI extends BaseAPI<
|
|
25
26
|
UserOnCallLogTimeline,
|
|
@@ -92,6 +93,84 @@ export default class UserNotificationLogTimelineAPI extends BaseAPI<
|
|
|
92
93
|
},
|
|
93
94
|
);
|
|
94
95
|
|
|
96
|
+
// We have this ack page to show the user a confirmation page before acknowledging the notification.
|
|
97
|
+
// this is because email clients automatically make a get request to the url in the email and ack the notification automatically which is not what we want.
|
|
98
|
+
// so we need to create this page for the user to confirm that they want to acknowledge the notification.
|
|
99
|
+
this.router.get(
|
|
100
|
+
`${new this.entityType()
|
|
101
|
+
.getCrudApiPath()
|
|
102
|
+
?.toString()}/acknowledge-page/:itemId`,
|
|
103
|
+
async (req: ExpressRequest, res: ExpressResponse) => {
|
|
104
|
+
req = req as OneUptimeRequest;
|
|
105
|
+
|
|
106
|
+
if (!req.params["itemId"]) {
|
|
107
|
+
return Response.sendErrorResponse(
|
|
108
|
+
req,
|
|
109
|
+
res,
|
|
110
|
+
new BadDataException("Item ID is required"),
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const itemId: ObjectID = new ObjectID(req.params["itemId"]);
|
|
115
|
+
|
|
116
|
+
const timelineItem: UserOnCallLogTimeline | null =
|
|
117
|
+
await this.service.findOneById({
|
|
118
|
+
id: itemId,
|
|
119
|
+
select: {
|
|
120
|
+
_id: true,
|
|
121
|
+
projectId: true,
|
|
122
|
+
triggeredByIncidentId: true,
|
|
123
|
+
triggeredByIncident: {
|
|
124
|
+
title: true,
|
|
125
|
+
description: true,
|
|
126
|
+
},
|
|
127
|
+
triggeredByAlertId: true,
|
|
128
|
+
triggeredByAlert: {
|
|
129
|
+
title: true,
|
|
130
|
+
description: true,
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
props: {
|
|
134
|
+
isRoot: true,
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (!timelineItem) {
|
|
139
|
+
return Response.sendErrorResponse(
|
|
140
|
+
req,
|
|
141
|
+
res,
|
|
142
|
+
new BadDataException("Invalid item Id"),
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const notificationType: string = timelineItem.triggeredByIncidentId
|
|
147
|
+
? "Incident"
|
|
148
|
+
: "Alert";
|
|
149
|
+
|
|
150
|
+
const host: Hostname = await DatabaseConfig.getHost();
|
|
151
|
+
const httpProtocol: Protocol = await DatabaseConfig.getHttpProtocol();
|
|
152
|
+
|
|
153
|
+
return Response.render(
|
|
154
|
+
req,
|
|
155
|
+
res,
|
|
156
|
+
"/usr/src/Common/Server/Views/AcknowledgeUserOnCallNotification.ejs",
|
|
157
|
+
{
|
|
158
|
+
title: `Acknowledge ${notificationType} - ${timelineItem.triggeredByIncident?.title || timelineItem.triggeredByAlert?.title}`,
|
|
159
|
+
message: `Do you want to acknowledge this ${notificationType}?`,
|
|
160
|
+
acknowledgeText: `Acknowledge ${notificationType}`,
|
|
161
|
+
acknowledgeUrl: new URL(
|
|
162
|
+
httpProtocol,
|
|
163
|
+
host,
|
|
164
|
+
new Route(AppApiRoute.toString())
|
|
165
|
+
.addRoute(new UserOnCallLogTimeline().crudApiPath!)
|
|
166
|
+
.addRoute("/acknowledge/" + itemId.toString()),
|
|
167
|
+
).toString(),
|
|
168
|
+
},
|
|
169
|
+
);
|
|
170
|
+
},
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
// This is the link that actually acknowledges the notification.
|
|
95
174
|
this.router.get(
|
|
96
175
|
`${new this.entityType()
|
|
97
176
|
.getCrudApiPath()
|
|
@@ -276,7 +276,8 @@ export class Service extends DatabaseService<Model> {
|
|
|
276
276
|
),
|
|
277
277
|
unsubscribeUrl: unsubscribeUrl,
|
|
278
278
|
},
|
|
279
|
-
subject:
|
|
279
|
+
subject:
|
|
280
|
+
"[Scheduled Maintenance] " + (event.title || statusPageName),
|
|
280
281
|
},
|
|
281
282
|
{
|
|
282
283
|
mailServer: ProjectSmtpConfigService.toEmailServer(
|