@oneuptime/common 8.0.5493 → 8.0.5513
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/EnterpriseLicense.ts +104 -0
- package/Models/DatabaseModels/GlobalConfig.ts +71 -0
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Server/API/EnterpriseLicenseAPI.ts +102 -0
- package/Server/API/GlobalConfigAPI.ts +168 -0
- package/Server/EnvironmentConfig.ts +7 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1762181014879-MigrationName.ts +69 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Services/EnterpriseLicenseService.ts +10 -0
- package/Server/Services/IncidentService.ts +13 -2
- package/Server/Services/Index.ts +2 -0
- package/UI/Components/EditionLabel/EditionLabel.tsx +545 -0
- package/UI/Components/Footer/Footer.tsx +18 -2
- package/UI/Components/Link/Link.tsx +7 -4
- package/UI/Components/LogsViewer/LogsViewer.tsx +4 -0
- package/UI/Components/LogsViewer/components/LiveLogsToggle.tsx +46 -0
- package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +4 -0
- package/UI/Components/LogsViewer/types.ts +5 -0
- package/UI/Config.ts +2 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +128 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +78 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.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/Server/API/EnterpriseLicenseAPI.js +71 -0
- package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -0
- package/build/dist/Server/API/GlobalConfigAPI.js +129 -1
- package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +2 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1762181014879-MigrationName.js +30 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1762181014879-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseService.js +9 -0
- package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -0
- package/build/dist/Server/Services/IncidentService.js +5 -4
- package/build/dist/Server/Services/IncidentService.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/UI/Components/EditionLabel/EditionLabel.js +285 -0
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -0
- package/build/dist/UI/Components/Footer/Footer.js +6 -0
- package/build/dist/UI/Components/Footer/Footer.js.map +1 -1
- package/build/dist/UI/Components/Link/Link.js +2 -1
- package/build/dist/UI/Components/Link/Link.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +2 -5
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LiveLogsToggle.js +22 -0
- package/build/dist/UI/Components/LogsViewer/components/LiveLogsToggle.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +4 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/types.js +2 -0
- package/build/dist/UI/Components/LogsViewer/types.js.map +1 -0
- package/build/dist/UI/Config.js +1 -0
- package/build/dist/UI/Config.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,104 @@
|
|
|
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, Index } from "typeorm";
|
|
13
|
+
|
|
14
|
+
@TableAccessControl({
|
|
15
|
+
create: [],
|
|
16
|
+
read: [],
|
|
17
|
+
update: [],
|
|
18
|
+
delete: [],
|
|
19
|
+
})
|
|
20
|
+
@CrudApiEndpoint(new Route("/enterprise-license"))
|
|
21
|
+
@TableMetadata({
|
|
22
|
+
tableName: "EnterpriseLicense",
|
|
23
|
+
singularName: "Enterprise License",
|
|
24
|
+
pluralName: "Enterprise Licenses",
|
|
25
|
+
icon: IconProp.Lock,
|
|
26
|
+
tableDescription: "Enterprise license keys issued by OneUptime.",
|
|
27
|
+
})
|
|
28
|
+
@Entity({
|
|
29
|
+
name: "EnterpriseLicense",
|
|
30
|
+
})
|
|
31
|
+
export default class EnterpriseLicense extends BaseModel {
|
|
32
|
+
@ColumnAccessControl({
|
|
33
|
+
create: [],
|
|
34
|
+
read: [],
|
|
35
|
+
update: [],
|
|
36
|
+
})
|
|
37
|
+
@TableColumn({
|
|
38
|
+
required: true,
|
|
39
|
+
type: TableColumnType.ShortText,
|
|
40
|
+
title: "Company Name",
|
|
41
|
+
description: "Company name associated with this license.",
|
|
42
|
+
})
|
|
43
|
+
@Column({
|
|
44
|
+
nullable: false,
|
|
45
|
+
type: ColumnType.ShortText,
|
|
46
|
+
length: ColumnLength.ShortText,
|
|
47
|
+
})
|
|
48
|
+
public companyName?: string = undefined;
|
|
49
|
+
|
|
50
|
+
@ColumnAccessControl({
|
|
51
|
+
create: [],
|
|
52
|
+
read: [],
|
|
53
|
+
update: [],
|
|
54
|
+
})
|
|
55
|
+
@TableColumn({
|
|
56
|
+
required: true,
|
|
57
|
+
type: TableColumnType.ShortText,
|
|
58
|
+
title: "License Key",
|
|
59
|
+
description: "Enterprise license key.",
|
|
60
|
+
unique: true,
|
|
61
|
+
})
|
|
62
|
+
@Index({ unique: true })
|
|
63
|
+
@Column({
|
|
64
|
+
nullable: false,
|
|
65
|
+
type: ColumnType.ShortText,
|
|
66
|
+
length: ColumnLength.ShortText,
|
|
67
|
+
unique: true,
|
|
68
|
+
})
|
|
69
|
+
public licenseKey?: string = undefined;
|
|
70
|
+
|
|
71
|
+
@ColumnAccessControl({
|
|
72
|
+
create: [],
|
|
73
|
+
read: [],
|
|
74
|
+
update: [],
|
|
75
|
+
})
|
|
76
|
+
@TableColumn({
|
|
77
|
+
required: true,
|
|
78
|
+
type: TableColumnType.Date,
|
|
79
|
+
title: "Expires At",
|
|
80
|
+
description: "Expiration date of this license.",
|
|
81
|
+
})
|
|
82
|
+
@Column({
|
|
83
|
+
nullable: false,
|
|
84
|
+
type: ColumnType.Date,
|
|
85
|
+
})
|
|
86
|
+
public expiresAt?: Date = undefined;
|
|
87
|
+
|
|
88
|
+
@ColumnAccessControl({
|
|
89
|
+
create: [],
|
|
90
|
+
read: [],
|
|
91
|
+
update: [],
|
|
92
|
+
})
|
|
93
|
+
@TableColumn({
|
|
94
|
+
required: false,
|
|
95
|
+
type: TableColumnType.Number,
|
|
96
|
+
title: "Annual Contract Value",
|
|
97
|
+
description: "Annual contract value (in USD) for this license.",
|
|
98
|
+
})
|
|
99
|
+
@Column({
|
|
100
|
+
nullable: true,
|
|
101
|
+
type: ColumnType.Number,
|
|
102
|
+
})
|
|
103
|
+
public annualContractValue?: number = undefined;
|
|
104
|
+
}
|
|
@@ -497,4 +497,75 @@ export default class GlobalConfig extends GlobalConfigModel {
|
|
|
497
497
|
transformer: Email.getDatabaseTransformer(),
|
|
498
498
|
})
|
|
499
499
|
public adminNotificationEmail?: Email = undefined;
|
|
500
|
+
|
|
501
|
+
@ColumnAccessControl({
|
|
502
|
+
create: [],
|
|
503
|
+
read: [],
|
|
504
|
+
update: [],
|
|
505
|
+
})
|
|
506
|
+
@TableColumn({
|
|
507
|
+
type: TableColumnType.ShortText,
|
|
508
|
+
title: "Enterprise Company Name",
|
|
509
|
+
description:
|
|
510
|
+
"Company name associated with the validated enterprise license.",
|
|
511
|
+
})
|
|
512
|
+
@Column({
|
|
513
|
+
type: ColumnType.ShortText,
|
|
514
|
+
length: ColumnLength.ShortText,
|
|
515
|
+
nullable: true,
|
|
516
|
+
unique: true,
|
|
517
|
+
})
|
|
518
|
+
public enterpriseCompanyName?: string = undefined;
|
|
519
|
+
|
|
520
|
+
@ColumnAccessControl({
|
|
521
|
+
create: [],
|
|
522
|
+
read: [],
|
|
523
|
+
update: [],
|
|
524
|
+
})
|
|
525
|
+
@TableColumn({
|
|
526
|
+
type: TableColumnType.ShortText,
|
|
527
|
+
title: "Enterprise License Key",
|
|
528
|
+
description: "Enterprise license key stored after successful validation.",
|
|
529
|
+
})
|
|
530
|
+
@Column({
|
|
531
|
+
type: ColumnType.ShortText,
|
|
532
|
+
length: ColumnLength.ShortText,
|
|
533
|
+
nullable: true,
|
|
534
|
+
unique: true,
|
|
535
|
+
})
|
|
536
|
+
public enterpriseLicenseKey?: string = undefined;
|
|
537
|
+
|
|
538
|
+
@ColumnAccessControl({
|
|
539
|
+
create: [],
|
|
540
|
+
read: [],
|
|
541
|
+
update: [],
|
|
542
|
+
})
|
|
543
|
+
@TableColumn({
|
|
544
|
+
type: TableColumnType.Date,
|
|
545
|
+
title: "Enterprise License Expires At",
|
|
546
|
+
description: "Expiration date of the validated enterprise license.",
|
|
547
|
+
})
|
|
548
|
+
@Column({
|
|
549
|
+
type: ColumnType.Date,
|
|
550
|
+
nullable: true,
|
|
551
|
+
unique: true,
|
|
552
|
+
})
|
|
553
|
+
public enterpriseLicenseExpiresAt?: Date = undefined;
|
|
554
|
+
|
|
555
|
+
@ColumnAccessControl({
|
|
556
|
+
create: [],
|
|
557
|
+
read: [],
|
|
558
|
+
update: [],
|
|
559
|
+
})
|
|
560
|
+
@TableColumn({
|
|
561
|
+
type: TableColumnType.VeryLongText,
|
|
562
|
+
title: "Enterprise License Token",
|
|
563
|
+
description: "Signed JWT returned from license validation.",
|
|
564
|
+
})
|
|
565
|
+
@Column({
|
|
566
|
+
type: ColumnType.VeryLongText,
|
|
567
|
+
nullable: true,
|
|
568
|
+
unique: true,
|
|
569
|
+
})
|
|
570
|
+
public enterpriseLicenseToken?: string = undefined;
|
|
500
571
|
}
|
|
@@ -81,6 +81,7 @@ import ProjectSmtpConfig from "./ProjectSmtpConfig";
|
|
|
81
81
|
//SSO
|
|
82
82
|
import ProjectSSO from "./ProjectSso";
|
|
83
83
|
import PromoCode from "./PromoCode";
|
|
84
|
+
import EnterpriseLicense from "./EnterpriseLicense";
|
|
84
85
|
import Reseller from "./Reseller";
|
|
85
86
|
import ResellerPlan from "./ResellerPlan";
|
|
86
87
|
// ScheduledMaintenances
|
|
@@ -331,6 +332,7 @@ const AllModelTypes: Array<{
|
|
|
331
332
|
ResellerPlan,
|
|
332
333
|
|
|
333
334
|
PromoCode,
|
|
335
|
+
EnterpriseLicense,
|
|
334
336
|
|
|
335
337
|
GlobalConfig,
|
|
336
338
|
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import EnterpriseLicense from "../../Models/DatabaseModels/EnterpriseLicense";
|
|
2
|
+
import BadDataException from "../../Types/Exception/BadDataException";
|
|
3
|
+
import { JSONObject } from "../../Types/JSON";
|
|
4
|
+
import EnterpriseLicenseService, {
|
|
5
|
+
Service as EnterpriseLicenseServiceType,
|
|
6
|
+
} from "../Services/EnterpriseLicenseService";
|
|
7
|
+
import UserMiddleware from "../Middleware/UserAuthorization";
|
|
8
|
+
import JSONWebToken from "../Utils/JsonWebToken";
|
|
9
|
+
import Response from "../Utils/Response";
|
|
10
|
+
import {
|
|
11
|
+
ExpressRequest,
|
|
12
|
+
ExpressResponse,
|
|
13
|
+
NextFunction,
|
|
14
|
+
} from "../Utils/Express";
|
|
15
|
+
import BaseAPI from "./BaseAPI";
|
|
16
|
+
// import { Host } from "../EnvironmentConfig";
|
|
17
|
+
|
|
18
|
+
export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
19
|
+
EnterpriseLicense,
|
|
20
|
+
EnterpriseLicenseServiceType
|
|
21
|
+
> {
|
|
22
|
+
public constructor() {
|
|
23
|
+
super(EnterpriseLicense, EnterpriseLicenseService);
|
|
24
|
+
|
|
25
|
+
this.router.post(
|
|
26
|
+
`${new this.entityType().getCrudApiPath()?.toString()}/validate`,
|
|
27
|
+
UserMiddleware.getUserMiddleware,
|
|
28
|
+
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
29
|
+
try {
|
|
30
|
+
const licenseKey: string | undefined = req.body["licenseKey"];
|
|
31
|
+
|
|
32
|
+
if (!licenseKey) {
|
|
33
|
+
throw new BadDataException("License key is required");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//const serverHost: string = Host.toString();
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
* if (!serverHost.includes("oneuptime.com")) {
|
|
40
|
+
* throw new BadDataException(
|
|
41
|
+
* "Enterprise license validation is only available on oneuptime.com",
|
|
42
|
+
* );
|
|
43
|
+
* }
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
const license: EnterpriseLicense | null =
|
|
47
|
+
await EnterpriseLicenseService.findOneBy({
|
|
48
|
+
query: {
|
|
49
|
+
licenseKey: licenseKey,
|
|
50
|
+
},
|
|
51
|
+
select: {
|
|
52
|
+
companyName: true,
|
|
53
|
+
expiresAt: true,
|
|
54
|
+
licenseKey: true,
|
|
55
|
+
},
|
|
56
|
+
props: {
|
|
57
|
+
isRoot: true,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (!license) {
|
|
62
|
+
throw new BadDataException("License key is invalid");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!license.expiresAt) {
|
|
66
|
+
throw new BadDataException("License expiration is not set");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const now: number = Date.now();
|
|
70
|
+
const expiresAtMs: number = license.expiresAt.getTime();
|
|
71
|
+
const secondsUntilExpiry: number = Math.floor(
|
|
72
|
+
(expiresAtMs - now) / 1000,
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
if (secondsUntilExpiry <= 0) {
|
|
76
|
+
throw new BadDataException("License key has expired");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const payload: JSONObject = {
|
|
80
|
+
companyName: license.companyName || "",
|
|
81
|
+
expiresAt: license.expiresAt.toISOString(),
|
|
82
|
+
licenseKey: license.licenseKey || "",
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const token: string = JSONWebToken.signJsonPayload(
|
|
86
|
+
payload,
|
|
87
|
+
Math.max(secondsUntilExpiry, 1),
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return Response.sendJsonObjectResponse(req, res, {
|
|
91
|
+
companyName: payload["companyName"] as string,
|
|
92
|
+
expiresAt: payload["expiresAt"] as string,
|
|
93
|
+
licenseKey: payload["licenseKey"] as string,
|
|
94
|
+
token,
|
|
95
|
+
});
|
|
96
|
+
} catch (err) {
|
|
97
|
+
next(err);
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -9,6 +9,15 @@ import {
|
|
|
9
9
|
import Response from "../Utils/Response";
|
|
10
10
|
import BaseAPI from "./BaseAPI";
|
|
11
11
|
import GlobalConfig from "../../Models/DatabaseModels/GlobalConfig";
|
|
12
|
+
import ObjectID from "../../Types/ObjectID";
|
|
13
|
+
import { JSONObject } from "../../Types/JSON";
|
|
14
|
+
import BadDataException from "../../Types/Exception/BadDataException";
|
|
15
|
+
import API from "../../Utils/API";
|
|
16
|
+
import HTTPErrorResponse from "../../Types/API/HTTPErrorResponse";
|
|
17
|
+
import HTTPResponse from "../../Types/API/HTTPResponse";
|
|
18
|
+
import PartialEntity from "../../Types/Database/PartialEntity";
|
|
19
|
+
import { EnterpriseLicenseValidationUrl } from "../EnvironmentConfig";
|
|
20
|
+
import UserMiddleware from "../Middleware/UserAuthorization";
|
|
12
21
|
|
|
13
22
|
export default class GlobalConfigAPI extends BaseAPI<
|
|
14
23
|
GlobalConfig,
|
|
@@ -45,5 +54,164 @@ export default class GlobalConfigAPI extends BaseAPI<
|
|
|
45
54
|
}
|
|
46
55
|
},
|
|
47
56
|
);
|
|
57
|
+
|
|
58
|
+
this.router.get(
|
|
59
|
+
`${new this.entityType().getCrudApiPath()?.toString()}/license`,
|
|
60
|
+
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
61
|
+
try {
|
|
62
|
+
const config: GlobalConfig | null =
|
|
63
|
+
await GlobalConfigService.findOneById({
|
|
64
|
+
id: ObjectID.getZeroObjectID(),
|
|
65
|
+
select: {
|
|
66
|
+
enterpriseCompanyName: true,
|
|
67
|
+
enterpriseLicenseExpiresAt: true,
|
|
68
|
+
enterpriseLicenseKey: true,
|
|
69
|
+
enterpriseLicenseToken: true,
|
|
70
|
+
},
|
|
71
|
+
props: {
|
|
72
|
+
isRoot: true,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const responseBody: JSONObject = {
|
|
77
|
+
companyName: config?.enterpriseCompanyName || null,
|
|
78
|
+
expiresAt: config?.enterpriseLicenseExpiresAt
|
|
79
|
+
? config.enterpriseLicenseExpiresAt.toISOString()
|
|
80
|
+
: null,
|
|
81
|
+
licenseKey: config?.enterpriseLicenseKey || null,
|
|
82
|
+
token: config?.enterpriseLicenseToken || null,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
return Response.sendJsonObjectResponse(req, res, responseBody);
|
|
86
|
+
} catch (err) {
|
|
87
|
+
next(err);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
this.router.post(
|
|
93
|
+
`${new this.entityType().getCrudApiPath()?.toString()}/license`,
|
|
94
|
+
UserMiddleware.getUserMiddleware,
|
|
95
|
+
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
96
|
+
try {
|
|
97
|
+
const licenseKey: string =
|
|
98
|
+
(req.body["licenseKey"] as string | undefined)?.trim() || "";
|
|
99
|
+
|
|
100
|
+
if (!licenseKey) {
|
|
101
|
+
throw new BadDataException("License key is required");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const validationResponse:
|
|
105
|
+
| HTTPResponse<JSONObject>
|
|
106
|
+
| HTTPErrorResponse = await API.post<JSONObject>({
|
|
107
|
+
url: EnterpriseLicenseValidationUrl,
|
|
108
|
+
data: {
|
|
109
|
+
licenseKey,
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
if (!validationResponse.isSuccess()) {
|
|
114
|
+
const errorMessage: string =
|
|
115
|
+
validationResponse instanceof HTTPErrorResponse
|
|
116
|
+
? validationResponse.message ||
|
|
117
|
+
"Failed to validate license key."
|
|
118
|
+
: "Failed to validate license key.";
|
|
119
|
+
throw new BadDataException(errorMessage);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const payload: JSONObject = validationResponse.data as JSONObject;
|
|
123
|
+
|
|
124
|
+
const companyNameRaw: string =
|
|
125
|
+
(payload["companyName"] as string | undefined)?.trim() || "";
|
|
126
|
+
const expiresAtRaw: string =
|
|
127
|
+
(payload["expiresAt"] as string | undefined) || "";
|
|
128
|
+
const licenseKeyRaw: string =
|
|
129
|
+
(payload["licenseKey"] as string | undefined)?.trim() || licenseKey;
|
|
130
|
+
const licenseToken: string =
|
|
131
|
+
(payload["token"] as string | undefined) || "";
|
|
132
|
+
|
|
133
|
+
let licenseExpiry: Date | undefined = undefined;
|
|
134
|
+
if (expiresAtRaw) {
|
|
135
|
+
const parsedDate: Date = new Date(expiresAtRaw);
|
|
136
|
+
|
|
137
|
+
if (Number.isNaN(parsedDate.getTime())) {
|
|
138
|
+
throw new BadDataException(
|
|
139
|
+
"License expiration returned from server is invalid.",
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
licenseExpiry = parsedDate;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const updatePayload: PartialEntity<GlobalConfig> = {
|
|
147
|
+
enterpriseCompanyName: companyNameRaw || null,
|
|
148
|
+
enterpriseLicenseKey: licenseKeyRaw || null,
|
|
149
|
+
enterpriseLicenseExpiresAt: licenseExpiry || null,
|
|
150
|
+
enterpriseLicenseToken: licenseToken || null,
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const globalConfigId: ObjectID = ObjectID.getZeroObjectID();
|
|
154
|
+
|
|
155
|
+
const existingConfig: GlobalConfig | null =
|
|
156
|
+
await GlobalConfigService.findOneById({
|
|
157
|
+
id: globalConfigId,
|
|
158
|
+
select: {
|
|
159
|
+
_id: true,
|
|
160
|
+
},
|
|
161
|
+
props: {
|
|
162
|
+
isRoot: true,
|
|
163
|
+
ignoreHooks: true,
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
if (existingConfig) {
|
|
168
|
+
await GlobalConfigService.updateOneById({
|
|
169
|
+
id: globalConfigId,
|
|
170
|
+
data: updatePayload,
|
|
171
|
+
props: {
|
|
172
|
+
isRoot: true,
|
|
173
|
+
ignoreHooks: true,
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
} else {
|
|
177
|
+
const newConfig: GlobalConfig = new GlobalConfig();
|
|
178
|
+
newConfig.id = globalConfigId;
|
|
179
|
+
|
|
180
|
+
if (companyNameRaw) {
|
|
181
|
+
newConfig.enterpriseCompanyName = companyNameRaw;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (licenseKeyRaw) {
|
|
185
|
+
newConfig.enterpriseLicenseKey = licenseKeyRaw;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (licenseToken) {
|
|
189
|
+
newConfig.enterpriseLicenseToken = licenseToken;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (licenseExpiry) {
|
|
193
|
+
newConfig.enterpriseLicenseExpiresAt = licenseExpiry;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
await GlobalConfigService.create({
|
|
197
|
+
data: newConfig,
|
|
198
|
+
props: {
|
|
199
|
+
isRoot: true,
|
|
200
|
+
ignoreHooks: true,
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return Response.sendJsonObjectResponse(req, res, {
|
|
206
|
+
companyName: companyNameRaw || null,
|
|
207
|
+
expiresAt: licenseExpiry ? licenseExpiry.toISOString() : null,
|
|
208
|
+
licenseKey: licenseKeyRaw || null,
|
|
209
|
+
token: licenseToken || null,
|
|
210
|
+
});
|
|
211
|
+
} catch (err) {
|
|
212
|
+
next(err);
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
);
|
|
48
216
|
}
|
|
49
217
|
}
|
|
@@ -365,6 +365,9 @@ export const DocsClientUrl: URL = new URL(
|
|
|
365
365
|
export const DisableTelemetry: boolean =
|
|
366
366
|
process.env["DISABLE_TELEMETRY"] === "true";
|
|
367
367
|
|
|
368
|
+
export const IsEnterpriseEdition: boolean =
|
|
369
|
+
process.env["IS_ENTERPRISE_EDITION"] === "true";
|
|
370
|
+
|
|
368
371
|
export const AverageSpanRowSizeInBytes: number = parsePositiveNumberFromEnv(
|
|
369
372
|
"AVERAGE_SPAN_ROW_SIZE_IN_BYTES",
|
|
370
373
|
1024,
|
|
@@ -405,3 +408,7 @@ export const VapidPrivateKey: string | undefined =
|
|
|
405
408
|
|
|
406
409
|
export const VapidSubject: string =
|
|
407
410
|
process.env["VAPID_SUBJECT"] || "mailto:support@oneuptime.com";
|
|
411
|
+
|
|
412
|
+
export const EnterpriseLicenseValidationUrl: URL = URL.fromString(
|
|
413
|
+
"https://oneuptime.com/api/enterprise-license/validate",
|
|
414
|
+
);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class MigrationName1762181014879 implements MigrationInterface {
|
|
4
|
+
public name = "MigrationName1762181014879";
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(
|
|
8
|
+
`CREATE TABLE "EnterpriseLicense" ("_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, "companyName" character varying(100) NOT NULL, "licenseKey" character varying(100) NOT NULL, "expiresAt" TIMESTAMP WITH TIME ZONE NOT NULL, "annualContractValue" integer, CONSTRAINT "UQ_d35e76999092d8a16a66e84c17c" UNIQUE ("licenseKey"), CONSTRAINT "PK_731aa4437672f250fd51ec04166" PRIMARY KEY ("_id"))`,
|
|
9
|
+
);
|
|
10
|
+
await queryRunner.query(
|
|
11
|
+
`CREATE UNIQUE INDEX "IDX_d35e76999092d8a16a66e84c17" ON "EnterpriseLicense" ("licenseKey") `,
|
|
12
|
+
);
|
|
13
|
+
await queryRunner.query(
|
|
14
|
+
`ALTER TABLE "GlobalConfig" ADD "enterpriseCompanyName" character varying(100)`,
|
|
15
|
+
);
|
|
16
|
+
await queryRunner.query(
|
|
17
|
+
`ALTER TABLE "GlobalConfig" ADD CONSTRAINT "UQ_46983cb1a59503dc09fc84bbe0c" UNIQUE ("enterpriseCompanyName")`,
|
|
18
|
+
);
|
|
19
|
+
await queryRunner.query(
|
|
20
|
+
`ALTER TABLE "GlobalConfig" ADD "enterpriseLicenseKey" character varying(100)`,
|
|
21
|
+
);
|
|
22
|
+
await queryRunner.query(
|
|
23
|
+
`ALTER TABLE "GlobalConfig" ADD CONSTRAINT "UQ_89f80e8a18c3372ee150a3812c1" UNIQUE ("enterpriseLicenseKey")`,
|
|
24
|
+
);
|
|
25
|
+
await queryRunner.query(
|
|
26
|
+
`ALTER TABLE "GlobalConfig" ADD "enterpriseLicenseExpiresAt" TIMESTAMP WITH TIME ZONE`,
|
|
27
|
+
);
|
|
28
|
+
await queryRunner.query(
|
|
29
|
+
`ALTER TABLE "GlobalConfig" ADD CONSTRAINT "UQ_a361278e9ce4056d59e8fb13319" UNIQUE ("enterpriseLicenseExpiresAt")`,
|
|
30
|
+
);
|
|
31
|
+
await queryRunner.query(
|
|
32
|
+
`ALTER TABLE "GlobalConfig" ADD "enterpriseLicenseToken" text`,
|
|
33
|
+
);
|
|
34
|
+
await queryRunner.query(
|
|
35
|
+
`ALTER TABLE "GlobalConfig" ADD CONSTRAINT "UQ_b0b9322c111c0cc629fedbb4eb3" UNIQUE ("enterpriseLicenseToken")`,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
40
|
+
await queryRunner.query(
|
|
41
|
+
`ALTER TABLE "GlobalConfig" DROP CONSTRAINT "UQ_b0b9322c111c0cc629fedbb4eb3"`,
|
|
42
|
+
);
|
|
43
|
+
await queryRunner.query(
|
|
44
|
+
`ALTER TABLE "GlobalConfig" DROP COLUMN "enterpriseLicenseToken"`,
|
|
45
|
+
);
|
|
46
|
+
await queryRunner.query(
|
|
47
|
+
`ALTER TABLE "GlobalConfig" DROP CONSTRAINT "UQ_a361278e9ce4056d59e8fb13319"`,
|
|
48
|
+
);
|
|
49
|
+
await queryRunner.query(
|
|
50
|
+
`ALTER TABLE "GlobalConfig" DROP COLUMN "enterpriseLicenseExpiresAt"`,
|
|
51
|
+
);
|
|
52
|
+
await queryRunner.query(
|
|
53
|
+
`ALTER TABLE "GlobalConfig" DROP CONSTRAINT "UQ_89f80e8a18c3372ee150a3812c1"`,
|
|
54
|
+
);
|
|
55
|
+
await queryRunner.query(
|
|
56
|
+
`ALTER TABLE "GlobalConfig" DROP COLUMN "enterpriseLicenseKey"`,
|
|
57
|
+
);
|
|
58
|
+
await queryRunner.query(
|
|
59
|
+
`ALTER TABLE "GlobalConfig" DROP CONSTRAINT "UQ_46983cb1a59503dc09fc84bbe0c"`,
|
|
60
|
+
);
|
|
61
|
+
await queryRunner.query(
|
|
62
|
+
`ALTER TABLE "GlobalConfig" DROP COLUMN "enterpriseCompanyName"`,
|
|
63
|
+
);
|
|
64
|
+
await queryRunner.query(
|
|
65
|
+
`DROP INDEX "public"."IDX_d35e76999092d8a16a66e84c17"`,
|
|
66
|
+
);
|
|
67
|
+
await queryRunner.query(`DROP TABLE "EnterpriseLicense"`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -179,6 +179,7 @@ import { MigrationName1760345757975 } from "./1760345757975-MigrationName";
|
|
|
179
179
|
import { MigrationName1760357680881 } from "./1760357680881-MigrationName";
|
|
180
180
|
import { MigrationName1761232578396 } from "./1761232578396-MigrationName";
|
|
181
181
|
import { MigrationName1761834523183 } from "./1761834523183-MigrationName";
|
|
182
|
+
import { MigrationName1762181014879 } from "./1762181014879-MigrationName";
|
|
182
183
|
|
|
183
184
|
export default [
|
|
184
185
|
InitialMigration,
|
|
@@ -362,4 +363,5 @@ export default [
|
|
|
362
363
|
MigrationName1760357680881,
|
|
363
364
|
MigrationName1761232578396,
|
|
364
365
|
MigrationName1761834523183,
|
|
366
|
+
MigrationName1762181014879,
|
|
365
367
|
];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import DatabaseService from "./DatabaseService";
|
|
2
|
+
import EnterpriseLicense from "../../Models/DatabaseModels/EnterpriseLicense";
|
|
3
|
+
|
|
4
|
+
export class Service extends DatabaseService<EnterpriseLicense> {
|
|
5
|
+
public constructor() {
|
|
6
|
+
super(EnterpriseLicense);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default new Service();
|
|
@@ -74,6 +74,17 @@ type UpdateCarryForward = Dictionary<{
|
|
|
74
74
|
newMonitorChangeStatusIdTo: ObjectID | undefined;
|
|
75
75
|
}>;
|
|
76
76
|
|
|
77
|
+
type IncidentUpdatePayload = {
|
|
78
|
+
postmortemNote?: string | null;
|
|
79
|
+
title?: string | null;
|
|
80
|
+
rootCause?: string | null;
|
|
81
|
+
description?: string | null;
|
|
82
|
+
remediationNotes?: string | null;
|
|
83
|
+
labels?: unknown;
|
|
84
|
+
incidentSeverity?: unknown;
|
|
85
|
+
[key: string]: unknown;
|
|
86
|
+
};
|
|
87
|
+
|
|
77
88
|
export class Service extends DatabaseService<Model> {
|
|
78
89
|
public constructor() {
|
|
79
90
|
super(Model);
|
|
@@ -1303,8 +1314,8 @@ ${incident.remediationNotes || "No remediation notes provided."}
|
|
|
1303
1314
|
incidentId,
|
|
1304
1315
|
);
|
|
1305
1316
|
|
|
1306
|
-
const updatedIncidentData:
|
|
1307
|
-
|
|
1317
|
+
const updatedIncidentData: IncidentUpdatePayload = (onUpdate.updateBy
|
|
1318
|
+
.data ?? {}) as IncidentUpdatePayload;
|
|
1308
1319
|
|
|
1309
1320
|
const createdByUserId: ObjectID | undefined | null =
|
|
1310
1321
|
onUpdate.updateBy.props.userId;
|
package/Server/Services/Index.ts
CHANGED
|
@@ -71,6 +71,7 @@ import ProjectService from "./ProjectService";
|
|
|
71
71
|
import ProjectSmtpConfigService from "./ProjectSmtpConfigService";
|
|
72
72
|
import ProjectSsoService from "./ProjectSsoService";
|
|
73
73
|
import PromoCodeService from "./PromoCodeService";
|
|
74
|
+
import EnterpriseLicenseService from "./EnterpriseLicenseService";
|
|
74
75
|
import ResellerPlanService from "./ResellerPlanService";
|
|
75
76
|
import ResellerService from "./ResellerService";
|
|
76
77
|
import ScheduledMaintenanceCustomFieldService from "./ScheduledMaintenanceCustomFieldService";
|
|
@@ -173,6 +174,7 @@ const services: Array<BaseService> = [
|
|
|
173
174
|
OnCallDutyPolicyTimeLogService,
|
|
174
175
|
AcmeCertificateService,
|
|
175
176
|
PromoCodeService,
|
|
177
|
+
EnterpriseLicenseService,
|
|
176
178
|
|
|
177
179
|
ResellerService,
|
|
178
180
|
ResellerPlanService,
|