@oneuptime/common 8.0.5496 → 8.0.5514

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.
Files changed (47) hide show
  1. package/Models/DatabaseModels/EnterpriseLicense.ts +104 -0
  2. package/Models/DatabaseModels/GlobalConfig.ts +71 -0
  3. package/Models/DatabaseModels/Index.ts +2 -0
  4. package/Server/API/EnterpriseLicenseAPI.ts +102 -0
  5. package/Server/API/GlobalConfigAPI.ts +168 -0
  6. package/Server/EnvironmentConfig.ts +7 -0
  7. package/Server/Infrastructure/Postgres/SchemaMigrations/1762181014879-MigrationName.ts +69 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  9. package/Server/Services/EnterpriseLicenseService.ts +10 -0
  10. package/Server/Services/Index.ts +2 -0
  11. package/UI/Components/EditionLabel/EditionLabel.tsx +563 -0
  12. package/UI/Components/Footer/Footer.tsx +18 -2
  13. package/UI/Components/Link/Link.tsx +7 -4
  14. package/UI/Components/Modal/Modal.tsx +1 -1
  15. package/UI/Components/Modal/ModalFooter.tsx +2 -2
  16. package/UI/Config.ts +2 -0
  17. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +128 -0
  18. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -0
  19. package/build/dist/Models/DatabaseModels/GlobalConfig.js +78 -0
  20. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  21. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  22. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  23. package/build/dist/Server/API/EnterpriseLicenseAPI.js +71 -0
  24. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -0
  25. package/build/dist/Server/API/GlobalConfigAPI.js +129 -1
  26. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  27. package/build/dist/Server/EnvironmentConfig.js +2 -0
  28. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  29. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1762181014879-MigrationName.js +30 -0
  30. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1762181014879-MigrationName.js.map +1 -0
  31. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  32. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  33. package/build/dist/Server/Services/EnterpriseLicenseService.js +9 -0
  34. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -0
  35. package/build/dist/Server/Services/Index.js +2 -0
  36. package/build/dist/Server/Services/Index.js.map +1 -1
  37. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +302 -0
  38. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -0
  39. package/build/dist/UI/Components/Footer/Footer.js +6 -0
  40. package/build/dist/UI/Components/Footer/Footer.js.map +1 -1
  41. package/build/dist/UI/Components/Link/Link.js +2 -1
  42. package/build/dist/UI/Components/Link/Link.js.map +1 -1
  43. package/build/dist/UI/Components/Modal/ModalFooter.js +2 -1
  44. package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
  45. package/build/dist/UI/Config.js +1 -0
  46. package/build/dist/UI/Config.js.map +1 -1
  47. 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();
@@ -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,