@oneuptime/common 7.0.3617 → 7.0.3652
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/Alert.ts +29 -0
- package/Models/DatabaseModels/Index.ts +10 -0
- package/Models/DatabaseModels/ScheduledMaintenance.ts +29 -0
- package/Models/DatabaseModels/WorkspaceNotificationRule.ts +461 -0
- package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +379 -0
- package/Models/DatabaseModels/WorkspaceSetting.ts +230 -0
- package/Models/DatabaseModels/WorkspaceUserAuthToken.ts +312 -0
- package/Server/API/SlackAPI.ts +368 -0
- package/Server/EnvironmentConfig.ts +23 -2
- package/Server/Infrastructure/Postgres/SchemaMigrations/1739209832500-MigrationName.ts +147 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1739210586538-MigrationName.ts +19 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1739217257089-MigrationName.ts +23 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Middleware/SlackAuthorization.ts +60 -0
- package/Server/Services/AlertService.ts +38 -2
- package/Server/Services/Index.ts +9 -0
- package/Server/Services/ProjectService.ts +177 -16
- package/Server/Services/ScheduledMaintenanceService.ts +39 -2
- package/Server/Services/UserService.ts +4 -4
- package/Server/Services/WorkspaceCommunicationTools/Slack.ts +0 -0
- package/Server/Services/WorkspaceCommunicationTools/Teams.ts +0 -0
- package/Server/Services/WorkspaceCommunicationTools/WorkspaceCommunicationBaseService.ts +0 -0
- package/Server/Services/WorkspaceNotificationRuleService.ts +22 -0
- package/Server/Services/WorkspaceProjectAuthTokenService.ts +84 -0
- package/Server/Services/WorkspaceSettingService.ts +78 -0
- package/Server/Services/WorkspaceUserAuthTokenService.ts +89 -0
- package/Server/Types/Workflow/Components/Slack/SendMessageToChannel.ts +1 -1
- package/Server/Utils/Express.ts +2 -1
- package/Server/Utils/Monitor/MonitorResource.ts +2 -5
- package/Server/Utils/{Slack.ts → Slack/Slack.ts} +40 -0
- package/Server/Utils/Slack/app-manifest-temp.json +198 -0
- package/Server/Utils/Slack/app-manifest.json +67 -0
- package/Server/Utils/StartServer.ts +2 -1
- package/Types/Filter/FilterCondition.ts +2 -2
- package/Types/Monitor/CriteriaFilter.ts +31 -5
- package/Types/Monitor/MonitorCriteriaInstance.ts +40 -10
- package/Types/Monitor/MonitorStep.ts +1 -1
- package/Types/Permission.ts +34 -0
- package/Types/Workspace/NotificationRules/BaseNotificationRule.ts +3 -0
- package/Types/Workspace/NotificationRules/EventType.ts +8 -0
- package/Types/Workspace/NotificationRules/NotificationRuleCondition.ts +355 -0
- package/Types/Workspace/NotificationRules/SlackNotificationRule.ts +19 -0
- package/Types/Workspace/WorkspaceNotificationPayload.ts +3 -0
- package/Types/Workspace/WorkspaceType.ts +6 -0
- package/UI/Components/Forms/BasicForm.tsx +9 -0
- package/UI/Components/Forms/Fields/FormField.tsx +36 -1
- package/UI/Components/Forms/Types/Field.ts +2 -0
- package/UI/Components/Forms/Types/FormFieldSchemaType.ts +1 -1
- package/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.ts +2 -2
- package/UI/Components/Icon/Icon.tsx +18 -5
- package/UI/Components/Radio/Radio.tsx +12 -10
- package/UI/Config.ts +3 -0
- package/build/dist/Models/DatabaseModels/Alert.js +31 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +8 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +31 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkspaceNotificationRule.js +481 -0
- package/build/dist/Models/DatabaseModels/WorkspaceNotificationRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js +390 -0
- package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -0
- package/build/dist/Models/DatabaseModels/WorkspaceSetting.js +236 -0
- package/build/dist/Models/DatabaseModels/WorkspaceSetting.js.map +1 -0
- package/build/dist/Models/DatabaseModels/WorkspaceUserAuthToken.js +326 -0
- package/build/dist/Models/DatabaseModels/WorkspaceUserAuthToken.js.map +1 -0
- package/build/dist/Server/API/SlackAPI.js +237 -0
- package/build/dist/Server/API/SlackAPI.js.map +1 -0
- package/build/dist/Server/EnvironmentConfig.js +11 -2
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1739209832500-MigrationName.js +58 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1739209832500-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1739210586538-MigrationName.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1739210586538-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1739217257089-MigrationName.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1739217257089-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/SlackAuthorization.js +28 -0
- package/build/dist/Server/Middleware/SlackAuthorization.js.map +1 -0
- package/build/dist/Server/Services/AlertService.js +31 -5
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +8 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +144 -15
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +30 -3
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +4 -4
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceCommunicationTools/Slack.js +2 -0
- package/build/dist/Server/Services/WorkspaceCommunicationTools/Slack.js.map +1 -0
- package/build/dist/Server/Services/WorkspaceCommunicationTools/Teams.js +2 -0
- package/build/dist/Server/Services/WorkspaceCommunicationTools/Teams.js.map +1 -0
- package/build/dist/Server/Services/WorkspaceCommunicationTools/WorkspaceCommunicationBaseService.js +2 -0
- package/build/dist/Server/Services/WorkspaceCommunicationTools/WorkspaceCommunicationBaseService.js.map +1 -0
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +14 -0
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -0
- package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js +63 -0
- package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js.map +1 -0
- package/build/dist/Server/Services/WorkspaceSettingService.js +59 -0
- package/build/dist/Server/Services/WorkspaceSettingService.js.map +1 -0
- package/build/dist/Server/Services/WorkspaceUserAuthTokenService.js +66 -0
- package/build/dist/Server/Services/WorkspaceUserAuthTokenService.js.map +1 -0
- package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Utils/Express.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +2 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Slack/Slack.js +49 -0
- package/build/dist/Server/Utils/Slack/Slack.js.map +1 -0
- package/build/dist/Server/Utils/Slack/app-manifest.json +67 -0
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Types/Filter/FilterCondition.js +2 -2
- package/build/dist/Types/Filter/FilterCondition.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +19 -5
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +33 -10
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Permission.js +32 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Workspace/NotificationRules/BaseNotificationRule.js +2 -0
- package/build/dist/Types/Workspace/NotificationRules/BaseNotificationRule.js.map +1 -0
- package/build/dist/Types/Workspace/NotificationRules/EventType.js +9 -0
- package/build/dist/Types/Workspace/NotificationRules/EventType.js.map +1 -0
- package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js +275 -0
- package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js.map +1 -0
- package/build/dist/Types/Workspace/NotificationRules/SlackNotificationRule.js +2 -0
- package/build/dist/Types/Workspace/NotificationRules/SlackNotificationRule.js.map +1 -0
- package/build/dist/Types/Workspace/WorkspaceNotificationPayload.js +2 -0
- package/build/dist/Types/Workspace/WorkspaceNotificationPayload.js.map +1 -0
- package/build/dist/Types/Workspace/WorkspaceType.js +7 -0
- package/build/dist/Types/Workspace/WorkspaceType.js.map +1 -0
- package/build/dist/UI/Components/Forms/BasicForm.js +7 -0
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +21 -4
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js +1 -1
- package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js.map +1 -1
- package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js +2 -2
- package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +5 -1
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/Radio/Radio.js +4 -4
- package/build/dist/UI/Components/Radio/Radio.js.map +1 -1
- package/build/dist/UI/Config.js +1 -0
- package/build/dist/UI/Config.js.map +1 -1
- package/package.json +2 -2
- package/build/dist/Server/Utils/Slack.js +0 -20
- package/build/dist/Server/Utils/Slack.js.map +0 -1
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
AccountsRoute,
|
|
3
3
|
AdminDashboardRoute,
|
|
4
4
|
DashboardRoute,
|
|
5
|
+
AppApiRoute,
|
|
5
6
|
} from "Common/ServiceRoute";
|
|
6
7
|
import BillingConfig from "./BillingConfig";
|
|
7
8
|
import Hostname from "Common/Types/API/Hostname";
|
|
@@ -279,8 +280,19 @@ export const AllowedSubscribersCountInFreePlan: number = process.env[
|
|
|
279
280
|
? parseInt(process.env["ALLOWED_SUBSCRIBERS_COUNT_IN_FREE_PLAN"].toString())
|
|
280
281
|
: 100;
|
|
281
282
|
|
|
282
|
-
export const
|
|
283
|
-
process.env["
|
|
283
|
+
export const NotificationSlackWebhookOnCreateUser: string =
|
|
284
|
+
process.env["NOTIFICATION_SLACK_WEBHOOK_ON_CREATED_USER"] || "";
|
|
285
|
+
|
|
286
|
+
export const NotificationSlackWebhookOnCreateProject: string =
|
|
287
|
+
process.env["NOTIFICATION_SLACK_WEBHOOK_ON_CREATED_PROJECT"] || "";
|
|
288
|
+
|
|
289
|
+
// notification delete project
|
|
290
|
+
export const NotificationSlackWebhookOnDeleteProject: string =
|
|
291
|
+
process.env["NOTIFICATION_SLACK_WEBHOOK_ON_DELETED_PROJECT"] || "";
|
|
292
|
+
|
|
293
|
+
// notification subscripton update.
|
|
294
|
+
export const NotificationSlackWebhookOnSubscriptionUpdate: string =
|
|
295
|
+
process.env["NOTIFICATION_SLACK_WEBHOOK_ON_SUBSCRIPTION_UPDATE"] || "";
|
|
284
296
|
|
|
285
297
|
export const AdminDashboardClientURL: URL = new URL(
|
|
286
298
|
HttpProtocol,
|
|
@@ -288,6 +300,8 @@ export const AdminDashboardClientURL: URL = new URL(
|
|
|
288
300
|
AdminDashboardRoute,
|
|
289
301
|
);
|
|
290
302
|
|
|
303
|
+
export const AppApiClientUrl: URL = new URL(HttpProtocol, Host, AppApiRoute);
|
|
304
|
+
|
|
291
305
|
export const DashboardClientUrl: URL = new URL(
|
|
292
306
|
HttpProtocol,
|
|
293
307
|
Host,
|
|
@@ -302,3 +316,10 @@ export const AccountsClientUrl: URL = new URL(
|
|
|
302
316
|
|
|
303
317
|
export const DisableTelemetry: boolean =
|
|
304
318
|
process.env["DISABLE_TELEMETRY"] === "true";
|
|
319
|
+
|
|
320
|
+
export const SlackAppClientId: string | null =
|
|
321
|
+
process.env["SLACK_APP_CLIENT_ID"] || null;
|
|
322
|
+
export const SlackAppClientSecret: string | null =
|
|
323
|
+
process.env["SLACK_APP_CLIENT_SECRET"] || null;
|
|
324
|
+
export const SlackAppSigningSecret: string | null =
|
|
325
|
+
process.env["SLACK_APP_SIGNING_SECRET"] || null;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class MigrationName1739209832500 implements MigrationInterface {
|
|
4
|
+
public name = "MigrationName1739209832500";
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(
|
|
8
|
+
`CREATE TABLE "WorkspaceUserAuthToken" ("_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, "projectId" uuid NOT NULL, "authToken" text NOT NULL, "workspaceUserId" character varying(500) NOT NULL, "workspaceType" character varying(500) NOT NULL, "miscData" jsonb NOT NULL, "userId" uuid, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_ae2f1b46b7e26f58a1f4a56b6ea" PRIMARY KEY ("_id"))`,
|
|
9
|
+
);
|
|
10
|
+
await queryRunner.query(
|
|
11
|
+
`CREATE INDEX "IDX_bee888f5782b9585e01f13455f" ON "WorkspaceUserAuthToken" ("projectId") `,
|
|
12
|
+
);
|
|
13
|
+
await queryRunner.query(
|
|
14
|
+
`CREATE INDEX "IDX_4b7c7d1a8b2259df8c790db094" ON "WorkspaceUserAuthToken" ("userId") `,
|
|
15
|
+
);
|
|
16
|
+
await queryRunner.query(
|
|
17
|
+
`CREATE TABLE "WorkspaceProjectAuthToken" ("_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, "projectId" uuid NOT NULL, "authToken" text NOT NULL, "workspaceType" character varying(500) NOT NULL, "workspaceProjectId" character varying(500) NOT NULL, "miscData" jsonb NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_c0caa6a69da614ee74d8c1291da" PRIMARY KEY ("_id"))`,
|
|
18
|
+
);
|
|
19
|
+
await queryRunner.query(
|
|
20
|
+
`CREATE INDEX "IDX_73f5887268b09c0abccf04ef02" ON "WorkspaceProjectAuthToken" ("projectId") `,
|
|
21
|
+
);
|
|
22
|
+
await queryRunner.query(
|
|
23
|
+
`CREATE TABLE "WorkspaceSetting" ("_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, "projectId" uuid NOT NULL, "settings" jsonb NOT NULL, "workspaceType" character varying(500) NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_eb98d42edd6489fbe1cf3f34515" PRIMARY KEY ("_id"))`,
|
|
24
|
+
);
|
|
25
|
+
await queryRunner.query(
|
|
26
|
+
`CREATE INDEX "IDX_c68f38e2b2b061c40209e85bf2" ON "WorkspaceSetting" ("projectId") `,
|
|
27
|
+
);
|
|
28
|
+
await queryRunner.query(
|
|
29
|
+
`CREATE TABLE "WorkspaceNotificationRule" ("_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, "projectId" uuid NOT NULL, "name" character varying(500) NOT NULL, "description" character varying(500), "notificationRule" jsonb NOT NULL, "eventType" character varying NOT NULL, "workspaceType" character varying(500) NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_d1485681c7695ac9841dc52a451" PRIMARY KEY ("_id"))`,
|
|
30
|
+
);
|
|
31
|
+
await queryRunner.query(
|
|
32
|
+
`CREATE INDEX "IDX_349b022afa9a50a597d6c91ec9" ON "WorkspaceNotificationRule" ("projectId") `,
|
|
33
|
+
);
|
|
34
|
+
await queryRunner.query(
|
|
35
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
|
|
36
|
+
);
|
|
37
|
+
await queryRunner.query(
|
|
38
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
|
|
39
|
+
);
|
|
40
|
+
await queryRunner.query(
|
|
41
|
+
`ALTER TABLE "WorkspaceUserAuthToken" ADD CONSTRAINT "FK_bee888f5782b9585e01f13455fb" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
42
|
+
);
|
|
43
|
+
await queryRunner.query(
|
|
44
|
+
`ALTER TABLE "WorkspaceUserAuthToken" ADD CONSTRAINT "FK_4b7c7d1a8b2259df8c790db0940" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
45
|
+
);
|
|
46
|
+
await queryRunner.query(
|
|
47
|
+
`ALTER TABLE "WorkspaceUserAuthToken" ADD CONSTRAINT "FK_ec5cbf4536681fe4bea883c98ea" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
48
|
+
);
|
|
49
|
+
await queryRunner.query(
|
|
50
|
+
`ALTER TABLE "WorkspaceUserAuthToken" ADD CONSTRAINT "FK_1b2cb71eaf9e665e4556d1b1263" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
51
|
+
);
|
|
52
|
+
await queryRunner.query(
|
|
53
|
+
`ALTER TABLE "WorkspaceProjectAuthToken" ADD CONSTRAINT "FK_73f5887268b09c0abccf04ef02e" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
54
|
+
);
|
|
55
|
+
await queryRunner.query(
|
|
56
|
+
`ALTER TABLE "WorkspaceProjectAuthToken" ADD CONSTRAINT "FK_8aa5804c7a728039564bf5d967d" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
57
|
+
);
|
|
58
|
+
await queryRunner.query(
|
|
59
|
+
`ALTER TABLE "WorkspaceProjectAuthToken" ADD CONSTRAINT "FK_6287095997a16f1cbdd4fb24b61" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
60
|
+
);
|
|
61
|
+
await queryRunner.query(
|
|
62
|
+
`ALTER TABLE "WorkspaceSetting" ADD CONSTRAINT "FK_c68f38e2b2b061c40209e85bf22" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
63
|
+
);
|
|
64
|
+
await queryRunner.query(
|
|
65
|
+
`ALTER TABLE "WorkspaceSetting" ADD CONSTRAINT "FK_c8fdd61b95bfd0a2ca268b8c602" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
66
|
+
);
|
|
67
|
+
await queryRunner.query(
|
|
68
|
+
`ALTER TABLE "WorkspaceSetting" ADD CONSTRAINT "FK_cb3b7931417a4b4ee05d487b614" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
69
|
+
);
|
|
70
|
+
await queryRunner.query(
|
|
71
|
+
`ALTER TABLE "WorkspaceNotificationRule" ADD CONSTRAINT "FK_349b022afa9a50a597d6c91ec95" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
72
|
+
);
|
|
73
|
+
await queryRunner.query(
|
|
74
|
+
`ALTER TABLE "WorkspaceNotificationRule" ADD CONSTRAINT "FK_55f4e43427fc217ed32cf640a28" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
75
|
+
);
|
|
76
|
+
await queryRunner.query(
|
|
77
|
+
`ALTER TABLE "WorkspaceNotificationRule" ADD CONSTRAINT "FK_65ac673d16286be2dcd5229fe24" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
82
|
+
await queryRunner.query(
|
|
83
|
+
`ALTER TABLE "WorkspaceNotificationRule" DROP CONSTRAINT "FK_65ac673d16286be2dcd5229fe24"`,
|
|
84
|
+
);
|
|
85
|
+
await queryRunner.query(
|
|
86
|
+
`ALTER TABLE "WorkspaceNotificationRule" DROP CONSTRAINT "FK_55f4e43427fc217ed32cf640a28"`,
|
|
87
|
+
);
|
|
88
|
+
await queryRunner.query(
|
|
89
|
+
`ALTER TABLE "WorkspaceNotificationRule" DROP CONSTRAINT "FK_349b022afa9a50a597d6c91ec95"`,
|
|
90
|
+
);
|
|
91
|
+
await queryRunner.query(
|
|
92
|
+
`ALTER TABLE "WorkspaceSetting" DROP CONSTRAINT "FK_cb3b7931417a4b4ee05d487b614"`,
|
|
93
|
+
);
|
|
94
|
+
await queryRunner.query(
|
|
95
|
+
`ALTER TABLE "WorkspaceSetting" DROP CONSTRAINT "FK_c8fdd61b95bfd0a2ca268b8c602"`,
|
|
96
|
+
);
|
|
97
|
+
await queryRunner.query(
|
|
98
|
+
`ALTER TABLE "WorkspaceSetting" DROP CONSTRAINT "FK_c68f38e2b2b061c40209e85bf22"`,
|
|
99
|
+
);
|
|
100
|
+
await queryRunner.query(
|
|
101
|
+
`ALTER TABLE "WorkspaceProjectAuthToken" DROP CONSTRAINT "FK_6287095997a16f1cbdd4fb24b61"`,
|
|
102
|
+
);
|
|
103
|
+
await queryRunner.query(
|
|
104
|
+
`ALTER TABLE "WorkspaceProjectAuthToken" DROP CONSTRAINT "FK_8aa5804c7a728039564bf5d967d"`,
|
|
105
|
+
);
|
|
106
|
+
await queryRunner.query(
|
|
107
|
+
`ALTER TABLE "WorkspaceProjectAuthToken" DROP CONSTRAINT "FK_73f5887268b09c0abccf04ef02e"`,
|
|
108
|
+
);
|
|
109
|
+
await queryRunner.query(
|
|
110
|
+
`ALTER TABLE "WorkspaceUserAuthToken" DROP CONSTRAINT "FK_1b2cb71eaf9e665e4556d1b1263"`,
|
|
111
|
+
);
|
|
112
|
+
await queryRunner.query(
|
|
113
|
+
`ALTER TABLE "WorkspaceUserAuthToken" DROP CONSTRAINT "FK_ec5cbf4536681fe4bea883c98ea"`,
|
|
114
|
+
);
|
|
115
|
+
await queryRunner.query(
|
|
116
|
+
`ALTER TABLE "WorkspaceUserAuthToken" DROP CONSTRAINT "FK_4b7c7d1a8b2259df8c790db0940"`,
|
|
117
|
+
);
|
|
118
|
+
await queryRunner.query(
|
|
119
|
+
`ALTER TABLE "WorkspaceUserAuthToken" DROP CONSTRAINT "FK_bee888f5782b9585e01f13455fb"`,
|
|
120
|
+
);
|
|
121
|
+
await queryRunner.query(
|
|
122
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
|
|
123
|
+
);
|
|
124
|
+
await queryRunner.query(
|
|
125
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
|
|
126
|
+
);
|
|
127
|
+
await queryRunner.query(
|
|
128
|
+
`DROP INDEX "public"."IDX_349b022afa9a50a597d6c91ec9"`,
|
|
129
|
+
);
|
|
130
|
+
await queryRunner.query(`DROP TABLE "WorkspaceNotificationRule"`);
|
|
131
|
+
await queryRunner.query(
|
|
132
|
+
`DROP INDEX "public"."IDX_c68f38e2b2b061c40209e85bf2"`,
|
|
133
|
+
);
|
|
134
|
+
await queryRunner.query(`DROP TABLE "WorkspaceSetting"`);
|
|
135
|
+
await queryRunner.query(
|
|
136
|
+
`DROP INDEX "public"."IDX_73f5887268b09c0abccf04ef02"`,
|
|
137
|
+
);
|
|
138
|
+
await queryRunner.query(`DROP TABLE "WorkspaceProjectAuthToken"`);
|
|
139
|
+
await queryRunner.query(
|
|
140
|
+
`DROP INDEX "public"."IDX_4b7c7d1a8b2259df8c790db094"`,
|
|
141
|
+
);
|
|
142
|
+
await queryRunner.query(
|
|
143
|
+
`DROP INDEX "public"."IDX_bee888f5782b9585e01f13455f"`,
|
|
144
|
+
);
|
|
145
|
+
await queryRunner.query(`DROP TABLE "WorkspaceUserAuthToken"`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class MigrationName1739210586538 implements MigrationInterface {
|
|
4
|
+
public name = "MigrationName1739210586538";
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(`ALTER TABLE "Alert" ADD "alertNumber" integer`);
|
|
8
|
+
await queryRunner.query(
|
|
9
|
+
`CREATE INDEX "IDX_aa91b2228a2b35424a3ae93fdc" ON "Alert" ("alertNumber") `,
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
14
|
+
await queryRunner.query(
|
|
15
|
+
`DROP INDEX "public"."IDX_aa91b2228a2b35424a3ae93fdc"`,
|
|
16
|
+
);
|
|
17
|
+
await queryRunner.query(`ALTER TABLE "Alert" DROP COLUMN "alertNumber"`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class MigrationName1739217257089 implements MigrationInterface {
|
|
4
|
+
public name = "MigrationName1739217257089";
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(
|
|
8
|
+
`ALTER TABLE "ScheduledMaintenance" ADD "scheduledMaintenanceNumber" integer`,
|
|
9
|
+
);
|
|
10
|
+
await queryRunner.query(
|
|
11
|
+
`CREATE INDEX "IDX_207fe82fd8bdc67bbe1aa0ebf8" ON "ScheduledMaintenance" ("scheduledMaintenanceNumber") `,
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
16
|
+
await queryRunner.query(
|
|
17
|
+
`DROP INDEX "public"."IDX_207fe82fd8bdc67bbe1aa0ebf8"`,
|
|
18
|
+
);
|
|
19
|
+
await queryRunner.query(
|
|
20
|
+
`ALTER TABLE "ScheduledMaintenance" DROP COLUMN "scheduledMaintenanceNumber"`,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -99,6 +99,9 @@ import { MigrationName1737141420441 } from "./1737141420441-MigrationName";
|
|
|
99
99
|
import { MigrationName1737713529424 } from "./1737713529424-MigrationName";
|
|
100
100
|
import { MigrationName1737715240684 } from "./1737715240684-MigrationName";
|
|
101
101
|
import { MigrationName1737997557974 } from "./1737997557974-MigrationName";
|
|
102
|
+
import { MigrationName1739209832500 } from "./1739209832500-MigrationName";
|
|
103
|
+
import { MigrationName1739210586538 } from "./1739210586538-MigrationName";
|
|
104
|
+
import { MigrationName1739217257089 } from "./1739217257089-MigrationName";
|
|
102
105
|
|
|
103
106
|
export default [
|
|
104
107
|
InitialMigration,
|
|
@@ -202,4 +205,7 @@ export default [
|
|
|
202
205
|
MigrationName1737713529424,
|
|
203
206
|
MigrationName1737715240684,
|
|
204
207
|
MigrationName1737997557974,
|
|
208
|
+
MigrationName1739209832500,
|
|
209
|
+
MigrationName1739210586538,
|
|
210
|
+
MigrationName1739217257089,
|
|
205
211
|
];
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ExpressResponse,
|
|
3
|
+
NextFunction,
|
|
4
|
+
OneUptimeRequest,
|
|
5
|
+
} from "../Utils/Express";
|
|
6
|
+
import Response from "../Utils/Response";
|
|
7
|
+
import BadDataException from "Common/Types/Exception/BadDataException";
|
|
8
|
+
import { SlackAppSigningSecret } from "../EnvironmentConfig";
|
|
9
|
+
import crypto from "crypto";
|
|
10
|
+
import logger from "../Utils/Logger";
|
|
11
|
+
|
|
12
|
+
export default class SlackAuthorization {
|
|
13
|
+
public static async isAuthorizedSlackRequest(
|
|
14
|
+
req: OneUptimeRequest,
|
|
15
|
+
res: ExpressResponse,
|
|
16
|
+
next: NextFunction,
|
|
17
|
+
): Promise<void> {
|
|
18
|
+
if (!SlackAppSigningSecret) {
|
|
19
|
+
return Response.sendErrorResponse(
|
|
20
|
+
req,
|
|
21
|
+
res,
|
|
22
|
+
new BadDataException(
|
|
23
|
+
"SLACK_APP_SIGNING_SECRET env variable not found.",
|
|
24
|
+
),
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// validate slack signing secret
|
|
29
|
+
const slackSigningSecret: string = SlackAppSigningSecret.toString();
|
|
30
|
+
|
|
31
|
+
const slackSignature: string = req.headers["x-slack-signature"] as string;
|
|
32
|
+
const timestamp: string = req.headers[
|
|
33
|
+
"x-slack-request-timestamp"
|
|
34
|
+
] as string;
|
|
35
|
+
const requestBody: string = req.body;
|
|
36
|
+
|
|
37
|
+
logger.debug(`slackSignature: ${slackSignature}`);
|
|
38
|
+
logger.debug(`timestamp: ${timestamp}`);
|
|
39
|
+
logger.debug(`requestBody: ${requestBody}`);
|
|
40
|
+
|
|
41
|
+
const baseString: string = `v0:${timestamp}:${requestBody}`;
|
|
42
|
+
const signature: string = `v0=${crypto.createHmac("sha256", slackSigningSecret).update(baseString).digest("hex")}`;
|
|
43
|
+
|
|
44
|
+
// check if the signature is valid
|
|
45
|
+
if (
|
|
46
|
+
!crypto.timingSafeEqual(
|
|
47
|
+
Buffer.from(signature),
|
|
48
|
+
Buffer.from(slackSignature),
|
|
49
|
+
)
|
|
50
|
+
) {
|
|
51
|
+
return Response.sendErrorResponse(
|
|
52
|
+
req,
|
|
53
|
+
res,
|
|
54
|
+
new BadDataException("Slack Signature Verification Failed."),
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
next();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -98,6 +98,32 @@ export class Service extends DatabaseService<Model> {
|
|
|
98
98
|
return false;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
public async getExistingAlertNumberForProject(data: {
|
|
102
|
+
projectId: ObjectID;
|
|
103
|
+
}): Promise<number> {
|
|
104
|
+
// get last alert number.
|
|
105
|
+
const lastAlert: Model | null = await this.findOneBy({
|
|
106
|
+
query: {
|
|
107
|
+
projectId: data.projectId,
|
|
108
|
+
},
|
|
109
|
+
select: {
|
|
110
|
+
alertNumber: true,
|
|
111
|
+
},
|
|
112
|
+
sort: {
|
|
113
|
+
createdAt: SortOrder.Descending,
|
|
114
|
+
},
|
|
115
|
+
props: {
|
|
116
|
+
isRoot: true,
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (!lastAlert) {
|
|
121
|
+
return 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return lastAlert.alertNumber || 0;
|
|
125
|
+
}
|
|
126
|
+
|
|
101
127
|
public async acknowledgeAlert(
|
|
102
128
|
alertId: ObjectID,
|
|
103
129
|
acknowledgedByUserId: ObjectID,
|
|
@@ -156,9 +182,12 @@ export class Service extends DatabaseService<Model> {
|
|
|
156
182
|
throw new BadDataException("ProjectId required to create alert.");
|
|
157
183
|
}
|
|
158
184
|
|
|
185
|
+
const projectId: ObjectID =
|
|
186
|
+
createBy.props.tenantId || createBy.data.projectId!;
|
|
187
|
+
|
|
159
188
|
const alertState: AlertState | null = await AlertStateService.findOneBy({
|
|
160
189
|
query: {
|
|
161
|
-
projectId:
|
|
190
|
+
projectId: projectId,
|
|
162
191
|
isCreatedState: true,
|
|
163
192
|
},
|
|
164
193
|
select: {
|
|
@@ -177,6 +206,13 @@ export class Service extends DatabaseService<Model> {
|
|
|
177
206
|
|
|
178
207
|
createBy.data.currentAlertStateId = alertState.id;
|
|
179
208
|
|
|
209
|
+
const alertNumberForThisAlert: number =
|
|
210
|
+
(await this.getExistingAlertNumberForProject({
|
|
211
|
+
projectId: projectId,
|
|
212
|
+
})) + 1;
|
|
213
|
+
|
|
214
|
+
createBy.data.alertNumber = alertNumberForThisAlert;
|
|
215
|
+
|
|
180
216
|
if (
|
|
181
217
|
(createBy.data.createdByUserId ||
|
|
182
218
|
createBy.data.createdByUser ||
|
|
@@ -239,7 +275,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
239
275
|
projectId: createdItem.projectId!,
|
|
240
276
|
alertFeedEventType: AlertFeedEventType.AlertCreated,
|
|
241
277
|
displayColor: Red500,
|
|
242
|
-
feedInfoInMarkdown: `**Alert Created**:
|
|
278
|
+
feedInfoInMarkdown: `**Alert #${createdItem.alertNumber?.toString()} Created**:
|
|
243
279
|
|
|
244
280
|
**Alert Title**:
|
|
245
281
|
|
package/Server/Services/Index.ts
CHANGED
|
@@ -152,6 +152,10 @@ import AlertFeedService from "./AlertFeedService";
|
|
|
152
152
|
import IncidentFeedService from "./IncidentFeedService";
|
|
153
153
|
|
|
154
154
|
import MonitorTestService from "./MonitorTestService";
|
|
155
|
+
import WorkspaceProjectAuthTokenService from "./WorkspaceProjectAuthTokenService";
|
|
156
|
+
import WorkspaceUserAuthTokenService from "./WorkspaceUserAuthTokenService";
|
|
157
|
+
import WorkspaceSettingService from "./WorkspaceSettingService";
|
|
158
|
+
import WorkspaceNotificationRuleService from "./WorkspaceNotificationRuleService";
|
|
155
159
|
|
|
156
160
|
const services: Array<BaseService> = [
|
|
157
161
|
AcmeCertificateService,
|
|
@@ -317,6 +321,11 @@ const services: Array<BaseService> = [
|
|
|
317
321
|
|
|
318
322
|
TableViewService,
|
|
319
323
|
MonitorTestService,
|
|
324
|
+
|
|
325
|
+
WorkspaceProjectAuthTokenService,
|
|
326
|
+
WorkspaceUserAuthTokenService,
|
|
327
|
+
WorkspaceSettingService,
|
|
328
|
+
WorkspaceNotificationRuleService,
|
|
320
329
|
];
|
|
321
330
|
|
|
322
331
|
export const AnalyticsServices: Array<
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import ResellerPlan from "Common/Models/DatabaseModels/ResellerPlan";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
IsBillingEnabled,
|
|
4
|
+
NotificationSlackWebhookOnCreateProject,
|
|
5
|
+
NotificationSlackWebhookOnDeleteProject,
|
|
6
|
+
NotificationSlackWebhookOnSubscriptionUpdate,
|
|
7
|
+
getAllEnvVars,
|
|
8
|
+
} from "../EnvironmentConfig";
|
|
3
9
|
import AllMeteredPlans from "../Types/Billing/MeteredPlan/AllMeteredPlans";
|
|
4
10
|
import CreateBy from "../Types/Database/CreateBy";
|
|
5
11
|
import DeleteBy from "../Types/Database/DeleteBy";
|
|
@@ -61,6 +67,9 @@ import AlertSeverity from "../../Models/DatabaseModels/AlertSeverity";
|
|
|
61
67
|
import AlertSeverityService from "./AlertSeverityService";
|
|
62
68
|
import AlertState from "../../Models/DatabaseModels/AlertState";
|
|
63
69
|
import AlertStateService from "./AlertStateService";
|
|
70
|
+
import SlackUtil from "../Utils/Slack/Slack";
|
|
71
|
+
import URL from "../../Types/API/URL";
|
|
72
|
+
import Exception from "../../Types/Exception/Exception";
|
|
64
73
|
|
|
65
74
|
export interface CurrentPlan {
|
|
66
75
|
plan: PlanType | null;
|
|
@@ -95,6 +104,8 @@ export class ProjectService extends DatabaseService<Model> {
|
|
|
95
104
|
);
|
|
96
105
|
}
|
|
97
106
|
|
|
107
|
+
logger.debug("Creating project for user " + data.props.userId);
|
|
108
|
+
|
|
98
109
|
const user: User | null = await UserService.findOneById({
|
|
99
110
|
id: data.props.userId,
|
|
100
111
|
select: {
|
|
@@ -398,6 +409,13 @@ export class ProjectService extends DatabaseService<Model> {
|
|
|
398
409
|
project.paymentProviderSubscriptionSeats +
|
|
399
410
|
" completed and project updated.",
|
|
400
411
|
);
|
|
412
|
+
|
|
413
|
+
if (project.id) {
|
|
414
|
+
// send slack message on plan change.
|
|
415
|
+
await this.sendSubscriptionChangeWebhookSlackNotification(
|
|
416
|
+
project.id,
|
|
417
|
+
);
|
|
418
|
+
}
|
|
401
419
|
}
|
|
402
420
|
}
|
|
403
421
|
}
|
|
@@ -405,6 +423,57 @@ export class ProjectService extends DatabaseService<Model> {
|
|
|
405
423
|
return { updateBy, carryForward: [] };
|
|
406
424
|
}
|
|
407
425
|
|
|
426
|
+
private async sendSubscriptionChangeWebhookSlackNotification(
|
|
427
|
+
projectId: ObjectID,
|
|
428
|
+
): Promise<void> {
|
|
429
|
+
if (NotificationSlackWebhookOnSubscriptionUpdate) {
|
|
430
|
+
// fetch project again.
|
|
431
|
+
const project: Model | null = await this.findOneById({
|
|
432
|
+
id: new ObjectID(projectId.toString()),
|
|
433
|
+
select: {
|
|
434
|
+
name: true,
|
|
435
|
+
_id: true,
|
|
436
|
+
createdOwnerName: true,
|
|
437
|
+
createdOwnerEmail: true,
|
|
438
|
+
planName: true,
|
|
439
|
+
createdByUserId: true,
|
|
440
|
+
paymentProviderSubscriptionStatus: true,
|
|
441
|
+
},
|
|
442
|
+
props: {
|
|
443
|
+
isRoot: true,
|
|
444
|
+
},
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
if (!project) {
|
|
448
|
+
throw new BadDataException("Project not found");
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
let slackMessage: string = `*Project Plan Changed:*
|
|
452
|
+
*Project Name:* ${project.name?.toString() || "N/A"}
|
|
453
|
+
*Project ID:* ${project.id?.toString() || "N/A"}
|
|
454
|
+
`;
|
|
455
|
+
|
|
456
|
+
if (project.createdOwnerName && project.createdOwnerEmail) {
|
|
457
|
+
slackMessage += `*Project Created By:* ${project?.createdOwnerName?.toString() + " (" + project.createdOwnerEmail.toString() + ")" || "N/A"}
|
|
458
|
+
`;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (IsBillingEnabled) {
|
|
462
|
+
// which plan?
|
|
463
|
+
slackMessage += `*Plan:* ${project.planName?.toString() || "N/A"}
|
|
464
|
+
*Subscription Status:* ${project.paymentProviderSubscriptionStatus?.toString() || "N/A"}
|
|
465
|
+
`;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
SlackUtil.sendMessageToChannel({
|
|
469
|
+
url: URL.fromString(NotificationSlackWebhookOnSubscriptionUpdate),
|
|
470
|
+
text: slackMessage,
|
|
471
|
+
}).catch((error: Exception) => {
|
|
472
|
+
logger.error("Error sending slack message: " + error);
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
408
477
|
private async addDefaultScheduledMaintenanceState(
|
|
409
478
|
createdItem: Model,
|
|
410
479
|
): Promise<Model> {
|
|
@@ -561,6 +630,53 @@ export class ProjectService extends DatabaseService<Model> {
|
|
|
561
630
|
createdItem = await this.addDefaultScheduledMaintenanceState(createdItem);
|
|
562
631
|
createdItem = await this.addDefaultAlertState(createdItem);
|
|
563
632
|
|
|
633
|
+
if (NotificationSlackWebhookOnCreateProject) {
|
|
634
|
+
// fetch project again.
|
|
635
|
+
const project: Model | null = await this.findOneById({
|
|
636
|
+
id: createdItem.id!,
|
|
637
|
+
select: {
|
|
638
|
+
name: true,
|
|
639
|
+
_id: true,
|
|
640
|
+
createdOwnerName: true,
|
|
641
|
+
createdOwnerEmail: true,
|
|
642
|
+
planName: true,
|
|
643
|
+
createdByUserId: true,
|
|
644
|
+
paymentProviderSubscriptionStatus: true,
|
|
645
|
+
},
|
|
646
|
+
props: {
|
|
647
|
+
isRoot: true,
|
|
648
|
+
},
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
if (!project) {
|
|
652
|
+
throw new BadDataException("Project not found");
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
let slackMessage: string = `*Project Created:*
|
|
656
|
+
*Project Name:* ${project.name?.toString() || "N/A"}
|
|
657
|
+
*Project ID:* ${project.id?.toString() || "N/A"}
|
|
658
|
+
`;
|
|
659
|
+
|
|
660
|
+
if (project.createdOwnerName && project.createdOwnerEmail) {
|
|
661
|
+
slackMessage += `*Created By:* ${project?.createdOwnerName?.toString() + " (" + project.createdOwnerEmail.toString() + ")" || "N/A"}
|
|
662
|
+
`;
|
|
663
|
+
|
|
664
|
+
if (IsBillingEnabled) {
|
|
665
|
+
// which plan?
|
|
666
|
+
slackMessage += `*Plan:* ${project.planName?.toString() || "N/A"}
|
|
667
|
+
*Subscription Status:* ${project.paymentProviderSubscriptionStatus?.toString() || "N/A"}
|
|
668
|
+
`;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
SlackUtil.sendMessageToChannel({
|
|
672
|
+
url: URL.fromString(NotificationSlackWebhookOnCreateProject),
|
|
673
|
+
text: slackMessage,
|
|
674
|
+
}).catch((error: Exception) => {
|
|
675
|
+
logger.error("Error sending slack message: " + error);
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
564
680
|
return createdItem;
|
|
565
681
|
}
|
|
566
682
|
|
|
@@ -1007,29 +1123,71 @@ export class ProjectService extends DatabaseService<Model> {
|
|
|
1007
1123
|
protected override async onBeforeDelete(
|
|
1008
1124
|
deleteBy: DeleteBy<Model>,
|
|
1009
1125
|
): Promise<OnDelete<Model>> {
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1126
|
+
const projects: Array<Model> = await this.findBy({
|
|
1127
|
+
query: deleteBy.query,
|
|
1128
|
+
props: {
|
|
1129
|
+
isRoot: true,
|
|
1130
|
+
},
|
|
1131
|
+
limit: LIMIT_MAX,
|
|
1132
|
+
skip: 0,
|
|
1133
|
+
select: {
|
|
1134
|
+
_id: true,
|
|
1135
|
+
paymentProviderSubscriptionId: true,
|
|
1136
|
+
paymentProviderMeteredSubscriptionId: true,
|
|
1137
|
+
name: true,
|
|
1138
|
+
createdByUser: {
|
|
1139
|
+
name: true,
|
|
1140
|
+
email: true,
|
|
1020
1141
|
},
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
return { deleteBy, carryForward: projects };
|
|
1024
|
-
}
|
|
1142
|
+
},
|
|
1143
|
+
});
|
|
1025
1144
|
|
|
1026
|
-
return { deleteBy, carryForward:
|
|
1145
|
+
return { deleteBy, carryForward: projects };
|
|
1027
1146
|
}
|
|
1028
1147
|
|
|
1029
1148
|
protected override async onDeleteSuccess(
|
|
1030
1149
|
onDelete: OnDelete<Model>,
|
|
1031
1150
|
_itemIdsBeforeDelete: ObjectID[],
|
|
1032
1151
|
): Promise<OnDelete<Model>> {
|
|
1152
|
+
if (NotificationSlackWebhookOnDeleteProject) {
|
|
1153
|
+
for (const project of onDelete.carryForward) {
|
|
1154
|
+
let subscriptionStatus: SubscriptionStatus | null = null;
|
|
1155
|
+
|
|
1156
|
+
if (IsBillingEnabled) {
|
|
1157
|
+
subscriptionStatus = await BillingService.getSubscriptionStatus(
|
|
1158
|
+
project.paymentProviderSubscriptionId!,
|
|
1159
|
+
);
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
let slackMessage: string = `*Project Deleted:*
|
|
1163
|
+
*Project Name:* ${project.name?.toString() || "N/A"}
|
|
1164
|
+
*Project ID:* ${project._id?.toString() || "N/A"}
|
|
1165
|
+
`;
|
|
1166
|
+
|
|
1167
|
+
if (subscriptionStatus) {
|
|
1168
|
+
slackMessage += `*Project Subscription Status:* ${subscriptionStatus?.toString() || "N/A"}
|
|
1169
|
+
`;
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
if (
|
|
1173
|
+
project.createdByUser &&
|
|
1174
|
+
project.createdByUser.name &&
|
|
1175
|
+
project.createdByUser.email
|
|
1176
|
+
) {
|
|
1177
|
+
slackMessage += `*Created By:* ${project?.createdByUser.name?.toString() + " (" + project.createdByUser.email.toString() + ")" || "N/A"}
|
|
1178
|
+
`;
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
SlackUtil.sendMessageToChannel({
|
|
1182
|
+
url: URL.fromString(NotificationSlackWebhookOnDeleteProject),
|
|
1183
|
+
text: slackMessage,
|
|
1184
|
+
}).catch((err: Error) => {
|
|
1185
|
+
// log this error but do not throw it. Not important enough to stop the process.
|
|
1186
|
+
logger.error(err);
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1033
1191
|
// get project id
|
|
1034
1192
|
if (IsBillingEnabled) {
|
|
1035
1193
|
for (const project of onDelete.carryForward) {
|
|
@@ -1224,6 +1382,9 @@ export class ProjectService extends DatabaseService<Model> {
|
|
|
1224
1382
|
isRoot: true,
|
|
1225
1383
|
},
|
|
1226
1384
|
});
|
|
1385
|
+
|
|
1386
|
+
// send slack message on plan change.
|
|
1387
|
+
await this.sendSubscriptionChangeWebhookSlackNotification(projectId);
|
|
1227
1388
|
}
|
|
1228
1389
|
|
|
1229
1390
|
public getActiveProjectStatusQuery(): Query<Model> {
|