@oneuptime/common 11.3.20 → 11.3.22
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/AnalyticsModels/AnalyticsBaseModel/CommonModel.ts +2 -0
- package/Models/AnalyticsModels/ExceptionInstance.ts +1 -0
- package/Models/AnalyticsModels/Log.ts +1 -0
- package/Models/AnalyticsModels/Metric.ts +1 -0
- package/Models/AnalyticsModels/MonitorLog.ts +1 -0
- package/Models/AnalyticsModels/Span.ts +1 -0
- package/Models/DatabaseModels/Alert.ts +100 -0
- package/Models/DatabaseModels/AlertInternalNote.ts +2 -0
- package/Models/DatabaseModels/AlertReminderRule.ts +597 -0
- package/Models/DatabaseModels/AlertSeverity.ts +2 -0
- package/Models/DatabaseModels/AlertState.ts +2 -0
- package/Models/DatabaseModels/AlertStateTimeline.ts +2 -0
- package/Models/DatabaseModels/EnterpriseLicenseInstance.ts +173 -0
- package/Models/DatabaseModels/GlobalConfig.ts +19 -0
- package/Models/DatabaseModels/Incident.ts +100 -0
- package/Models/DatabaseModels/IncidentInternalNote.ts +2 -0
- package/Models/DatabaseModels/IncidentPublicNote.ts +2 -0
- package/Models/DatabaseModels/IncidentReminderRule.ts +597 -0
- package/Models/DatabaseModels/IncidentSeverity.ts +2 -0
- package/Models/DatabaseModels/IncidentStateTimeline.ts +2 -0
- package/Models/DatabaseModels/Index.ts +8 -0
- package/Models/DatabaseModels/Label.ts +2 -0
- package/Models/DatabaseModels/MonitorStatusTimeline.ts +2 -0
- package/Models/DatabaseModels/ScheduledMaintenance.ts +100 -0
- package/Models/DatabaseModels/ScheduledMaintenanceReminderRule.ts +585 -0
- package/Models/DatabaseModels/ScheduledMaintenanceState.ts +2 -0
- package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +2 -0
- package/Models/DatabaseModels/StatusPageAnnouncement.ts +2 -0
- package/Server/API/DashboardAPI.ts +221 -0
- package/Server/API/EnterpriseLicenseAPI.ts +279 -12
- package/Server/API/GlobalConfigAPI.ts +81 -16
- package/Server/API/StatusPageAPI.ts +894 -791
- package/Server/EnvironmentConfig.ts +9 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783226868418-AddEnterpriseLicenseInstance.ts +47 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783234451106-AddIncidentAlertReminderRules.ts +211 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783320000000-AddScheduledMaintenanceReminderRules.ts +113 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783330000000-AddRemindWhileScheduledToScheduledMaintenanceReminderRule.ts +20 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783340000000-AddLabelsToIncidentAndAlertReminderRules.ts +69 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Services/AlertReminderRuleService.ts +253 -0
- package/Server/Services/AlertService.ts +106 -0
- package/Server/Services/EnterpriseLicenseInstanceService.ts +10 -0
- package/Server/Services/IncidentReminderRuleService.ts +256 -0
- package/Server/Services/IncidentService.ts +143 -0
- package/Server/Services/Index.ts +8 -0
- package/Server/Services/IoTDeviceService.ts +99 -4
- package/Server/Services/ScheduledMaintenanceReminderRuleService.ts +236 -0
- package/Server/Services/ScheduledMaintenanceService.ts +127 -0
- package/Server/Services/StatusPageService.ts +104 -45
- package/Server/Services/TelemetryExceptionService.ts +123 -0
- package/Server/Services/UserNotificationSettingService.ts +24 -0
- package/Server/Utils/AnalyticsDatabase/Statement.ts +7 -3
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +35 -0
- package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +6 -4
- package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +7 -6
- package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +6 -4
- package/Server/Utils/Telemetry/IoTSnapshotScan.ts +45 -7
- package/Server/Utils/WhatsAppTemplateUtil.ts +10 -0
- package/ServiceRoute.ts +4 -0
- package/Tests/Server/Services/IoTDeviceService.test.ts +280 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +49 -0
- package/Tests/Server/Utils/Monitor/Criteria/TelemetryStepMetricAlias.test.ts +390 -0
- package/Tests/Server/Utils/Telemetry/IoTSnapshotScan.test.ts +202 -0
- package/Tests/Utils/EnterpriseLicenseUsage.test.ts +165 -0
- package/Types/Email/EmailTemplateType.ts +3 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +18 -0
- package/Types/Monitor/MonitorStep.ts +32 -0
- package/Types/NotificationSetting/NotificationSettingEventType.ts +3 -0
- package/Types/Permission.ts +144 -0
- package/Types/Reminder/ReminderStopState.ts +6 -0
- package/Types/Reminder/ScheduledMaintenanceReminderStopState.ts +6 -0
- package/Types/WhatsApp/WhatsAppTemplates.ts +14 -0
- package/UI/Components/EditionLabel/EditionLabel.tsx +172 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +125 -0
- package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/CommonModel.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/ExceptionInstance.js +1 -0
- package/build/dist/Models/AnalyticsModels/ExceptionInstance.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/Log.js +1 -0
- package/build/dist/Models/AnalyticsModels/Log.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/Metric.js +1 -0
- package/build/dist/Models/AnalyticsModels/Metric.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MonitorLog.js +1 -0
- package/build/dist/Models/AnalyticsModels/MonitorLog.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/Span.js +1 -0
- package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Alert.js +103 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertInternalNote.js +2 -0
- package/build/dist/Models/DatabaseModels/AlertInternalNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertReminderRule.js +605 -0
- package/build/dist/Models/DatabaseModels/AlertReminderRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/AlertSeverity.js +2 -0
- package/build/dist/Models/DatabaseModels/AlertSeverity.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertState.js +2 -0
- package/build/dist/Models/DatabaseModels/AlertState.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertStateTimeline.js +2 -0
- package/build/dist/Models/DatabaseModels/AlertStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/EnterpriseLicenseInstance.js +197 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicenseInstance.js.map +1 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +18 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +103 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentInternalNote.js +2 -0
- package/build/dist/Models/DatabaseModels/IncidentInternalNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +2 -0
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentReminderRule.js +605 -0
- package/build/dist/Models/DatabaseModels/IncidentReminderRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncidentSeverity.js +2 -0
- package/build/dist/Models/DatabaseModels/IncidentSeverity.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +2 -0
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.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/Label.js +2 -0
- package/build/dist/Models/DatabaseModels/Label.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js +2 -0
- package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +103 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceReminderRule.js +596 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceReminderRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceState.js +2 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceState.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +2 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +2 -0
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +166 -16
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/EnterpriseLicenseAPI.js +203 -13
- package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
- package/build/dist/Server/API/GlobalConfigAPI.js +62 -15
- package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +74 -31
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +6 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783226868418-AddEnterpriseLicenseInstance.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783226868418-AddEnterpriseLicenseInstance.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783234451106-AddIncidentAlertReminderRules.js +78 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783234451106-AddIncidentAlertReminderRules.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783320000000-AddScheduledMaintenanceReminderRules.js +44 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783320000000-AddScheduledMaintenanceReminderRules.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783330000000-AddRemindWhileScheduledToScheduledMaintenanceReminderRule.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783330000000-AddRemindWhileScheduledToScheduledMaintenanceReminderRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783340000000-AddLabelsToIncidentAndAlertReminderRules.js +30 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783340000000-AddLabelsToIncidentAndAlertReminderRules.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AlertReminderRuleService.js +228 -0
- package/build/dist/Server/Services/AlertReminderRuleService.js.map +1 -0
- package/build/dist/Server/Services/AlertService.js +87 -0
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js +9 -0
- package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js.map +1 -0
- package/build/dist/Server/Services/IncidentReminderRuleService.js +231 -0
- package/build/dist/Server/Services/IncidentReminderRuleService.js.map +1 -0
- package/build/dist/Server/Services/IncidentService.js +116 -0
- package/build/dist/Server/Services/IncidentService.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/IoTDeviceService.js +66 -4
- package/build/dist/Server/Services/IoTDeviceService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js +214 -0
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js.map +1 -0
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +102 -0
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +91 -43
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryExceptionService.js +101 -0
- package/build/dist/Server/Services/TelemetryExceptionService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationSettingService.js +6 -0
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +4 -2
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +29 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +4 -5
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js +6 -5
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +9 -9
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/IoTSnapshotScan.js +33 -2
- package/build/dist/Server/Utils/Telemetry/IoTSnapshotScan.js.map +1 -1
- package/build/dist/Server/Utils/WhatsAppTemplateUtil.js +6 -0
- package/build/dist/Server/Utils/WhatsAppTemplateUtil.js.map +1 -1
- package/build/dist/ServiceRoute.js +1 -0
- package/build/dist/ServiceRoute.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +3 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.js +2 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorStep.js +25 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
- package/build/dist/Types/Permission.js +126 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Reminder/ReminderStopState.js +7 -0
- package/build/dist/Types/Reminder/ReminderStopState.js.map +1 -0
- package/build/dist/Types/Reminder/ScheduledMaintenanceReminderStopState.js +7 -0
- package/build/dist/Types/Reminder/ScheduledMaintenanceReminderStopState.js.map +1 -0
- package/build/dist/Types/WhatsApp/WhatsAppTemplates.js +9 -0
- package/build/dist/Types/WhatsApp/WhatsAppTemplates.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +92 -0
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +83 -0
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -0
- package/package.json +1 -1
|
@@ -11,6 +11,7 @@ import CanAccessIfCanReadOn from "../../Types/Database/CanAccessIfCanReadOn";
|
|
|
11
11
|
import ColumnType from "../../Types/Database/ColumnType";
|
|
12
12
|
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
|
|
13
13
|
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
|
|
14
|
+
import EnableMCP from "../../Types/Database/EnableMCP";
|
|
14
15
|
import EnableWorkflow from "../../Types/Database/EnableWorkflow";
|
|
15
16
|
import TableColumn from "../../Types/Database/TableColumn";
|
|
16
17
|
import TableColumnType from "../../Types/Database/TableColumnType";
|
|
@@ -23,6 +24,7 @@ import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/Statu
|
|
|
23
24
|
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
|
24
25
|
|
|
25
26
|
@EnableDocumentation()
|
|
27
|
+
@EnableMCP()
|
|
26
28
|
@CanAccessIfCanReadOn("scheduledMaintenance")
|
|
27
29
|
@TenantColumn("projectId")
|
|
28
30
|
@TableAccessControl({
|
|
@@ -14,6 +14,7 @@ import ColumnLength from "../../Types/Database/ColumnLength";
|
|
|
14
14
|
import ColumnType from "../../Types/Database/ColumnType";
|
|
15
15
|
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
|
|
16
16
|
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
|
|
17
|
+
import EnableMCP from "../../Types/Database/EnableMCP";
|
|
17
18
|
import EnableWorkflow from "../../Types/Database/EnableWorkflow";
|
|
18
19
|
import SlugifyColumn from "../../Types/Database/SlugifyColumn";
|
|
19
20
|
import TableColumn from "../../Types/Database/TableColumn";
|
|
@@ -35,6 +36,7 @@ import {
|
|
|
35
36
|
} from "typeorm";
|
|
36
37
|
|
|
37
38
|
@EnableDocumentation()
|
|
39
|
+
@EnableMCP()
|
|
38
40
|
@TenantColumn("projectId")
|
|
39
41
|
@CanAccessIfCanReadOn("statusPages")
|
|
40
42
|
@TableBillingAccessControl({
|
|
@@ -375,6 +375,58 @@ const PUBLIC_DASHBOARD_RESOURCES: Record<
|
|
|
375
375
|
},
|
|
376
376
|
};
|
|
377
377
|
|
|
378
|
+
type ResolveDashboardIdOrThrowFunction = (
|
|
379
|
+
dashboardIdOrDomain: string,
|
|
380
|
+
) => Promise<ObjectID>;
|
|
381
|
+
|
|
382
|
+
/*
|
|
383
|
+
* Resolve the :dashboardIdOrDomain route param to a dashboard ID. Accepts
|
|
384
|
+
* either a dashboard ID (UUID) or a verified custom dashboard domain —
|
|
385
|
+
* same contract as the status page overview endpoint.
|
|
386
|
+
*/
|
|
387
|
+
const resolveDashboardIdOrThrow: ResolveDashboardIdOrThrowFunction = async (
|
|
388
|
+
dashboardIdOrDomain: string,
|
|
389
|
+
): Promise<ObjectID> => {
|
|
390
|
+
if (!dashboardIdOrDomain) {
|
|
391
|
+
throw new NotFoundException("Dashboard not found");
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if (dashboardIdOrDomain.includes(".")) {
|
|
395
|
+
const dashboardDomain: DashboardDomain | null =
|
|
396
|
+
await DashboardDomainService.findOneBy({
|
|
397
|
+
query: {
|
|
398
|
+
fullDomain: dashboardIdOrDomain,
|
|
399
|
+
domain: {
|
|
400
|
+
isVerified: true,
|
|
401
|
+
} as any,
|
|
402
|
+
},
|
|
403
|
+
select: {
|
|
404
|
+
dashboardId: true,
|
|
405
|
+
},
|
|
406
|
+
props: {
|
|
407
|
+
isRoot: true,
|
|
408
|
+
},
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
if (!dashboardDomain || !dashboardDomain.dashboardId) {
|
|
412
|
+
throw new NotFoundException("Dashboard not found");
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
return dashboardDomain.dashboardId;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
try {
|
|
419
|
+
ObjectID.validateUUID(dashboardIdOrDomain);
|
|
420
|
+
return new ObjectID(dashboardIdOrDomain);
|
|
421
|
+
} catch (err) {
|
|
422
|
+
logger.error(
|
|
423
|
+
`Error converting dashboardIdOrDomain to ObjectID: ${dashboardIdOrDomain}`,
|
|
424
|
+
);
|
|
425
|
+
logger.error(err);
|
|
426
|
+
throw new NotFoundException("Dashboard not found");
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
|
|
378
430
|
export default class DashboardAPI extends BaseAPI<
|
|
379
431
|
Dashboard,
|
|
380
432
|
DashboardServiceType
|
|
@@ -476,6 +528,111 @@ export default class DashboardAPI extends BaseAPI<
|
|
|
476
528
|
},
|
|
477
529
|
);
|
|
478
530
|
|
|
531
|
+
/*
|
|
532
|
+
* Shared handler for the public overview endpoint. Registered for both
|
|
533
|
+
* POST and GET (machine-readable access for crawlers / AI agents that
|
|
534
|
+
* only issue plain GET requests — discovered via llms.txt on public
|
|
535
|
+
* dashboard URLs) so the authentication and authorization path can
|
|
536
|
+
* never drift between the two methods. It does not read req.body.
|
|
537
|
+
*/
|
|
538
|
+
const overviewHandler: (
|
|
539
|
+
req: ExpressRequest,
|
|
540
|
+
res: ExpressResponse,
|
|
541
|
+
next: NextFunction,
|
|
542
|
+
) => Promise<void> = async (
|
|
543
|
+
req: ExpressRequest,
|
|
544
|
+
res: ExpressResponse,
|
|
545
|
+
next: NextFunction,
|
|
546
|
+
): Promise<void> => {
|
|
547
|
+
try {
|
|
548
|
+
const dashboardId: ObjectID = await resolveDashboardIdOrThrow(
|
|
549
|
+
req.params["dashboardIdOrDomain"] as string,
|
|
550
|
+
);
|
|
551
|
+
|
|
552
|
+
// Check read access (handles public check, IP whitelist, master password)
|
|
553
|
+
const accessResult: {
|
|
554
|
+
hasReadAccess: boolean;
|
|
555
|
+
error?: NotAuthenticatedException | ForbiddenException;
|
|
556
|
+
} = await DashboardService.hasReadAccess({
|
|
557
|
+
dashboardId,
|
|
558
|
+
req,
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
if (!accessResult.hasReadAccess) {
|
|
562
|
+
throw (
|
|
563
|
+
accessResult.error ||
|
|
564
|
+
new BadDataException("Access denied to this dashboard.")
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
const dashboard: Dashboard | null = await DashboardService.findOneById({
|
|
569
|
+
id: dashboardId,
|
|
570
|
+
select: {
|
|
571
|
+
_id: true,
|
|
572
|
+
name: true,
|
|
573
|
+
description: true,
|
|
574
|
+
pageTitle: true,
|
|
575
|
+
pageDescription: true,
|
|
576
|
+
dashboardViewConfig: true,
|
|
577
|
+
},
|
|
578
|
+
props: {
|
|
579
|
+
isRoot: true,
|
|
580
|
+
},
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
if (!dashboard) {
|
|
584
|
+
throw new NotFoundException("Dashboard not found");
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/*
|
|
588
|
+
* Everything below is derived from columns the public /metadata and
|
|
589
|
+
* /view-config endpoints already serve to anonymous viewers — the
|
|
590
|
+
* overview only reshapes them into a single GET-able document.
|
|
591
|
+
*/
|
|
592
|
+
return Response.sendJsonObjectResponse(req, res, {
|
|
593
|
+
_id: dashboard._id?.toString() || "",
|
|
594
|
+
name: dashboard.name || "Dashboard",
|
|
595
|
+
description: dashboard.description || "",
|
|
596
|
+
pageTitle: dashboard.pageTitle || "",
|
|
597
|
+
pageDescription: dashboard.pageDescription || "",
|
|
598
|
+
components: DashboardAPI.buildPublicComponentSummaries(
|
|
599
|
+
dashboard.dashboardViewConfig,
|
|
600
|
+
),
|
|
601
|
+
metricsUsed: Array.from(
|
|
602
|
+
DashboardAPI.collectDashboardMetricNames(
|
|
603
|
+
dashboard.dashboardViewConfig,
|
|
604
|
+
),
|
|
605
|
+
).sort(),
|
|
606
|
+
dashboardViewConfig: dashboard.dashboardViewConfig
|
|
607
|
+
? JSONFunctions.serialize(dashboard.dashboardViewConfig as any)
|
|
608
|
+
: null,
|
|
609
|
+
});
|
|
610
|
+
} catch (err) {
|
|
611
|
+
next(err);
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
const overviewApiPath: string = `${new this.entityType()
|
|
616
|
+
.getCrudApiPath()
|
|
617
|
+
?.toString()}/overview/:dashboardIdOrDomain`;
|
|
618
|
+
|
|
619
|
+
this.router.post(
|
|
620
|
+
overviewApiPath,
|
|
621
|
+
UserMiddleware.getUserMiddleware,
|
|
622
|
+
overviewHandler,
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
/*
|
|
626
|
+
* GET variant of the overview endpoint. Same middleware and same handler
|
|
627
|
+
* as the POST route above — non-public dashboards are rejected for
|
|
628
|
+
* unauthenticated callers exactly as they are on POST.
|
|
629
|
+
*/
|
|
630
|
+
this.router.get(
|
|
631
|
+
overviewApiPath,
|
|
632
|
+
UserMiddleware.getUserMiddleware,
|
|
633
|
+
overviewHandler,
|
|
634
|
+
);
|
|
635
|
+
|
|
479
636
|
// Domain resolution endpoint
|
|
480
637
|
this.router.post(
|
|
481
638
|
`${new this.entityType().getCrudApiPath()?.toString()}/domain`,
|
|
@@ -1079,6 +1236,70 @@ export default class DashboardAPI extends BaseAPI<
|
|
|
1079
1236
|
);
|
|
1080
1237
|
}
|
|
1081
1238
|
|
|
1239
|
+
/*
|
|
1240
|
+
* Build a compact machine-readable summary of the widgets on a dashboard
|
|
1241
|
+
* for the public overview endpoint. Derived entirely from the stored
|
|
1242
|
+
* dashboardViewConfig (already served to public viewers by /view-config) —
|
|
1243
|
+
* this only lifts out the human-meaningful fields (widget type, title,
|
|
1244
|
+
* text, metric names). The config comes straight from a JSON column, so
|
|
1245
|
+
* every field is read defensively.
|
|
1246
|
+
*/
|
|
1247
|
+
private static buildPublicComponentSummaries(
|
|
1248
|
+
dashboardViewConfig: unknown,
|
|
1249
|
+
): Array<JSONObject> {
|
|
1250
|
+
const summaries: Array<JSONObject> = [];
|
|
1251
|
+
|
|
1252
|
+
const components: unknown =
|
|
1253
|
+
dashboardViewConfig && typeof dashboardViewConfig === "object"
|
|
1254
|
+
? (dashboardViewConfig as Record<string, unknown>)["components"]
|
|
1255
|
+
: undefined;
|
|
1256
|
+
|
|
1257
|
+
if (!Array.isArray(components)) {
|
|
1258
|
+
return summaries;
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
for (const component of components) {
|
|
1262
|
+
if (!component || typeof component !== "object") {
|
|
1263
|
+
continue;
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
const componentObject: Record<string, unknown> = component as Record<
|
|
1267
|
+
string,
|
|
1268
|
+
unknown
|
|
1269
|
+
>;
|
|
1270
|
+
|
|
1271
|
+
const argumentsObject: Record<string, unknown> =
|
|
1272
|
+
componentObject["arguments"] &&
|
|
1273
|
+
typeof componentObject["arguments"] === "object"
|
|
1274
|
+
? (componentObject["arguments"] as Record<string, unknown>)
|
|
1275
|
+
: {};
|
|
1276
|
+
|
|
1277
|
+
const getStringArgument: (key: string) => string | null = (
|
|
1278
|
+
key: string,
|
|
1279
|
+
): string | null => {
|
|
1280
|
+
const value: unknown = argumentsObject[key];
|
|
1281
|
+
return typeof value === "string" && value.trim().length > 0
|
|
1282
|
+
? value
|
|
1283
|
+
: null;
|
|
1284
|
+
};
|
|
1285
|
+
|
|
1286
|
+
summaries.push({
|
|
1287
|
+
componentType:
|
|
1288
|
+
typeof componentObject["componentType"] === "string"
|
|
1289
|
+
? componentObject["componentType"]
|
|
1290
|
+
: "",
|
|
1291
|
+
title: getStringArgument("chartTitle") || getStringArgument("title"),
|
|
1292
|
+
description: getStringArgument("chartDescription"),
|
|
1293
|
+
text: getStringArgument("text"),
|
|
1294
|
+
metricNames: Array.from(
|
|
1295
|
+
DashboardAPI.collectDashboardMetricNames(component),
|
|
1296
|
+
).sort(),
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
return summaries;
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1082
1303
|
/*
|
|
1083
1304
|
* Walk a stored dashboard view config and collect every metric name it
|
|
1084
1305
|
* references (chart/value/gauge/table widgets all carry their metric in a
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import EnterpriseLicense from "../../Models/DatabaseModels/EnterpriseLicense";
|
|
2
|
+
import EnterpriseLicenseInstance from "../../Models/DatabaseModels/EnterpriseLicenseInstance";
|
|
2
3
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
3
4
|
import { JSONObject } from "../../Types/JSON";
|
|
5
|
+
import PartialEntity from "../../Types/Database/PartialEntity";
|
|
6
|
+
import EnterpriseLicenseInstanceSummary from "../../Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary";
|
|
7
|
+
import EnterpriseLicenseUsageUtil from "../../Utils/EnterpriseLicense/EnterpriseLicenseUsage";
|
|
8
|
+
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
9
|
+
import ObjectID from "../../Types/ObjectID";
|
|
10
|
+
import PositiveNumber from "../../Types/PositiveNumber";
|
|
11
|
+
import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
4
12
|
import EnterpriseLicenseService, {
|
|
5
13
|
Service as EnterpriseLicenseServiceType,
|
|
6
14
|
} from "../Services/EnterpriseLicenseService";
|
|
15
|
+
import EnterpriseLicenseInstanceService from "../Services/EnterpriseLicenseInstanceService";
|
|
7
16
|
import UserMiddleware from "../Middleware/UserAuthorization";
|
|
8
17
|
import JSONWebToken from "../Utils/JsonWebToken";
|
|
9
18
|
import OneUptimeDate from "../../Types/Date";
|
|
@@ -16,6 +25,23 @@ import {
|
|
|
16
25
|
import BaseAPI from "./BaseAPI";
|
|
17
26
|
// import { Host } from "../EnvironmentConfig";
|
|
18
27
|
|
|
28
|
+
export interface LicenseInstanceUpsert {
|
|
29
|
+
licenseId: ObjectID;
|
|
30
|
+
instanceId: string;
|
|
31
|
+
host: string | undefined;
|
|
32
|
+
// Usage fields are only set on report-user-count, not on validate.
|
|
33
|
+
userCount?: number | undefined;
|
|
34
|
+
userEmailHashes?: Array<string> | undefined;
|
|
35
|
+
lastReportedAt?: Date | undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
* Bounds how many instance rows one license key can register. Real customers
|
|
40
|
+
* run a handful of instances; this stops a leaked key from being used to
|
|
41
|
+
* fill the table with junk rows.
|
|
42
|
+
*/
|
|
43
|
+
const MAX_INSTANCES_PER_LICENSE: number = 100;
|
|
44
|
+
|
|
19
45
|
export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
20
46
|
EnterpriseLicense,
|
|
21
47
|
EnterpriseLicenseServiceType
|
|
@@ -50,6 +76,7 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
50
76
|
licenseKey: licenseKey,
|
|
51
77
|
},
|
|
52
78
|
select: {
|
|
79
|
+
_id: true,
|
|
53
80
|
companyName: true,
|
|
54
81
|
expiresAt: true,
|
|
55
82
|
licenseKey: true,
|
|
@@ -80,6 +107,27 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
80
107
|
throw new BadDataException("License key has expired");
|
|
81
108
|
}
|
|
82
109
|
|
|
110
|
+
/*
|
|
111
|
+
* The validating instance sends its instanceId and host so it
|
|
112
|
+
* shows up in the instance list right away (usage is reported
|
|
113
|
+
* later by the daily job on the instance).
|
|
114
|
+
*/
|
|
115
|
+
const instanceId: string = this.parseShortText(
|
|
116
|
+
req.body["instanceId"],
|
|
117
|
+
);
|
|
118
|
+
const instanceHost: string = this.parseShortText(req.body["host"]);
|
|
119
|
+
|
|
120
|
+
if (instanceId) {
|
|
121
|
+
await this.upsertLicenseInstance({
|
|
122
|
+
licenseId: license.id!,
|
|
123
|
+
instanceId: instanceId,
|
|
124
|
+
host: instanceHost || undefined,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const instances: Array<EnterpriseLicenseInstance> =
|
|
129
|
+
await this.findLicenseInstances(license.id!);
|
|
130
|
+
|
|
83
131
|
const payload: JSONObject = {
|
|
84
132
|
companyName: license.companyName || "",
|
|
85
133
|
expiresAt: license.expiresAt.toISOString(),
|
|
@@ -105,6 +153,7 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
105
153
|
userCountUpdatedAt: license.userCountUpdatedAt
|
|
106
154
|
? license.userCountUpdatedAt.toISOString()
|
|
107
155
|
: null,
|
|
156
|
+
instances: this.getInstanceSummaries(instances),
|
|
108
157
|
token,
|
|
109
158
|
});
|
|
110
159
|
} catch (err) {
|
|
@@ -158,23 +207,67 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
158
207
|
|
|
159
208
|
const reportedAt: Date = OneUptimeDate.getCurrentDate();
|
|
160
209
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
210
|
+
const instanceId: string = this.parseShortText(
|
|
211
|
+
req.body["instanceId"],
|
|
212
|
+
);
|
|
213
|
+
const instanceHost: string = this.parseShortText(req.body["host"]);
|
|
214
|
+
const userEmailHashes: Array<string> =
|
|
215
|
+
EnterpriseLicenseUsageUtil.sanitizeUserEmailHashes(
|
|
216
|
+
req.body["userEmailHashes"],
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
if (instanceId) {
|
|
220
|
+
/*
|
|
221
|
+
* Multi-instance report: track usage per instance and count
|
|
222
|
+
* users uniquely across all instances of this license.
|
|
223
|
+
*/
|
|
224
|
+
await this.upsertLicenseInstance({
|
|
225
|
+
licenseId: license.id!,
|
|
226
|
+
instanceId: instanceId,
|
|
227
|
+
host: instanceHost || undefined,
|
|
228
|
+
userCount: userCount,
|
|
229
|
+
userEmailHashes: userEmailHashes,
|
|
230
|
+
lastReportedAt: reportedAt,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const instances: Array<EnterpriseLicenseInstance> =
|
|
235
|
+
await this.findLicenseInstances(license.id!);
|
|
236
|
+
|
|
237
|
+
let currentUserCount: number = userCount;
|
|
238
|
+
|
|
239
|
+
if (instances.length > 0) {
|
|
240
|
+
currentUserCount = EnterpriseLicenseUsageUtil.getUniqueUserCount(
|
|
241
|
+
instances,
|
|
242
|
+
reportedAt,
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/*
|
|
247
|
+
* Legacy reports (no instanceId) only drive the license-wide count
|
|
248
|
+
* while no instance has registered — otherwise they would stomp
|
|
249
|
+
* the deduplicated multi-instance count.
|
|
250
|
+
*/
|
|
251
|
+
if (instanceId || instances.length === 0) {
|
|
252
|
+
await EnterpriseLicenseService.updateOneById({
|
|
253
|
+
id: license.id!,
|
|
254
|
+
data: {
|
|
255
|
+
currentUserCount: currentUserCount,
|
|
256
|
+
userCountUpdatedAt: reportedAt,
|
|
257
|
+
},
|
|
258
|
+
props: {
|
|
259
|
+
isRoot: true,
|
|
260
|
+
ignoreHooks: true,
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
}
|
|
172
264
|
|
|
173
265
|
return Response.sendJsonObjectResponse(req, res, {
|
|
174
|
-
currentUserCount:
|
|
266
|
+
currentUserCount: currentUserCount,
|
|
175
267
|
userCountUpdatedAt: reportedAt.toISOString(),
|
|
176
268
|
userLimit:
|
|
177
269
|
typeof license.userLimit === "number" ? license.userLimit : null,
|
|
270
|
+
instances: this.getInstanceSummaries(instances),
|
|
178
271
|
});
|
|
179
272
|
} catch (err) {
|
|
180
273
|
next(err);
|
|
@@ -182,4 +275,178 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
182
275
|
},
|
|
183
276
|
);
|
|
184
277
|
}
|
|
278
|
+
|
|
279
|
+
private parseShortText(value: unknown): string {
|
|
280
|
+
if (typeof value !== "string") {
|
|
281
|
+
return "";
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return value.trim().substring(0, 100);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
private async findLicenseInstances(
|
|
288
|
+
licenseId: ObjectID,
|
|
289
|
+
): Promise<Array<EnterpriseLicenseInstance>> {
|
|
290
|
+
return EnterpriseLicenseInstanceService.findBy({
|
|
291
|
+
query: {
|
|
292
|
+
enterpriseLicenseId: licenseId,
|
|
293
|
+
},
|
|
294
|
+
select: {
|
|
295
|
+
_id: true,
|
|
296
|
+
instanceId: true,
|
|
297
|
+
host: true,
|
|
298
|
+
userCount: true,
|
|
299
|
+
userEmailHashes: true,
|
|
300
|
+
lastReportedAt: true,
|
|
301
|
+
},
|
|
302
|
+
sort: {
|
|
303
|
+
createdAt: SortOrder.Ascending,
|
|
304
|
+
},
|
|
305
|
+
skip: 0,
|
|
306
|
+
limit: LIMIT_MAX,
|
|
307
|
+
props: {
|
|
308
|
+
isRoot: true,
|
|
309
|
+
},
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
private getInstanceSummaries(
|
|
314
|
+
instances: Array<EnterpriseLicenseInstance>,
|
|
315
|
+
): Array<EnterpriseLicenseInstanceSummary> {
|
|
316
|
+
return instances.map(
|
|
317
|
+
(
|
|
318
|
+
instance: EnterpriseLicenseInstance,
|
|
319
|
+
): EnterpriseLicenseInstanceSummary => {
|
|
320
|
+
return {
|
|
321
|
+
instanceId: instance.instanceId || "",
|
|
322
|
+
host: instance.host || null,
|
|
323
|
+
userCount:
|
|
324
|
+
typeof instance.userCount === "number" ? instance.userCount : null,
|
|
325
|
+
lastReportedAt: instance.lastReportedAt
|
|
326
|
+
? instance.lastReportedAt.toISOString()
|
|
327
|
+
: null,
|
|
328
|
+
};
|
|
329
|
+
},
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
private async upsertLicenseInstance(
|
|
334
|
+
data: LicenseInstanceUpsert,
|
|
335
|
+
): Promise<void> {
|
|
336
|
+
const updated: boolean = await this.updateLicenseInstanceIfExists(data);
|
|
337
|
+
|
|
338
|
+
if (updated) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const instanceCount: PositiveNumber =
|
|
343
|
+
await EnterpriseLicenseInstanceService.countBy({
|
|
344
|
+
query: {
|
|
345
|
+
enterpriseLicenseId: data.licenseId,
|
|
346
|
+
},
|
|
347
|
+
props: {
|
|
348
|
+
isRoot: true,
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
if (instanceCount.toNumber() >= MAX_INSTANCES_PER_LICENSE) {
|
|
353
|
+
throw new BadDataException(
|
|
354
|
+
"Too many instances are registered for this license. Please contact support@oneuptime.com.",
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const newInstance: EnterpriseLicenseInstance =
|
|
359
|
+
new EnterpriseLicenseInstance();
|
|
360
|
+
newInstance.enterpriseLicenseId = data.licenseId;
|
|
361
|
+
newInstance.instanceId = data.instanceId;
|
|
362
|
+
|
|
363
|
+
if (data.host !== undefined) {
|
|
364
|
+
newInstance.host = data.host;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (data.userCount !== undefined) {
|
|
368
|
+
newInstance.userCount = data.userCount;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (data.userEmailHashes !== undefined) {
|
|
372
|
+
newInstance.userEmailHashes = data.userEmailHashes;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (data.lastReportedAt !== undefined) {
|
|
376
|
+
newInstance.lastReportedAt = data.lastReportedAt;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
try {
|
|
380
|
+
await EnterpriseLicenseInstanceService.create({
|
|
381
|
+
data: newInstance,
|
|
382
|
+
props: {
|
|
383
|
+
isRoot: true,
|
|
384
|
+
},
|
|
385
|
+
});
|
|
386
|
+
} catch (err) {
|
|
387
|
+
/*
|
|
388
|
+
* A concurrent request created the row between our check and this
|
|
389
|
+
* insert — the unique index on (enterpriseLicenseId, instanceId)
|
|
390
|
+
* rejected the duplicate. Apply the report as an update instead.
|
|
391
|
+
*/
|
|
392
|
+
const retried: boolean = await this.updateLicenseInstanceIfExists(data);
|
|
393
|
+
|
|
394
|
+
if (!retried) {
|
|
395
|
+
throw err;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
private async updateLicenseInstanceIfExists(
|
|
401
|
+
data: LicenseInstanceUpsert,
|
|
402
|
+
): Promise<boolean> {
|
|
403
|
+
const existingInstance: EnterpriseLicenseInstance | null =
|
|
404
|
+
await EnterpriseLicenseInstanceService.findOneBy({
|
|
405
|
+
query: {
|
|
406
|
+
enterpriseLicenseId: data.licenseId,
|
|
407
|
+
instanceId: data.instanceId,
|
|
408
|
+
},
|
|
409
|
+
select: {
|
|
410
|
+
_id: true,
|
|
411
|
+
},
|
|
412
|
+
props: {
|
|
413
|
+
isRoot: true,
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
if (!existingInstance) {
|
|
418
|
+
return false;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const updateData: PartialEntity<EnterpriseLicenseInstance> = {};
|
|
422
|
+
|
|
423
|
+
if (data.host !== undefined) {
|
|
424
|
+
updateData.host = data.host;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (data.userCount !== undefined) {
|
|
428
|
+
updateData.userCount = data.userCount;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
if (data.userEmailHashes !== undefined) {
|
|
432
|
+
updateData.userEmailHashes = data.userEmailHashes;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (data.lastReportedAt !== undefined) {
|
|
436
|
+
updateData.lastReportedAt = data.lastReportedAt;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if (Object.keys(updateData).length > 0) {
|
|
440
|
+
await EnterpriseLicenseInstanceService.updateOneById({
|
|
441
|
+
id: existingInstance.id!,
|
|
442
|
+
data: updateData,
|
|
443
|
+
props: {
|
|
444
|
+
isRoot: true,
|
|
445
|
+
ignoreHooks: true,
|
|
446
|
+
},
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
return true;
|
|
451
|
+
}
|
|
185
452
|
}
|