@oneuptime/common 14.0.8 → 14.0.10
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/AutoRemediationSuggestion.ts +60 -0
- package/Models/DatabaseModels/CephCluster.ts +213 -0
- package/Models/DatabaseModels/DatabaseServer.ts +213 -0
- package/Models/DatabaseModels/DockerHost.ts +213 -0
- package/Models/DatabaseModels/DockerSwarmCluster.ts +213 -0
- package/Models/DatabaseModels/GlobalConfig.ts +1 -1
- package/Models/DatabaseModels/Host.ts +213 -0
- package/Models/DatabaseModels/Index.ts +4 -0
- package/Models/DatabaseModels/KubernetesAiAgent.ts +364 -0
- package/Models/DatabaseModels/KubernetesCluster.ts +3 -3
- package/Models/DatabaseModels/PodmanHost.ts +213 -0
- package/Models/DatabaseModels/Project.ts +55 -5
- package/Models/DatabaseModels/ProxmoxCluster.ts +213 -0
- package/Models/DatabaseModels/ProxmoxResource.ts +49 -1
- package/Models/DatabaseModels/ResourceAiAgent.ts +419 -0
- package/Models/DatabaseModels/RunnerJob.ts +219 -0
- package/Models/DatabaseModels/TeamComplianceSetting.ts +143 -2
- package/Models/DatabaseModels/VMwareVCenter.ts +213 -0
- package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +17 -0
- package/Server/API/AIChatAPI.ts +6 -3
- package/Server/API/AIInvestigationAPI.ts +17 -10
- package/Server/API/AutoRemediationAPI.ts +598 -25
- package/Server/API/KubernetesClusterAiAccessAPI.ts +623 -21
- package/Server/API/MicrosoftTeamsAPI.ts +93 -14
- package/Server/API/ProxmoxResourceAPI.ts +244 -14
- package/Server/API/ResourceAiAccessAPI.ts +1669 -0
- package/Server/Infrastructure/GlobalCache.ts +32 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.ts +99 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.ts +137 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.ts +42 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.ts +423 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
- package/Server/Infrastructure/Semaphore.ts +22 -0
- package/Server/Middleware/TelemetryIngest.ts +51 -18
- package/Server/Services/AIService.ts +70 -1
- package/Server/Services/AlertService.ts +352 -11
- package/Server/Services/AlertSeverityService.ts +65 -15
- package/Server/Services/AnalyticsDatabaseService.ts +45 -1
- package/Server/Services/AutoRemediationRuleEngineService.ts +940 -112
- package/Server/Services/AutoRemediationRuleService.ts +1 -1
- package/Server/Services/CephClusterService.ts +109 -1
- package/Server/Services/DatabaseServerService.ts +116 -1
- package/Server/Services/DockerHostService.ts +109 -1
- package/Server/Services/DockerSwarmClusterService.ts +113 -1
- package/Server/Services/HostService.ts +126 -4
- package/Server/Services/IncidentService.ts +280 -104
- package/Server/Services/IncidentSeverityService.ts +66 -15
- package/Server/Services/KubernetesAiAgentJobService.ts +185 -0
- package/Server/Services/KubernetesAiAgentService.ts +1634 -0
- package/Server/Services/KubernetesClusterAiAccessService.ts +1118 -451
- package/Server/Services/KubernetesClusterService.ts +129 -21
- package/Server/Services/MetricRecordingRuleService.ts +47 -0
- package/Server/Services/PodmanHostService.ts +109 -1
- package/Server/Services/ProjectService.ts +32 -0
- package/Server/Services/ProxmoxClusterService.ts +110 -1
- package/Server/Services/ProxmoxResourceService.ts +322 -5
- package/Server/Services/ResourceAiAccessService.ts +1439 -0
- package/Server/Services/ResourceAiAgentJobService.ts +202 -0
- package/Server/Services/ResourceAiAgentService.ts +2432 -0
- package/Server/Services/RunnerJobService.ts +852 -108
- package/Server/Services/RunnerService.ts +1 -1
- package/Server/Services/ScheduledMaintenanceService.ts +737 -1
- package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +414 -56
- package/Server/Services/TeamComplianceSettingService.ts +1125 -9
- package/Server/Services/TelemetryUsageBillingService.ts +28 -0
- package/Server/Services/TraceRecordingRuleService.ts +33 -0
- package/Server/Services/VMwareVCenterService.ts +110 -1
- package/Server/Utils/AI/ClusterAccess/ClusterAccessContext.ts +67 -9
- package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +39 -10
- package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +14 -3
- package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +1475 -51
- package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +1000 -43
- package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +25 -1
- package/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.ts +577 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAccessContext.ts +271 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.ts +45 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.ts +964 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.ts +333 -0
- package/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.ts +873 -0
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +120 -7
- package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +72 -5
- package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +72 -5
- package/Server/Utils/AI/SRE/IncidentPostmortemRunner.ts +40 -8
- package/Server/Utils/AI/SRE/InvestigationEligibility.ts +13 -2
- package/Server/Utils/AI/SRE/InvestigationGrader.ts +1 -1
- package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +402 -14
- package/Server/Utils/AutoRemediation/RemediationVerifier.ts +35 -2
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +9 -1
- package/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.ts +920 -0
- package/Server/Utils/SessionReplay/SessionReplayUsage.ts +84 -6
- package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +133 -7
- package/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.ts +58 -4
- package/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.ts +447 -0
- package/Server/Utils/Telemetry/ProxmoxNativePush.ts +903 -0
- package/Server/Utils/Telemetry/TelemetryEntity.ts +87 -27
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +35 -15
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.ts +33 -15
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.ts +21 -1
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +298 -224
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +35 -15
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.ts +389 -175
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +1073 -213
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.ts +163 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.ts +396 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.ts +418 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.ts +152 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.ts +251 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.ts +214 -0
- package/Tests/App/AdminDashboard/RowActionPlacementOverrides.test.tsx +278 -0
- package/Tests/App/Dashboard/AIChatChartWidgetZoom.test.tsx +738 -0
- package/Tests/App/Dashboard/AIFeaturesSettingsPointers.test.tsx +147 -0
- package/Tests/App/Dashboard/AIInsightsKubernetesClusterPage.test.tsx +1523 -0
- package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +463 -3
- package/Tests/App/Dashboard/AffectedResourcesPickerDropdownPlacement.test.tsx +958 -0
- package/Tests/App/Dashboard/AffectedResourcesPickerFocusLeave.test.tsx +595 -0
- package/Tests/App/Dashboard/AskAiAvailability.test.ts +20 -3
- package/Tests/App/Dashboard/AskAiDisabled.test.tsx +8 -3
- package/Tests/App/Dashboard/CephRateChartReload.test.tsx +1456 -0
- package/Tests/App/Dashboard/CephTimeRangeZoom.test.tsx +1229 -0
- package/Tests/App/Dashboard/ChartCardTimeRangeZoom.test.tsx +151 -0
- package/Tests/App/Dashboard/ChartCardZoomAffordances.test.tsx +257 -0
- package/Tests/App/Dashboard/ChartRefetchFrame.test.tsx +141 -0
- package/Tests/App/Dashboard/ChartZoomHarness.tsx +249 -0
- package/Tests/App/Dashboard/ChartZoomStandIn.tsx +131 -0
- package/Tests/App/Dashboard/CloudServerlessSlowLoads.test.tsx +628 -0
- package/Tests/App/Dashboard/CloudServerlessTimeRangeZoom.test.tsx +607 -0
- package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +184 -19
- package/Tests/App/Dashboard/CompanionMetricsTabZoom.test.tsx +632 -0
- package/Tests/App/Dashboard/ContainerChartZoomStandIn.tsx +195 -0
- package/Tests/App/Dashboard/ContainerHostOverviewSlowLoads.test.tsx +542 -0
- package/Tests/App/Dashboard/ContainerHostOverviewTimeRangeZoom.test.tsx +848 -0
- package/Tests/App/Dashboard/ContainerMetricsTimeRangeZoom.test.tsx +561 -0
- package/Tests/App/Dashboard/DashboardBoardWideZoomShell.test.tsx +1147 -0
- package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +3 -2
- package/Tests/App/Dashboard/DashboardHistogramWidgetDragCursor.test.tsx +399 -0
- package/Tests/App/Dashboard/DashboardHistogramWidgetZoom.test.tsx +985 -0
- package/Tests/App/Dashboard/DashboardHistogramWidgetZoomHint.test.tsx +803 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +1 -0
- package/Tests/App/Dashboard/DashboardSettingsPreviewZoom.test.tsx +679 -0
- package/Tests/App/Dashboard/DashboardSloAndDataSourceChartZoom.test.tsx +881 -0
- package/Tests/App/Dashboard/DashboardTraceStatusWidgets.test.tsx +878 -0
- package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +18 -6
- package/Tests/App/Dashboard/DatabaseMetricChartModalTimeRangeZoom.test.tsx +442 -0
- package/Tests/App/Dashboard/DatabaseOverviewTimeRangeZoom.test.tsx +831 -0
- package/Tests/App/Dashboard/DatabaseServerComponents.test.tsx +43 -0
- package/Tests/App/Dashboard/DockerSwarmInsightsTimeRangeZoom.test.tsx +524 -0
- package/Tests/App/Dashboard/DockerSwarmRateChartRefresh.test.tsx +259 -0
- package/Tests/App/Dashboard/EdgeDetailPanelHistory.test.tsx +763 -0
- package/Tests/App/Dashboard/EdgeDetailPanelTimeRangeZoom.test.tsx +547 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsCases.tsx +565 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsKathmandu.test.tsx +73 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsKolkata.test.tsx +74 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsNewYork.test.tsx +72 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsUtc.test.tsx +72 -0
- package/Tests/App/Dashboard/EmbeddedMetricCardRefresh.test.tsx +310 -0
- package/Tests/App/Dashboard/EmbeddedMetricCardTimeRangeZoom.test.tsx +536 -0
- package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +3 -1
- package/Tests/App/Dashboard/EscalationRuleRowActions.test.tsx +660 -0
- package/Tests/App/Dashboard/EventNotes.test.tsx +2 -2
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +587 -13
- package/Tests/App/Dashboard/EventOverviewSnapshotExplorerZoom.test.tsx +1139 -0
- package/Tests/App/Dashboard/EventOverviewSnapshotZoomAcrossTabs.test.tsx +1057 -0
- package/Tests/App/Dashboard/EventOverviewTelemetrySnapshotZoom.test.tsx +757 -0
- package/Tests/App/Dashboard/ExceptionOccurrenceTrendZoom.test.tsx +675 -0
- package/Tests/App/Dashboard/ExceptionOccurrencesZoomSurvivesViewSwitch.test.tsx +405 -0
- package/Tests/App/Dashboard/ExceptionSignalPages.test.tsx +67 -3
- package/Tests/App/Dashboard/ExceptionTablesSpanStatus.test.tsx +515 -0
- package/Tests/App/Dashboard/ExplorerOwnZoomRegression.test.tsx +739 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisCases.tsx +461 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisKathmandu.test.tsx +25 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisKolkata.test.tsx +25 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisNewYork.test.tsx +25 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisUtc.test.tsx +24 -0
- package/Tests/App/Dashboard/FlowTopTalkersZoomRefetch.test.tsx +722 -0
- package/Tests/App/Dashboard/FlowViewportGuard.test.tsx +2526 -0
- package/Tests/App/Dashboard/HostPagesSlowLoads.test.tsx +872 -0
- package/Tests/App/Dashboard/HostPagesTimeRangeZoom.test.tsx +1208 -0
- package/Tests/App/Dashboard/IncidentRootCauseTimeRangeZoom.test.tsx +358 -0
- package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +100 -9
- package/Tests/App/Dashboard/InfrastructureMetricsTabTimeRangeZoom.test.tsx +485 -0
- package/Tests/App/Dashboard/InvestigationDrawerCompanionZoom.test.tsx +655 -0
- package/Tests/App/Dashboard/InvestigationDrawerZoom.test.tsx +830 -0
- package/Tests/App/Dashboard/InvestigationInfrastructureTools.test.tsx +506 -0
- package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +338 -2
- package/Tests/App/Dashboard/InvoicesPayInvoice.test.tsx +454 -16
- package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +799 -819
- package/Tests/App/Dashboard/KubernetesClusterAiAgentOverviewCard.test.tsx +367 -0
- package/Tests/App/Dashboard/KubernetesClusterAiAgentStatus.test.ts +1202 -0
- package/Tests/App/Dashboard/KubernetesClusterAiDocumentationMarkdown.test.ts +106 -0
- package/Tests/App/Dashboard/KubernetesClusterAiNavigation.test.tsx +354 -0
- package/Tests/App/Dashboard/KubernetesClusterAiPage.test.tsx +1884 -2054
- package/Tests/App/Dashboard/KubernetesClusterAiPageServerParity.test.ts +478 -179
- package/Tests/App/Dashboard/KubernetesClusterMetricTooltips.test.ts +50 -0
- package/Tests/App/Dashboard/KubernetesClusterOverviewTooltips.test.tsx +2 -1
- package/Tests/App/Dashboard/KubernetesClusterOverviewZoom.test.tsx +1217 -0
- package/Tests/App/Dashboard/KubernetesClusterPagesZoom.test.tsx +731 -0
- package/Tests/App/Dashboard/KubernetesCostsLoadRecovery.test.tsx +869 -0
- package/Tests/App/Dashboard/KubernetesCostsZoom.test.tsx +1214 -0
- package/Tests/App/Dashboard/KubernetesCostsZoomExactHours.test.tsx +692 -0
- package/Tests/App/Dashboard/KubernetesNetworkThroughputReload.test.tsx +902 -0
- package/Tests/App/Dashboard/KubernetesNetworkZoomBucketEdges.test.tsx +571 -0
- package/Tests/App/Dashboard/KubernetesOverviewZoomBucketEdges.test.tsx +697 -0
- package/Tests/App/Dashboard/KubernetesResourceMetricsTabZoom.test.tsx +633 -0
- package/Tests/App/Dashboard/LogsExplorerTimeRangeZoom.test.tsx +470 -0
- package/Tests/App/Dashboard/LogsInsightsTimeRangeZoom.test.tsx +948 -0
- package/Tests/App/Dashboard/LogsViewerPinnedWindowZoom.test.tsx +486 -0
- package/Tests/App/Dashboard/MetricChartsBucketInspectorDoubleClick.test.tsx +1001 -0
- package/Tests/App/Dashboard/MetricExplorerInvestigationAutoRefresh.test.tsx +514 -0
- package/Tests/App/Dashboard/MetricExplorerSavedViewZoomRoundTrip.test.tsx +581 -0
- package/Tests/App/Dashboard/MetricExplorerTimeRangeZoom.test.tsx +1162 -0
- package/Tests/App/Dashboard/MetricMonitorPreviewZoomLabel.test.ts +72 -0
- package/Tests/App/Dashboard/MetricRowSparklineTimeRangeZoom.test.tsx +204 -0
- package/Tests/App/Dashboard/MetricViewFirstResultLands.test.tsx +408 -0
- package/Tests/App/Dashboard/MetricViewOwnZoomResetPlacement.test.tsx +952 -0
- package/Tests/App/Dashboard/MetricViewTimeRange.test.ts +139 -0
- package/Tests/App/Dashboard/MetricViewTimeRangeZoom.test.tsx +556 -0
- package/Tests/App/Dashboard/MonitorMetricsChartWrappersZoom.test.tsx +552 -0
- package/Tests/App/Dashboard/MonitorMetricsTabsTimeRangeZoom.test.tsx +740 -0
- package/Tests/App/Dashboard/MonitorOverviewChartsTimeRangeZoom.test.tsx +735 -0
- package/Tests/App/Dashboard/MonitorStepPreviewsTimeRangeZoom.test.tsx +835 -0
- package/Tests/App/Dashboard/NetworkDeviceTimeRangeZoom.test.tsx +1115 -0
- package/Tests/App/Dashboard/OnCallPreventionGuards.test.tsx +186 -17
- package/Tests/App/Dashboard/OnCallRulesDeleteGuard.test.tsx +155 -46
- package/Tests/App/Dashboard/PasskeySettings.test.tsx +87 -2
- package/Tests/App/Dashboard/ProjectAISettingsPages.test.tsx +884 -0
- package/Tests/App/Dashboard/ProxmoxNodeRemove.test.tsx +621 -0
- package/Tests/App/Dashboard/ProxmoxOverviewSlowLoads.test.tsx +584 -0
- package/Tests/App/Dashboard/ProxmoxPagesTimeRangeZoom.test.tsx +823 -0
- package/Tests/App/Dashboard/ProxmoxRateChartReload.test.tsx +1253 -0
- package/Tests/App/Dashboard/PublicDashboardBoardWideZoom.test.tsx +605 -0
- package/Tests/App/Dashboard/RealRowsLineChart.tsx +250 -0
- package/Tests/App/Dashboard/RechartsHostsPlotCursor.test.tsx +513 -0
- package/Tests/App/Dashboard/RemediationSuggestionCardDescription.test.tsx +209 -0
- package/Tests/App/Dashboard/RemediationSuggestionCardResource.test.tsx +317 -0
- package/Tests/App/Dashboard/ResourceAiAccessSettingsUtil.test.ts +921 -0
- package/Tests/App/Dashboard/ResourceAiAgentInstall.test.ts +860 -0
- package/Tests/App/Dashboard/ResourceAiAgentPage.test.tsx +1721 -0
- package/Tests/App/Dashboard/ResourceAiAgentStatus.test.ts +1002 -0
- package/Tests/App/Dashboard/ResourceAiInsightsPage.test.tsx +931 -0
- package/Tests/App/Dashboard/ResourceAiNavigation.test.tsx +575 -0
- package/Tests/App/Dashboard/RowActionPlacementOverrides.test.tsx +865 -0
- package/Tests/App/Dashboard/RumOverviewTimeRangeZoom.test.tsx +877 -0
- package/Tests/App/Dashboard/RunbookStepTypeMaps.test.ts +38 -7
- package/Tests/App/Dashboard/RunnerKubernetesAgentForm.test.tsx +20 -4
- package/Tests/App/Dashboard/RunnerSupersededByAiAgentNote.test.tsx +296 -0
- package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +146 -36
- package/Tests/App/Dashboard/ServiceDatabaseSlowLoads.test.tsx +1166 -0
- package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +1243 -104
- package/Tests/App/Dashboard/ServiceOverviewTimeRangeZoom.test.tsx +792 -0
- package/Tests/App/Dashboard/SloBudgetBurnDownZoom.test.tsx +771 -0
- package/Tests/App/Dashboard/SloBudgetBurnDownZoomAffordances.test.tsx +380 -0
- package/Tests/App/Dashboard/SloEventMetricsBarChartZoom.test.tsx +369 -0
- package/Tests/App/Dashboard/SloHistoryChartsTimeRangeZoom.test.tsx +694 -0
- package/Tests/App/Dashboard/SloHistoryChartsZoomAffordances.test.tsx +497 -0
- package/Tests/App/Dashboard/SloMetricsTimeRangeZoom.test.tsx +541 -0
- package/Tests/App/Dashboard/SlowLoadHarness.ts +123 -0
- package/Tests/App/Dashboard/SnapshotExplorerPrimaryZoom.test.tsx +1194 -0
- package/Tests/App/Dashboard/SnapshotViewerPinnedWindow.test.tsx +620 -0
- package/Tests/App/Dashboard/TelemetrySnapshotPanelTimeRangeZoom.test.tsx +765 -0
- package/Tests/App/Dashboard/TelemetrySnapshotZoom.test.tsx +516 -0
- package/Tests/App/Dashboard/TelemetrySnapshotZoomAcrossTabs.test.tsx +827 -0
- package/Tests/App/Dashboard/TimeRangeZoomPageHarness.tsx +463 -0
- package/Tests/App/Dashboard/TraceChartEditorStatusSplit.test.tsx +543 -0
- package/Tests/App/Dashboard/TraceStatusPresentation.test.tsx +967 -0
- package/Tests/App/Dashboard/TraceTimelineMinimapZoom.test.tsx +315 -0
- package/Tests/App/Dashboard/TracesAnalyticsStatusSplit.test.tsx +778 -0
- package/Tests/App/Dashboard/TracesAnalyticsViewZoom.test.tsx +349 -0
- package/Tests/App/Dashboard/TracesExplorerTimeRangeZoom.test.tsx +551 -0
- package/Tests/App/Dashboard/TracesStatusChartAndFacet.test.tsx +687 -0
- package/Tests/App/Dashboard/TracesViewerStaleResponses.test.tsx +458 -0
- package/Tests/App/Dashboard/UptimeStripsExcludedFromZoom.test.tsx +406 -0
- package/Tests/App/Dashboard/VMwareOverviewSlowLoads.test.tsx +535 -0
- package/Tests/App/Dashboard/VMwarePagesTimeRangeZoom.test.tsx +606 -0
- package/Tests/App/Dashboard/ValueWidgetSparklineStaleHover.test.tsx +1292 -0
- package/Tests/App/Dashboard/ValueWidgetSparklineZoom.test.tsx +765 -0
- package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +98 -0
- package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +33 -1
- package/Tests/Models/DatabaseModels/KubernetesAiAgentModel.test.ts +295 -0
- package/Tests/Models/DatabaseModels/ResourceAiAccessColumns.test.ts +738 -0
- package/Tests/Models/DatabaseModels/ResourceAiAgentModel.test.ts +842 -0
- package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +347 -0
- package/Tests/Server/API/AIChatRouteAuthorization.test.ts +58 -0
- package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +1 -1
- package/Tests/Server/API/AIInvestigationAPI.test.ts +123 -45
- package/Tests/Server/API/AutoRemediationApproveClusterRound.test.ts +1329 -0
- package/Tests/Server/API/AutoRemediationApproveKubectlRecheck.test.ts +25 -2
- package/Tests/Server/API/AutoRemediationApproveResourceRound.test.ts +835 -0
- package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +2 -0
- package/Tests/Server/API/KubernetesClusterAiAccessAPIAgent.test.ts +903 -0
- package/Tests/Server/API/MicrosoftTeamsChatsRefreshRoute.test.ts +667 -0
- package/Tests/Server/API/MicrosoftTeamsManifest.test.ts +294 -6
- package/Tests/Server/API/ProxmoxResourceAPIRemoveNode.test.ts +1932 -0
- package/Tests/Server/API/ResourceAiAccessAPI.test.ts +2730 -0
- package/Tests/Server/Infrastructure/GlobalCache.test.ts +195 -0
- package/Tests/Server/Infrastructure/Postgres/AddDatabaseServerTablesMigration.test.ts +60 -0
- package/Tests/Server/Infrastructure/Postgres/AddKubernetesAiAgentAndAiDefaultsMigration.test.ts +623 -0
- package/Tests/Server/Infrastructure/Postgres/AddKubernetesClusterAiAccessMigration.test.ts +87 -10
- package/Tests/Server/Infrastructure/Postgres/AddResourceAiAgentsMigration.test.ts +659 -0
- package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleScopeMigration.test.ts +622 -0
- package/Tests/Server/Infrastructure/SemaphoreMutex.test.ts +31 -0
- package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +119 -4
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +196 -2
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +123 -2
- package/Tests/Server/Services/AIServiceBalanceBlocker.test.ts +282 -0
- package/Tests/Server/Services/AlertMonitorClearWritesNull.test.ts +409 -0
- package/Tests/Server/Services/AlertMonitorEditFeed.test.ts +474 -0
- package/Tests/Server/Services/AlertMonitorEditGuard.test.ts +610 -0
- package/Tests/Server/Services/AutoRemediationClusterRuleEngine.test.ts +2 -0
- package/Tests/Server/Services/AutoRemediationResourceRuleEngine.test.ts +1279 -0
- package/Tests/Server/Services/AutoRemediationRuleCommandRunners.test.ts +2 -1
- package/Tests/Server/Services/DatabaseServerService.test.ts +55 -0
- package/Tests/Server/Services/GroupTelemetryUsageExcludeNames.test.ts +299 -0
- package/Tests/Server/Services/HostServiceFindOrCreateMemo.test.ts +44 -0
- package/Tests/Server/Services/IncidentAffectedMonitorsEdit.test.ts +1360 -0
- package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +3 -1
- package/Tests/Server/Services/IncidentSeverityDeletePausesComplianceRules.test.ts +488 -0
- package/Tests/Server/Services/KubernetesAiAgentJobService.test.ts +329 -0
- package/Tests/Server/Services/KubernetesAiAgentServiceHelpers.test.ts +618 -0
- package/Tests/Server/Services/KubernetesAiAgentServiceLifecycle.test.ts +1444 -0
- package/Tests/Server/Services/KubernetesAiAgentServiceRegister.test.ts +1666 -0
- package/Tests/Server/Services/KubernetesClusterAiAccessDeletedRunnerRemedy.test.ts +140 -111
- package/Tests/Server/Services/KubernetesClusterAiAccessGapNextSteps.test.ts +267 -105
- package/Tests/Server/Services/KubernetesClusterAiAccessLegacySuperseded.test.ts +440 -0
- package/Tests/Server/Services/KubernetesClusterAiAccessService.test.ts +567 -411
- package/Tests/Server/Services/KubernetesClusterAiAccessTarget.test.ts +1168 -0
- package/Tests/Server/Services/KubernetesClusterAiSettingsPermission.test.ts +410 -12
- package/Tests/Server/Services/KubernetesClusterServiceAiAccessFeed.test.ts +55 -0
- package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +45 -6
- package/Tests/Server/Services/ProjectServiceNewProjectAiDefaults.test.ts +288 -0
- package/Tests/Server/Services/ProxmoxResourcePostgres.test.ts +5633 -0
- package/Tests/Server/Services/ProxmoxResourceService.test.ts +6458 -5
- package/Tests/Server/Services/RecordingRuleReservedMetricName.test.ts +171 -0
- package/Tests/Server/Services/ResourceAiAccessChangeAuthorization.test.ts +256 -0
- package/Tests/Server/Services/ResourceAiAccessService.test.ts +1373 -0
- package/Tests/Server/Services/ResourceAiAgentJobService.test.ts +375 -0
- package/Tests/Server/Services/ResourceAiAgentServiceHelpers.test.ts +1114 -0
- package/Tests/Server/Services/ResourceAiAgentServiceLifecycle.test.ts +1050 -0
- package/Tests/Server/Services/ResourceAiAgentServiceRegister.test.ts +2251 -0
- package/Tests/Server/Services/ResourceAiSettingsCreate.test.ts +373 -0
- package/Tests/Server/Services/ResourceAiSettingsPermission.test.ts +1042 -0
- package/Tests/Server/Services/ResourceServiceDeleteCleansUpAi.test.ts +319 -0
- package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +153 -15
- package/Tests/Server/Services/RunnerJobEnqueueKubectlAiAgent.test.ts +620 -0
- package/Tests/Server/Services/RunnerJobEnqueueResourceCommand.test.ts +986 -0
- package/Tests/Server/Services/RunnerJobKubectlWriteScope.test.ts +170 -3
- package/Tests/Server/Services/RunnerJobResourceCommandLane.test.ts +211 -0
- package/Tests/Server/Services/RunnerJobResourceCommandTimeoutAndRedaction.test.ts +352 -0
- package/Tests/Server/Services/RunnerJobTimeoutReason.test.ts +72 -0
- package/Tests/Server/Services/RunnerServiceAgentName.test.ts +6 -4
- package/Tests/Server/Services/ScheduledMaintenanceAttachmentEdit.test.ts +2113 -0
- package/Tests/Server/Services/ScheduledMaintenanceMonitorRelease.test.ts +972 -0
- package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +2237 -0
- package/Tests/Server/Services/TeamComplianceSettingService.test.ts +3988 -138
- package/Tests/Server/Services/TelemetryUsageBillingSloExclusion.test.ts +218 -0
- package/Tests/Server/TestingUtils/Services/FakeRunnerJobCount.ts +145 -0
- package/Tests/Server/Utils/AI/ClusterAccessContext.test.ts +107 -1
- package/Tests/Server/Utils/AI/IncidentPostmortemRunner.test.ts +351 -0
- package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +2 -0
- package/Tests/Server/Utils/AI/InvestigationEligibility.test.ts +310 -0
- package/Tests/Server/Utils/AI/InvestigationInfrastructureAccessWiring.test.ts +453 -0
- package/Tests/Server/Utils/AI/InvestigationInfrastructureReport.test.ts +721 -0
- package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +70 -0
- package/Tests/Server/Utils/AI/KubectlJobRunnerFinishedJob.test.ts +58 -0
- package/Tests/Server/Utils/AI/RemediationCommandTools.test.ts +94 -1
- package/Tests/Server/Utils/AI/RemediationCommandToolsKubectl.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsKubectlOutcome.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsLiveCluster.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsResource.test.ts +1530 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsRunnerScope.test.ts +125 -1
- package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +252 -3
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerClusterMode.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerProjectGates.test.ts +240 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerResourceMode.test.ts +1249 -0
- package/Tests/Server/Utils/AI/RemediationKubectlCopyParity.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +117 -0
- package/Tests/Server/Utils/AI/RemediationResourceCopyParity.test.ts +463 -0
- package/Tests/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.test.ts +722 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAccessContext.test.ts +266 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.test.ts +1220 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.test.ts +569 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.test.ts +830 -0
- package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutor.test.ts +2 -0
- package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorResource.test.ts +717 -0
- package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorUnknownRun.test.ts +2 -0
- package/Tests/Server/Utils/AutoRemediation/CommandPlanVerification.test.ts +2 -0
- package/Tests/Server/Utils/AutoRemediation/RemediationVerifierResourceFollowUp.test.ts +338 -0
- package/Tests/Server/Utils/Monitor/Criteria/SessionReplayBudgetTemplateCriteria.test.ts +422 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.test.ts +1647 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayUsage.test.ts +143 -1
- package/Tests/Server/Utils/Telemetry/HostAssetAttributesFromOtlp.test.ts +68 -0
- package/Tests/Server/Utils/Telemetry/InventoryMirrorPostgres.test.ts +370 -0
- package/Tests/Server/Utils/Telemetry/NetworkDeviceInventoryAttributes.test.ts +522 -0
- package/Tests/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.test.ts +155 -0
- package/Tests/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.test.ts +8631 -0
- package/Tests/Server/Utils/Telemetry/ProxmoxNativePush.test.ts +2852 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +367 -1
- package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +75 -3
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsAccountNotLinked.test.ts +1093 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.test.ts +1049 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.test.ts +1676 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCards.test.ts +2884 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.test.ts +2490 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmit.test.ts +2293 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmitServerTimezone.test.ts +386 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.test.ts +1477 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.test.ts +1967 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsStripHtmlTags.test.ts +92 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsSubmittedFormRemoval.test.ts +1819 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.test.ts +1033 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezoneServerZone.test.ts +610 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsBotMessageHandling.test.ts +2610 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChats.test.ts +25 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsCreateCommandsEndToEnd.test.ts +4672 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsGroupChatNames.test.ts +3119 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsGroupChatNamesPostgres.test.ts +1721 -0
- package/Tests/Server/Utils/Workspace/WorkspaceCreateProjectReferences.test.ts +190 -65
- package/Tests/Types/AutoRemediation/AiRemediationCommandPlan.test.ts +10 -4
- package/Tests/Types/AutoRemediation/AiRemediationCommandPlanResourceCommand.test.ts +305 -0
- package/Tests/Types/Kubernetes/KubernetesAgentChartAiAccess.test.ts +581 -113
- package/Tests/Types/Kubernetes/KubernetesAiAgentAccessContract.test.ts +510 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +277 -13
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +113 -0
- package/Tests/Types/Monitor/RumAlertTemplates.test.ts +773 -2
- package/Tests/Types/ResourceAiAgent/AiResourceType.test.ts +419 -0
- package/Tests/Types/ResourceAiAgent/ResourceAiAccess.test.ts +517 -0
- package/Tests/Types/Runbook/RunbookStepType.test.ts +147 -8
- package/Tests/Types/Team/ComplianceRule.test.ts +1029 -0
- package/Tests/Types/Team/TeamComplianceStatus.test.ts +176 -0
- package/Tests/UI/Components/ActionButton/RowActions.test.tsx +641 -0
- package/Tests/UI/Components/ActionButton/RowActionsAccessibility.test.tsx +414 -0
- package/Tests/UI/Components/ActionButton/SplitActionButtons.test.ts +565 -0
- package/Tests/UI/Components/Charts/BarChartDragToSelect.test.tsx +386 -0
- package/Tests/UI/Components/Charts/ChartDoubleClickResetWithoutDblclick.test.tsx +1025 -0
- package/Tests/UI/Components/Charts/ChartGroupPageZoomHint.test.tsx +196 -0
- package/Tests/UI/Components/Charts/ChartPlaceholdersTakeDoubleClick.test.tsx +1861 -0
- package/Tests/UI/Components/Charts/ChartPlotClicksWhileResetArmed.test.tsx +382 -0
- package/Tests/UI/Components/Charts/ChartRangeSelection.test.tsx +704 -0
- package/Tests/UI/Components/Charts/ChartRangeSelectionDoubleClickReset.test.tsx +1481 -0
- package/Tests/UI/Components/Charts/ChartRangeSelectionRealRecharts.test.tsx +918 -0
- package/Tests/UI/Components/Charts/ChartRowBucketStart.test.ts +350 -0
- package/Tests/UI/Components/Charts/DoubleClickReset.test.tsx +996 -0
- package/Tests/UI/Components/Charts/HistogramDoubleClickResetRealRecharts.test.tsx +965 -0
- package/Tests/UI/Components/Charts/HistogramDriftThenRefetch.test.tsx +277 -0
- package/Tests/UI/Components/Charts/HistogramRangeSelectionDataChange.test.tsx +1757 -0
- package/Tests/UI/Components/Charts/HistogramRangeSelectionRealRecharts.test.tsx +560 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/ChartPageTimeRangeZoom.test.tsx +513 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.test.tsx +845 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.test.tsx +119 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHintTailwind.test.tsx +274 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.test.ts +433 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.test.tsx +863 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/ZoomDocsPromises.test.tsx +1147 -0
- package/Tests/UI/Components/DisabledButtonTooltip.test.tsx +14 -3
- package/Tests/UI/Components/EntityDropdownEscape.test.tsx +454 -0
- package/Tests/UI/Components/EntityDropdownFocusLeave.test.tsx +420 -0
- package/Tests/UI/Components/Forms/FormFieldDropdownDisabled.test.tsx +233 -0
- package/Tests/UI/Components/Input.test.tsx +80 -1
- package/Tests/UI/Components/LogsAnalyticsViewZoom.test.tsx +947 -0
- package/Tests/UI/Components/LogsHistogramDragTooltip.test.tsx +17 -5
- package/Tests/UI/Components/LogsViewerAnalyticsZoom.test.tsx +501 -0
- package/Tests/UI/Components/LogsViewerHistogramZoom.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +6 -4
- package/Tests/UI/Components/ModelTable/BaseModelTablePermissionGating.test.tsx +60 -8
- package/Tests/UI/Components/ModelTable/BaseModelTableRowActions.test.tsx +476 -0
- package/Tests/UI/Components/ModelTable/ModelTableWrapContent.test.tsx +7 -5
- package/Tests/UI/Components/MoreMenuPortal.test.tsx +623 -0
- package/Tests/UI/Components/StatusPage/ResourceGridActions.test.tsx +538 -0
- package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +14 -4
- package/Tests/UI/Components/TableCellWrapping.test.tsx +3 -3
- package/Tests/UI/Components/TableRowActions.test.tsx +472 -0
- package/Tests/UI/Components/TelemetryHistogramDragTooltip.test.tsx +1 -1
- package/Tests/UI/Components/TelemetryViewer/TelemetryViewerHistogramClickZoom.test.tsx +1 -1
- package/Tests/UI/Components/TelemetryViewer/TelemetryViewerZoomScope.test.tsx +470 -0
- package/Tests/UI/Components/TelemetryViewer/UseViewerTimeRangeZoom.test.tsx +571 -0
- package/Tests/UI/Components/TelemetryViewer/ViewerDoubleClickResetUnderDataChange.test.tsx +928 -0
- package/Tests/UI/Components/TelemetryViewer/ViewerFollowsEnclosingZoom.test.tsx +1569 -0
- package/Tests/UI/Components/Toggle.test.tsx +66 -0
- package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardRefreshNames.test.tsx +1023 -0
- package/Tests/UI/Rum/ChunkLoader.test.ts +201 -0
- package/Tests/UI/Rum/FidelityNotices.test.ts +54 -0
- package/Tests/UI/Rum/RecordingHealthDashboard.test.tsx +769 -1
- package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +72 -0
- package/Tests/UI/Rum/ReplayFrameCapture.test.ts +1009 -9
- package/Tests/UI/Rum/ReplayRecordedAssets.test.ts +1069 -0
- package/Tests/UI/Rum/ReplayStage.test.tsx +913 -2
- package/Tests/UI/Rum/SessionReplayTable.test.tsx +443 -8
- package/Tests/UI/Rum/SessionReplayUsersTable.test.tsx +439 -9
- package/Tests/UI/Rum/UserFlowTablesRowActions.test.tsx +501 -0
- package/Tests/Utils/AiRemediation/KubectlPolicyChartRbacParity.test.ts +47 -19
- package/Tests/Utils/AiRemediation/KubectlWriteScopeCallerParity.test.ts +2 -0
- package/Tests/Utils/AiRemediation/KubernetesAiAgentPolicyCopyParity.test.ts +396 -0
- package/Tests/Utils/AiRemediation/Resource/CephCommandPolicy.test.ts +1653 -0
- package/Tests/Utils/AiRemediation/Resource/CephOutputRedaction.test.ts +204 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseCommandPolicy.test.ts +1077 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.test.ts +558 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseQueryRedactor.test.ts +834 -0
- package/Tests/Utils/AiRemediation/Resource/DockerCliGrammar.test.ts +747 -0
- package/Tests/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.test.ts +1259 -0
- package/Tests/Utils/AiRemediation/Resource/DockerOutputRedaction.test.ts +386 -0
- package/Tests/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.test.ts +782 -0
- package/Tests/Utils/AiRemediation/Resource/GovcCommandPolicy.test.ts +2259 -0
- package/Tests/Utils/AiRemediation/Resource/HostCommandPolicy.test.ts +2019 -0
- package/Tests/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.test.ts +2497 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicy.test.ts +1305 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.test.ts +585 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactor.test.ts +334 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactorCopyParity.test.ts +98 -0
- package/Tests/Utils/AiRemediation/Resource/ResourcePolicyImportClosure.test.ts +391 -0
- package/Tests/Utils/AiRemediation/ResourceAiAgentPolicyCopyParity.test.ts +497 -0
- package/Tests/Utils/Dashboard/DashboardTimeRangeZoom.test.ts +104 -1
- package/Tests/Utils/SessionReplay/SessionReplayBudgetMetricType.test.ts +383 -0
- package/Types/AI/AIRunType.ts +9 -4
- package/Types/AI/InvestigationNotStartedReason.ts +6 -0
- package/Types/AI/ResourceAiAccessApi.ts +140 -0
- package/Types/AI/ResourceAiAccessPermissions.ts +126 -0
- package/Types/AutoRemediation/AiRemediationCommandPlan.ts +197 -18
- package/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.ts +28 -0
- package/Types/Dashboard/DashboardComponents/DashboardTraceChartComponent.ts +4 -2
- package/Types/Kubernetes/KubernetesClusterAiAccess.ts +263 -32
- package/Types/Kubernetes/KubernetesClusterAiAccessPermissions.ts +20 -16
- package/Types/Kubernetes/KubernetesClusterAiInsights.ts +81 -0
- package/Types/Monitor/ProxmoxAlertTemplates.ts +4 -4
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +55 -22
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +35 -3
- package/Types/Monitor/RumAlertTemplates.ts +351 -4
- package/Types/ResourceAiAgent/AiResourceType.ts +310 -0
- package/Types/ResourceAiAgent/ResourceAiAccess.ts +574 -0
- package/Types/Rum/SessionReplayBudgetMetricType.ts +47 -0
- package/Types/Runbook/RunbookStepType.ts +29 -0
- package/Types/Team/ComplianceNotificationChannel.ts +22 -0
- package/Types/Team/ComplianceRule.ts +434 -0
- package/Types/Team/ComplianceRuleType.ts +21 -0
- package/Types/Team/TeamComplianceStatus.ts +81 -0
- package/Types/Telemetry/TelemetryIngestSurface.ts +40 -0
- package/UI/Components/ActionButton/ActionButtonSchema.ts +21 -0
- package/UI/Components/ActionButton/RowActions.tsx +238 -0
- package/UI/Components/ActionButton/SplitActionButtons.ts +173 -0
- package/UI/Components/Charts/Area/AreaChart.tsx +32 -2
- package/UI/Components/Charts/Bar/BarChart.tsx +40 -3
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +37 -11
- package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +80 -243
- package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +122 -31
- package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +95 -244
- package/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.ts +214 -0
- package/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.ts +32 -0
- package/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.ts +599 -0
- package/UI/Components/Charts/Line/LineChart.tsx +32 -2
- package/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.tsx +70 -0
- package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.tsx +226 -0
- package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.tsx +73 -0
- package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.ts +163 -0
- package/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.ts +215 -0
- package/UI/Components/Charts/Utils/DataPoint.ts +20 -8
- package/UI/Components/Charts/Utils/XAxis.ts +75 -0
- package/UI/Components/Charts/Utils/useHistogramRangeSelection.ts +493 -59
- package/UI/Components/EntityDropdown/EntityDropdown.tsx +107 -11
- package/UI/Components/Forms/Fields/FormField.tsx +10 -0
- package/UI/Components/Input/Input.tsx +90 -57
- package/UI/Components/List/ListRow.tsx +8 -74
- package/UI/Components/LogsViewer/LogsViewer.tsx +40 -11
- package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +22 -6
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +209 -6
- package/UI/Components/LogsViewer/components/LogsHistogram.tsx +127 -84
- package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +3 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +12 -1
- package/UI/Components/MoreMenu/MoreMenu.tsx +365 -30
- package/UI/Components/MoreMenu/MoreMenuItem.tsx +70 -17
- package/UI/Components/OrderedStatesList/Item.tsx +7 -72
- package/UI/Components/StatusPage/ResourceGrid.tsx +126 -77
- package/UI/Components/Table/TableBody.tsx +8 -2
- package/UI/Components/Table/TableRow.tsx +20 -140
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +41 -10
- package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +47 -9
- package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +25 -6
- package/UI/Components/TelemetryViewer/types.ts +2 -0
- package/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.ts +448 -0
- package/UI/Components/Toggle/Toggle.tsx +26 -0
- package/UI/Components/Tooltip/Tooltip.tsx +8 -1
- package/UI/Styles/Theme.css +14 -2
- package/Utils/AI/InvestigationReport.ts +121 -15
- package/Utils/AiRemediation/CommandPolicy.ts +1 -1
- package/Utils/AiRemediation/KubectlPolicy.ts +1 -1
- package/Utils/AiRemediation/Resource/CephCommandPolicy.ts +1936 -0
- package/Utils/AiRemediation/Resource/DatabaseCommandPolicy.ts +166 -0
- package/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.ts +1532 -0
- package/Utils/AiRemediation/Resource/DatabaseQueryRedactor.ts +1394 -0
- package/Utils/AiRemediation/Resource/DockerCliGrammar.ts +1839 -0
- package/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.ts +490 -0
- package/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.ts +687 -0
- package/Utils/AiRemediation/Resource/GovcCommandPolicy.ts +2096 -0
- package/Utils/AiRemediation/Resource/HostCommandPolicy.ts +2982 -0
- package/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.ts +1679 -0
- package/Utils/AiRemediation/Resource/ResourceCommandPolicy.ts +851 -0
- package/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.ts +593 -0
- package/Utils/AiRemediation/Resource/ResourceOutputRedactor.ts +2812 -0
- package/Utils/Dashboard/DashboardTimeRangeZoom.ts +46 -2
- package/Utils/SessionReplay/SessionReplayBudgetMetricType.ts +184 -0
- package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js +62 -0
- package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephCluster.js +219 -0
- package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseServer.js +219 -0
- package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHost.js +219 -0
- package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +219 -0
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Host.js +219 -0
- package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +4 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesAiAgent.js +385 -0
- package/build/dist/Models/DatabaseModels/KubernetesAiAgent.js.map +1 -0
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js +3 -3
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/PodmanHost.js +219 -0
- package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +56 -5
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +219 -0
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxResource.js +51 -1
- package/build/dist/Models/DatabaseModels/ProxmoxResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ResourceAiAgent.js +439 -0
- package/build/dist/Models/DatabaseModels/ResourceAiAgent.js.map +1 -0
- package/build/dist/Models/DatabaseModels/RunnerJob.js +219 -0
- package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js +134 -3
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js.map +1 -1
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js +219 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
- package/build/dist/Server/API/AIChatAPI.js +6 -1
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +17 -10
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/AutoRemediationAPI.js +374 -24
- package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
- package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js +436 -22
- package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +69 -13
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/ProxmoxResourceAPI.js +187 -14
- package/build/dist/Server/API/ProxmoxResourceAPI.js.map +1 -1
- package/build/dist/Server/API/ResourceAiAccessAPI.js +1119 -0
- package/build/dist/Server/API/ResourceAiAccessAPI.js.map +1 -0
- package/build/dist/Server/Infrastructure/GlobalCache.js +27 -0
- package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.js +50 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.js +84 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.js +31 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js +168 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Semaphore.js +6 -0
- package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +41 -19
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +59 -1
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +248 -13
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/AlertSeverityService.js +51 -15
- package/build/dist/Server/Services/AlertSeverityService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +26 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +601 -3
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleService.js +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterService.js +104 -0
- package/build/dist/Server/Services/CephClusterService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseServerService.js +99 -0
- package/build/dist/Server/Services/DatabaseServerService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +104 -0
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js +104 -0
- package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +114 -2
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +199 -72
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentSeverityService.js +51 -15
- package/build/dist/Server/Services/IncidentSeverityService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesAiAgentJobService.js +158 -0
- package/build/dist/Server/Services/KubernetesAiAgentJobService.js.map +1 -0
- package/build/dist/Server/Services/KubernetesAiAgentService.js +1145 -0
- package/build/dist/Server/Services/KubernetesAiAgentService.js.map +1 -0
- package/build/dist/Server/Services/KubernetesClusterAiAccessService.js +842 -371
- package/build/dist/Server/Services/KubernetesClusterAiAccessService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterService.js +86 -17
- package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
- package/build/dist/Server/Services/MetricRecordingRuleService.js +46 -0
- package/build/dist/Server/Services/MetricRecordingRuleService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostService.js +104 -0
- package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +22 -0
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js +104 -0
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxResourceService.js +258 -3
- package/build/dist/Server/Services/ProxmoxResourceService.js.map +1 -1
- package/build/dist/Server/Services/ResourceAiAccessService.js +1028 -0
- package/build/dist/Server/Services/ResourceAiAccessService.js.map +1 -0
- package/build/dist/Server/Services/ResourceAiAgentJobService.js +173 -0
- package/build/dist/Server/Services/ResourceAiAgentJobService.js.map +1 -0
- package/build/dist/Server/Services/ResourceAiAgentService.js +1687 -0
- package/build/dist/Server/Services/ResourceAiAgentService.js.map +1 -0
- package/build/dist/Server/Services/RunnerJobService.js +522 -97
- package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
- package/build/dist/Server/Services/RunnerService.js +1 -1
- package/build/dist/Server/Services/RunnerService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +535 -3
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +316 -46
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/TeamComplianceSettingService.js +833 -7
- package/build/dist/Server/Services/TeamComplianceSettingService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +26 -0
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/TraceRecordingRuleService.js +37 -0
- package/build/dist/Server/Services/TraceRecordingRuleService.js.map +1 -1
- package/build/dist/Server/Services/VMwareVCenterService.js +104 -0
- package/build/dist/Server/Services/VMwareVCenterService.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js +52 -9
- package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +13 -9
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +7 -3
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +1056 -43
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +683 -42
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +21 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js +330 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js +160 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js +33 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js +640 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js +226 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js +600 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +89 -9
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +55 -4
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +55 -4
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js +30 -3
- package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js +13 -2
- package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +1 -1
- package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +294 -15
- package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
- package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js +29 -1
- package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js.map +1 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +9 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
- package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js +627 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js +60 -5
- package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +111 -6
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js +40 -4
- package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.js +296 -0
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativePush.js +699 -0
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativePush.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +77 -19
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +19 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js +19 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js +17 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +183 -209
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +19 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js +233 -167
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +768 -152
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js +129 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js +266 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js +258 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js +104 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js +183 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js +123 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js.map +1 -0
- package/build/dist/Types/AI/AIRunType.js +9 -4
- package/build/dist/Types/AI/AIRunType.js.map +1 -1
- package/build/dist/Types/AI/ResourceAiAccessApi.js +30 -0
- package/build/dist/Types/AI/ResourceAiAccessApi.js.map +1 -0
- package/build/dist/Types/AI/ResourceAiAccessPermissions.js +98 -0
- package/build/dist/Types/AI/ResourceAiAccessPermissions.js.map +1 -0
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +126 -45
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.js +28 -0
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.js.map +1 -0
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +72 -16
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -1
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js +20 -16
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js.map +1 -1
- package/build/dist/Types/Kubernetes/KubernetesClusterAiInsights.js +17 -0
- package/build/dist/Types/Kubernetes/KubernetesClusterAiInsights.js.map +1 -0
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +4 -4
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +47 -21
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +5 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/RumAlertTemplates.js +199 -3
- package/build/dist/Types/Monitor/RumAlertTemplates.js.map +1 -1
- package/build/dist/Types/ResourceAiAgent/AiResourceType.js +242 -0
- package/build/dist/Types/ResourceAiAgent/AiResourceType.js.map +1 -0
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js +275 -0
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js.map +1 -0
- package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js +45 -0
- package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js.map +1 -0
- package/build/dist/Types/Runbook/RunbookStepType.js +27 -0
- package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
- package/build/dist/Types/Team/ComplianceNotificationChannel.js +23 -0
- package/build/dist/Types/Team/ComplianceNotificationChannel.js.map +1 -0
- package/build/dist/Types/Team/ComplianceRule.js +304 -0
- package/build/dist/Types/Team/ComplianceRule.js.map +1 -0
- package/build/dist/Types/Team/ComplianceRuleType.js +21 -0
- package/build/dist/Types/Team/ComplianceRuleType.js.map +1 -1
- package/build/dist/Types/Team/TeamComplianceStatus.js +2 -0
- package/build/dist/Types/Team/TeamComplianceStatus.js.map +1 -0
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +36 -0
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -1
- package/build/dist/UI/Components/ActionButton/ActionButtonSchema.js +20 -1
- package/build/dist/UI/Components/ActionButton/ActionButtonSchema.js.map +1 -1
- package/build/dist/UI/Components/ActionButton/RowActions.js +113 -0
- package/build/dist/UI/Components/ActionButton/RowActions.js.map +1 -0
- package/build/dist/UI/Components/ActionButton/SplitActionButtons.js +71 -0
- package/build/dist/UI/Components/ActionButton/SplitActionButtons.js.map +1 -0
- package/build/dist/UI/Components/Charts/Area/AreaChart.js +16 -1
- package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js +16 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +27 -5
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +61 -194
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +84 -26
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +75 -196
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js +133 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.js +26 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.js.map +1 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.js +371 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.js.map +1 -0
- package/build/dist/UI/Components/Charts/Line/LineChart.js +16 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.js +35 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.js +107 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.js +41 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.js +117 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.js +121 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.js.map +1 -0
- package/build/dist/UI/Components/Charts/Utils/DataPoint.js +15 -7
- package/build/dist/UI/Components/Charts/Utils/DataPoint.js.map +1 -1
- package/build/dist/UI/Components/Charts/Utils/XAxis.js +70 -0
- package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
- package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js +305 -38
- package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js.map +1 -1
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +89 -14
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +11 -2
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +69 -54
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/List/ListRow.js +4 -39
- package/build/dist/UI/Components/List/ListRow.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +31 -8
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +10 -1
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +139 -21
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +30 -8
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +10 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +253 -14
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +43 -13
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
- package/build/dist/UI/Components/OrderedStatesList/Item.js +2 -38
- package/build/dist/UI/Components/OrderedStatesList/Item.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js +53 -15
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
- package/build/dist/UI/Components/Table/TableBody.js +6 -2
- package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +12 -75
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +32 -7
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +27 -9
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +11 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.js +272 -0
- package/build/dist/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.js.map +1 -0
- package/build/dist/UI/Components/Toggle/Toggle.js +14 -1
- package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
- package/build/dist/Utils/AI/InvestigationReport.js +71 -11
- package/build/dist/Utils/AI/InvestigationReport.js.map +1 -1
- package/build/dist/Utils/AiRemediation/CommandPolicy.js +1 -1
- package/build/dist/Utils/AiRemediation/CommandPolicy.js.map +1 -1
- package/build/dist/Utils/AiRemediation/KubectlPolicy.js +1 -1
- package/build/dist/Utils/AiRemediation/KubectlPolicy.js.map +1 -1
- package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js +1462 -0
- package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js +122 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js +1139 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js +1060 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js +1301 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js +370 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js +498 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js +1565 -0
- package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js +2206 -0
- package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js +1129 -0
- package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js +565 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js +408 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js +1910 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js.map +1 -0
- package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js +27 -1
- package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js.map +1 -1
- package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js +160 -0
- package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1093 @@
|
|
|
1
|
+
import {
|
|
2
|
+
afterEach,
|
|
3
|
+
beforeEach,
|
|
4
|
+
describe,
|
|
5
|
+
expect,
|
|
6
|
+
jest,
|
|
7
|
+
test,
|
|
8
|
+
} from "@jest/globals";
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* Issue #4111: "create incident" and "create maintenance" in Microsoft Teams
|
|
12
|
+
* answered "Sorry, I encountered an error processing your request" - twice.
|
|
13
|
+
* Part of the fix is that the bot checks the sender before it sends either
|
|
14
|
+
* form, and the commonest reason a sender cannot use a form is that they
|
|
15
|
+
* never connected their Microsoft Teams account to OneUptime.
|
|
16
|
+
*
|
|
17
|
+
* MicrosoftTeamsAuthAction.getOneUptimeUserIdFromTeamsUserId used to throw a
|
|
18
|
+
* plain BadDataException for that and log it with logger.error. So a card
|
|
19
|
+
* button pressed by such a user was answered "Sorry, that action failed.
|
|
20
|
+
* Please try again later.", and every press filled the server log with an
|
|
21
|
+
* error that was not one.
|
|
22
|
+
*
|
|
23
|
+
* It now throws MicrosoftTeamsAccountNotLinkedException, logged at debug.
|
|
24
|
+
* That is still a BadDataException with the same message, so whatever
|
|
25
|
+
* handled the old exception handles this one. A failure to read the link
|
|
26
|
+
* table is not "not linked": it is rethrown as it was and logged as an error,
|
|
27
|
+
* so the bot need not tell a linked user to connect an account they have
|
|
28
|
+
* connected.
|
|
29
|
+
*
|
|
30
|
+
* The first half pins the lookup, with WorkspaceUserAuthTokenService stubbed.
|
|
31
|
+
* The second runs the real lookup under the places that turn the exception
|
|
32
|
+
* into guidance - a card button (handleBotInvokeActivity), the create
|
|
33
|
+
* commands (MicrosoftTeamsCreateCommands) and the AI assistant ("ask ...",
|
|
34
|
+
* through handleBotMessageActivity) - with only the link table, the tenant
|
|
35
|
+
* and the dashboard URL stubbed. Each says where to connect the account,
|
|
36
|
+
* with the link to User Settings, and takes nothing else for "not linked".
|
|
37
|
+
*
|
|
38
|
+
* The AI assistant used to answer every lookup failure - a database error
|
|
39
|
+
* included - with "Please connect your Microsoft Teams account in OneUptime
|
|
40
|
+
* User Settings", so it told a linked user to connect the account they had
|
|
41
|
+
* connected. It now answers only the not-linked exception, and rethrows
|
|
42
|
+
* anything else, which the message handler answers with its one generic
|
|
43
|
+
* reply and logs by the command, never by the question.
|
|
44
|
+
*
|
|
45
|
+
* The create commands check the sender only in a personal chat, where the
|
|
46
|
+
* sender is the one who will submit the form. In a team channel or a group
|
|
47
|
+
* chat anyone there may submit it, so the form is posted without looking the
|
|
48
|
+
* sender up, and the submit checks whoever submits it.
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
jest.mock("../../../../../Server/EnvironmentConfig", () => {
|
|
52
|
+
return {
|
|
53
|
+
...(jest.requireActual("../../../../../Server/EnvironmentConfig") as Record<
|
|
54
|
+
string,
|
|
55
|
+
unknown
|
|
56
|
+
>),
|
|
57
|
+
MicrosoftTeamsAppClientId: "11111111-2222-3333-4444-555555555555",
|
|
58
|
+
MicrosoftTeamsAppClientSecret: "test-secret",
|
|
59
|
+
MicrosoftTeamsAppTenantId: "test-tenant",
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
/*
|
|
64
|
+
* Same botbuilder module factory as MicrosoftTeamsTeamInstalls.test.ts: the
|
|
65
|
+
* repo-wide manual mock (Tests/__mocks__/botbuilder.js) does not expose
|
|
66
|
+
* TeamsInfo or MessageFactory.attachment, both of which MicrosoftTeams.ts
|
|
67
|
+
* touches at import time.
|
|
68
|
+
*/
|
|
69
|
+
jest.mock("botbuilder", () => {
|
|
70
|
+
return {
|
|
71
|
+
CloudAdapter: class CloudAdapter {},
|
|
72
|
+
ConfigurationBotFrameworkAuthentication: class ConfigurationBotFrameworkAuthentication {},
|
|
73
|
+
TeamsActivityHandler: class TeamsActivityHandler {},
|
|
74
|
+
TurnContext: class TurnContext {},
|
|
75
|
+
ActivityHandler: class ActivityHandler {},
|
|
76
|
+
MessageFactory: {
|
|
77
|
+
text: jest.fn(),
|
|
78
|
+
attachment: jest.fn((attachment: unknown) => {
|
|
79
|
+
return { type: "message", attachments: [attachment] };
|
|
80
|
+
}),
|
|
81
|
+
},
|
|
82
|
+
CardFactory: { heroCard: jest.fn() },
|
|
83
|
+
TeamsInfo: {
|
|
84
|
+
getMembers: jest.fn(),
|
|
85
|
+
getPagedMembers: jest.fn(),
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
import type { TurnContext } from "botbuilder";
|
|
91
|
+
import type { SpyInstance } from "jest-mock";
|
|
92
|
+
import WorkspaceProjectAuthToken from "../../../../../Models/DatabaseModels/WorkspaceProjectAuthToken";
|
|
93
|
+
import WorkspaceUserAuthToken from "../../../../../Models/DatabaseModels/WorkspaceUserAuthToken";
|
|
94
|
+
import DatabaseConfig from "../../../../../Server/DatabaseConfig";
|
|
95
|
+
import AIService from "../../../../../Server/Services/AIService";
|
|
96
|
+
import IncidentService from "../../../../../Server/Services/IncidentService";
|
|
97
|
+
import ScheduledMaintenanceService from "../../../../../Server/Services/ScheduledMaintenanceService";
|
|
98
|
+
import WorkspaceUserAuthTokenService from "../../../../../Server/Services/WorkspaceUserAuthTokenService";
|
|
99
|
+
import logger, { LogAttributes } from "../../../../../Server/Utils/Logger";
|
|
100
|
+
import {
|
|
101
|
+
MicrosoftTeamsIncidentActionType,
|
|
102
|
+
MicrosoftTeamsScheduledMaintenanceActionType,
|
|
103
|
+
} from "../../../../../Server/Utils/Workspace/MicrosoftTeams/Actions/ActionTypes";
|
|
104
|
+
import MicrosoftTeamsAuthAction, {
|
|
105
|
+
MicrosoftTeamsAccountNotLinkedException,
|
|
106
|
+
} from "../../../../../Server/Utils/Workspace/MicrosoftTeams/Actions/Auth";
|
|
107
|
+
import MicrosoftTeamsIncidentActions, {
|
|
108
|
+
MicrosoftTeamsNewIncidentFormChoices,
|
|
109
|
+
} from "../../../../../Server/Utils/Workspace/MicrosoftTeams/Actions/Incident";
|
|
110
|
+
import MicrosoftTeamsScheduledMaintenanceActions, {
|
|
111
|
+
MicrosoftTeamsNewScheduledMaintenanceFormChoices,
|
|
112
|
+
} from "../../../../../Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance";
|
|
113
|
+
import MicrosoftTeamsUtil from "../../../../../Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams";
|
|
114
|
+
import { MicrosoftTeamsCardChoiceList } from "../../../../../Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices";
|
|
115
|
+
import MicrosoftTeamsCreateCommands from "../../../../../Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands";
|
|
116
|
+
import MicrosoftTeamsReplies, {
|
|
117
|
+
MICROSOFT_TEAMS_ADAPTIVE_CARD_CONTENT_TYPE,
|
|
118
|
+
} from "../../../../../Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies";
|
|
119
|
+
import WorkspaceActionAuthorization from "../../../../../Server/Utils/Workspace/WorkspaceActionAuthorization";
|
|
120
|
+
import URL from "../../../../../Types/API/URL";
|
|
121
|
+
import BadDataException from "../../../../../Types/Exception/BadDataException";
|
|
122
|
+
import Exception from "../../../../../Types/Exception/Exception";
|
|
123
|
+
import ExceptionCode from "../../../../../Types/Exception/ExceptionCode";
|
|
124
|
+
import { JSONObject } from "../../../../../Types/JSON";
|
|
125
|
+
import ObjectID from "../../../../../Types/ObjectID";
|
|
126
|
+
import WorkspaceType from "../../../../../Types/Workspace/WorkspaceType";
|
|
127
|
+
|
|
128
|
+
const PROJECT_ID: ObjectID = new ObjectID(
|
|
129
|
+
"c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
|
|
130
|
+
);
|
|
131
|
+
const LINKED_USER_ID: ObjectID = new ObjectID(
|
|
132
|
+
"d2e3f4a5-b6c7-4d8e-9f0a-1b2c3d4e5f6a",
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
// The sender as Teams names them (from.aadObjectId), and their tenant.
|
|
136
|
+
const TEAMS_USER_ID: string = "e3f4a5b6-c7d8-4e9f-8a1b-2c3d4e5f6a7b";
|
|
137
|
+
const TENANT_ID: string = "f4a5b6c7-d8e9-4f0a-9b2c-3d4e5f6a7b8c";
|
|
138
|
+
|
|
139
|
+
const INCIDENT_ID: string = "a5b6c7d8-e9f0-4a1b-8c3d-4e5f6a7b8c9d";
|
|
140
|
+
const SEVERITY_ID: string = "b6c7d8e9-f0a1-4b2c-9d3e-5f6a7b8c9d0e";
|
|
141
|
+
|
|
142
|
+
// The message the exception carried before the fix, and still carries.
|
|
143
|
+
const NOT_LINKED_MESSAGE: string =
|
|
144
|
+
"No OneUptime user linked to this Microsoft Teams user. Please authenticate with Microsoft Teams.";
|
|
145
|
+
|
|
146
|
+
const DASHBOARD_URL: string = "https://oneuptime.test/dashboard";
|
|
147
|
+
const SETTINGS_LINK: string = `${DASHBOARD_URL}/${PROJECT_ID.toString()}/user-settings/microsoft-teams-integration`;
|
|
148
|
+
|
|
149
|
+
// Where the log lines say it happened.
|
|
150
|
+
const LOG_ATTRIBUTES: JSONObject = {
|
|
151
|
+
projectId: PROJECT_ID.toString(),
|
|
152
|
+
workspaceUserId: TEAMS_USER_ID,
|
|
153
|
+
};
|
|
154
|
+
const NOT_LINKED_LOG_LINE: string = `No OneUptime user linked to Teams user: ${TEAMS_USER_ID}`;
|
|
155
|
+
const LOOKUP_FAILED_LOG_LINE: string = `Error finding OneUptime user for Teams user: ${TEAMS_USER_ID}`;
|
|
156
|
+
|
|
157
|
+
function lookUpTeamsUser(): Promise<ObjectID> {
|
|
158
|
+
return MicrosoftTeamsAuthAction.getOneUptimeUserIdFromTeamsUserId({
|
|
159
|
+
teamsUserId: TEAMS_USER_ID,
|
|
160
|
+
projectId: PROJECT_ID,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// A WorkspaceUserAuthToken row: the link between a Teams and a OneUptime user.
|
|
165
|
+
function linkRow(userId?: ObjectID): WorkspaceUserAuthToken {
|
|
166
|
+
const row: WorkspaceUserAuthToken = new WorkspaceUserAuthToken();
|
|
167
|
+
row.workspaceUserId = TEAMS_USER_ID;
|
|
168
|
+
row.projectId = PROJECT_ID;
|
|
169
|
+
row.workspaceType = WorkspaceType.MicrosoftTeams;
|
|
170
|
+
|
|
171
|
+
if (userId) {
|
|
172
|
+
row.userId = userId;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return row;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// What a promise that must fail was rejected with.
|
|
179
|
+
async function rejectionOf(promise: Promise<unknown>): Promise<unknown> {
|
|
180
|
+
try {
|
|
181
|
+
await promise;
|
|
182
|
+
} catch (error) {
|
|
183
|
+
return error;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
throw new Error("Expected the promise to be rejected, but it resolved.");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
type LinkTableSpy = SpyInstance<typeof WorkspaceUserAuthTokenService.findOneBy>;
|
|
190
|
+
|
|
191
|
+
function stubLinkTable(row: WorkspaceUserAuthToken | null): LinkTableSpy {
|
|
192
|
+
return jest
|
|
193
|
+
.spyOn(WorkspaceUserAuthTokenService, "findOneBy")
|
|
194
|
+
.mockResolvedValue(row);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function stubUnreadableLinkTable(error: unknown): LinkTableSpy {
|
|
198
|
+
return jest
|
|
199
|
+
.spyOn(WorkspaceUserAuthTokenService, "findOneBy")
|
|
200
|
+
.mockRejectedValue(error);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
interface UnlinkedCase {
|
|
204
|
+
name: string;
|
|
205
|
+
row: () => WorkspaceUserAuthToken | null;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const UNLINKED: ReadonlyArray<UnlinkedCase> = [
|
|
209
|
+
{
|
|
210
|
+
name: "no link for this Teams user in this project",
|
|
211
|
+
row: (): WorkspaceUserAuthToken | null => {
|
|
212
|
+
return null;
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
name: "a link that names no OneUptime user",
|
|
217
|
+
row: (): WorkspaceUserAuthToken | null => {
|
|
218
|
+
return linkRow();
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
];
|
|
222
|
+
|
|
223
|
+
interface LookupFailureCase {
|
|
224
|
+
name: string;
|
|
225
|
+
error: () => unknown;
|
|
226
|
+
// How a log line names it (MicrosoftTeamsReplies.describeError).
|
|
227
|
+
described: string;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const LOOKUP_FAILURES: ReadonlyArray<LookupFailureCase> = [
|
|
231
|
+
{
|
|
232
|
+
name: "the database is unreachable",
|
|
233
|
+
error: (): Error => {
|
|
234
|
+
return new Error("Connection terminated unexpectedly");
|
|
235
|
+
},
|
|
236
|
+
described: "Error: Connection terminated unexpectedly",
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
name: "the database rejects the query",
|
|
240
|
+
error: (): Error => {
|
|
241
|
+
return Object.assign(
|
|
242
|
+
new Error('relation "WorkspaceUserAuthToken" does not exist'),
|
|
243
|
+
{ name: "QueryFailedError", code: "42P01" },
|
|
244
|
+
);
|
|
245
|
+
},
|
|
246
|
+
described:
|
|
247
|
+
'QueryFailedError 42P01: relation "WorkspaceUserAuthToken" does not exist',
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
// The not-linked exception is a BadDataException; this one is not it.
|
|
251
|
+
name: "the data layer throws a BadDataException of its own",
|
|
252
|
+
error: (): BadDataException => {
|
|
253
|
+
return new BadDataException("Invalid select: userId");
|
|
254
|
+
},
|
|
255
|
+
described: "BadDataException: Invalid select: userId",
|
|
256
|
+
},
|
|
257
|
+
];
|
|
258
|
+
|
|
259
|
+
let debugLog: SpyInstance<typeof logger.debug>;
|
|
260
|
+
let errorLog: SpyInstance<typeof logger.error>;
|
|
261
|
+
|
|
262
|
+
/*
|
|
263
|
+
* Every logger.error call, with exactly the arguments it was given. Copied
|
|
264
|
+
* into arrays made here: jest records calls in arrays of its own realm,
|
|
265
|
+
* which toStrictEqual would tell apart from the literals they are compared
|
|
266
|
+
* with.
|
|
267
|
+
*/
|
|
268
|
+
function errorLogCalls(): Array<Array<unknown>> {
|
|
269
|
+
return Array.from(
|
|
270
|
+
errorLog.mock.calls,
|
|
271
|
+
(call: Parameters<typeof logger.error>): Array<unknown> => {
|
|
272
|
+
return [...call];
|
|
273
|
+
},
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
beforeEach((): void => {
|
|
278
|
+
debugLog = jest.spyOn(logger, "debug").mockImplementation((): void => {});
|
|
279
|
+
errorLog = jest.spyOn(logger, "error").mockImplementation((): void => {});
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
afterEach((): void => {
|
|
283
|
+
jest.restoreAllMocks();
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
describe("MicrosoftTeamsAuthAction.getOneUptimeUserIdFromTeamsUserId", (): void => {
|
|
287
|
+
test("a linked Teams user resolves to the OneUptime user the link names, looked up by that Teams user in this project's Microsoft Teams links", async (): Promise<void> => {
|
|
288
|
+
const row: WorkspaceUserAuthToken = linkRow(LINKED_USER_ID);
|
|
289
|
+
const findOneBy: LinkTableSpy = stubLinkTable(row);
|
|
290
|
+
|
|
291
|
+
const userId: ObjectID = await lookUpTeamsUser();
|
|
292
|
+
|
|
293
|
+
expect(userId).toBe(row.userId);
|
|
294
|
+
expect(userId.toString()).toBe(LINKED_USER_ID.toString());
|
|
295
|
+
|
|
296
|
+
expect(findOneBy).toHaveBeenCalledTimes(1);
|
|
297
|
+
expect(findOneBy).toHaveBeenCalledWith({
|
|
298
|
+
query: {
|
|
299
|
+
workspaceUserId: TEAMS_USER_ID,
|
|
300
|
+
projectId: PROJECT_ID,
|
|
301
|
+
workspaceType: WorkspaceType.MicrosoftTeams,
|
|
302
|
+
},
|
|
303
|
+
select: {
|
|
304
|
+
userId: true,
|
|
305
|
+
},
|
|
306
|
+
props: {
|
|
307
|
+
isRoot: true,
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
expect(errorLog).not.toHaveBeenCalled();
|
|
312
|
+
expect(debugLog).not.toHaveBeenCalledWith(
|
|
313
|
+
NOT_LINKED_LOG_LINE,
|
|
314
|
+
expect.anything(),
|
|
315
|
+
);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test.each(UNLINKED)(
|
|
319
|
+
"$name: throws MicrosoftTeamsAccountNotLinkedException, still a BadDataException with the same message",
|
|
320
|
+
async (unlinked: UnlinkedCase): Promise<void> => {
|
|
321
|
+
stubLinkTable(unlinked.row());
|
|
322
|
+
|
|
323
|
+
const error: unknown = await rejectionOf(lookUpTeamsUser());
|
|
324
|
+
|
|
325
|
+
expect(error).toBeInstanceOf(MicrosoftTeamsAccountNotLinkedException);
|
|
326
|
+
expect(error).toBeInstanceOf(BadDataException);
|
|
327
|
+
expect((error as BadDataException).message).toBe(NOT_LINKED_MESSAGE);
|
|
328
|
+
expect((error as BadDataException).code).toBe(
|
|
329
|
+
ExceptionCode.BadDataException,
|
|
330
|
+
);
|
|
331
|
+
},
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
test.each(UNLINKED)(
|
|
335
|
+
"$name: logged at debug, as expected - not as a server error",
|
|
336
|
+
async (unlinked: UnlinkedCase): Promise<void> => {
|
|
337
|
+
stubLinkTable(unlinked.row());
|
|
338
|
+
|
|
339
|
+
await rejectionOf(lookUpTeamsUser());
|
|
340
|
+
|
|
341
|
+
// master: logger.error("Error finding OneUptime user ...") and the error.
|
|
342
|
+
expect(errorLog).not.toHaveBeenCalled();
|
|
343
|
+
expect(debugLog).toHaveBeenCalledWith(
|
|
344
|
+
NOT_LINKED_LOG_LINE,
|
|
345
|
+
LOG_ATTRIBUTES,
|
|
346
|
+
);
|
|
347
|
+
},
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
test.each(LOOKUP_FAILURES)(
|
|
351
|
+
"$name: that error is rethrown as it is - never as 'not linked' - and logged as an error",
|
|
352
|
+
async (failure: LookupFailureCase): Promise<void> => {
|
|
353
|
+
const lookupError: unknown = failure.error();
|
|
354
|
+
stubUnreadableLinkTable(lookupError);
|
|
355
|
+
|
|
356
|
+
const error: unknown = await rejectionOf(lookUpTeamsUser());
|
|
357
|
+
|
|
358
|
+
expect(error).toBe(lookupError);
|
|
359
|
+
expect(error).not.toBeInstanceOf(MicrosoftTeamsAccountNotLinkedException);
|
|
360
|
+
|
|
361
|
+
expect(errorLog).toHaveBeenCalledWith(
|
|
362
|
+
LOOKUP_FAILED_LOG_LINE,
|
|
363
|
+
LOG_ATTRIBUTES,
|
|
364
|
+
);
|
|
365
|
+
expect(errorLog).toHaveBeenCalledWith(lookupError);
|
|
366
|
+
expect(debugLog).not.toHaveBeenCalledWith(
|
|
367
|
+
NOT_LINKED_LOG_LINE,
|
|
368
|
+
expect.anything(),
|
|
369
|
+
);
|
|
370
|
+
},
|
|
371
|
+
);
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
describe("MicrosoftTeamsAccountNotLinkedException", (): void => {
|
|
375
|
+
test("is a BadDataException, so whatever handles bad data still handles it", (): void => {
|
|
376
|
+
const error: MicrosoftTeamsAccountNotLinkedException =
|
|
377
|
+
new MicrosoftTeamsAccountNotLinkedException(NOT_LINKED_MESSAGE);
|
|
378
|
+
|
|
379
|
+
expect(error).toBeInstanceOf(BadDataException);
|
|
380
|
+
expect(error).toBeInstanceOf(Exception);
|
|
381
|
+
expect(error).toBeInstanceOf(Error);
|
|
382
|
+
expect(error.code).toBe(ExceptionCode.BadDataException);
|
|
383
|
+
expect(error.message).toBe(NOT_LINKED_MESSAGE);
|
|
384
|
+
|
|
385
|
+
// The bot shows a BadDataException's message to the user.
|
|
386
|
+
expect(MicrosoftTeamsReplies.getUserFacingErrorMessage(error)).toBe(
|
|
387
|
+
NOT_LINKED_MESSAGE,
|
|
388
|
+
);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
test("an ordinary BadDataException is not taken for it", (): void => {
|
|
392
|
+
expect(new BadDataException(NOT_LINKED_MESSAGE)).not.toBeInstanceOf(
|
|
393
|
+
MicrosoftTeamsAccountNotLinkedException,
|
|
394
|
+
);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
test("a log line names it by its class, not as a plain Error: OneUptime's exceptions keep Error's name", (): void => {
|
|
398
|
+
const error: MicrosoftTeamsAccountNotLinkedException =
|
|
399
|
+
new MicrosoftTeamsAccountNotLinkedException(NOT_LINKED_MESSAGE);
|
|
400
|
+
|
|
401
|
+
expect(error.name).toBe("Error");
|
|
402
|
+
expect(MicrosoftTeamsReplies.describeError(error)).toBe(
|
|
403
|
+
`MicrosoftTeamsAccountNotLinkedException: ${NOT_LINKED_MESSAGE}`,
|
|
404
|
+
);
|
|
405
|
+
// So the log tells it apart from the BadDataException it extends.
|
|
406
|
+
expect(
|
|
407
|
+
MicrosoftTeamsReplies.describeError(
|
|
408
|
+
new BadDataException(NOT_LINKED_MESSAGE),
|
|
409
|
+
),
|
|
410
|
+
).toBe(`BadDataException: ${NOT_LINKED_MESSAGE}`);
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
interface FakeTurn {
|
|
415
|
+
activity: JSONObject;
|
|
416
|
+
turnContext: TurnContext;
|
|
417
|
+
replies: Array<string>;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
function createFakeTurn(activity: JSONObject): FakeTurn {
|
|
421
|
+
const replies: Array<string> = [];
|
|
422
|
+
|
|
423
|
+
const turnContext: TurnContext = {
|
|
424
|
+
activity: activity,
|
|
425
|
+
sendActivity: async (reply: unknown): Promise<{ id: string }> => {
|
|
426
|
+
replies.push(typeof reply === "string" ? reply : JSON.stringify(reply));
|
|
427
|
+
return { id: `reply-${replies.length}` };
|
|
428
|
+
},
|
|
429
|
+
} as unknown as TurnContext;
|
|
430
|
+
|
|
431
|
+
return { activity: activity, turnContext: turnContext, replies: replies };
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function fromSender(): JSONObject {
|
|
435
|
+
return { id: "29:teams-user", aadObjectId: TEAMS_USER_ID, name: "Alex" };
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// A card button press: Acknowledge on an incident notification.
|
|
439
|
+
function acknowledgeButtonActivity(): JSONObject {
|
|
440
|
+
return {
|
|
441
|
+
type: "invoke",
|
|
442
|
+
name: "adaptiveCard/action",
|
|
443
|
+
id: "1727611260456",
|
|
444
|
+
value: {
|
|
445
|
+
action: MicrosoftTeamsIncidentActionType.AckIncident,
|
|
446
|
+
actionValue: INCIDENT_ID,
|
|
447
|
+
},
|
|
448
|
+
from: fromSender(),
|
|
449
|
+
recipient: { id: "28:oneuptime-bot" },
|
|
450
|
+
conversation: { conversationType: "personal", id: "a:personal-chat" },
|
|
451
|
+
channelData: { tenant: { id: TENANT_ID } },
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
function commandActivity(text: string): JSONObject {
|
|
456
|
+
return {
|
|
457
|
+
type: "message",
|
|
458
|
+
id: "1727611290789",
|
|
459
|
+
text: text,
|
|
460
|
+
from: fromSender(),
|
|
461
|
+
recipient: { id: "28:oneuptime-bot" },
|
|
462
|
+
conversation: { conversationType: "personal", id: "a:personal-chat" },
|
|
463
|
+
channelData: { tenant: { id: TENANT_ID } },
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// Conversations where anyone there can submit a form the bot posts.
|
|
468
|
+
type SharedConversation = "channel" | "groupChat";
|
|
469
|
+
|
|
470
|
+
const SHARED_CONVERSATIONS: Record<SharedConversation, JSONObject> = {
|
|
471
|
+
channel: {
|
|
472
|
+
conversation: {
|
|
473
|
+
conversationType: "channel",
|
|
474
|
+
id: "19:general@thread.tacv2;messageid=1727611290789",
|
|
475
|
+
isGroup: true,
|
|
476
|
+
},
|
|
477
|
+
channelData: {
|
|
478
|
+
tenant: { id: TENANT_ID },
|
|
479
|
+
team: { id: "19:engineering@thread.tacv2" },
|
|
480
|
+
channel: { id: "19:general@thread.tacv2" },
|
|
481
|
+
},
|
|
482
|
+
},
|
|
483
|
+
groupChat: {
|
|
484
|
+
conversation: {
|
|
485
|
+
conversationType: "groupChat",
|
|
486
|
+
id: "19:on-call-chat@thread.v2",
|
|
487
|
+
isGroup: true,
|
|
488
|
+
},
|
|
489
|
+
},
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
// The same activity, in a team channel or a group chat.
|
|
493
|
+
function inSharedConversation(
|
|
494
|
+
activity: JSONObject,
|
|
495
|
+
where: SharedConversation,
|
|
496
|
+
): JSONObject {
|
|
497
|
+
return { ...activity, ...SHARED_CONVERSATIONS[where] };
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// A question for the AI assistant, typed to the bot in a personal chat.
|
|
501
|
+
function askActivity(activityId: string): JSONObject {
|
|
502
|
+
return {
|
|
503
|
+
type: "message",
|
|
504
|
+
id: activityId,
|
|
505
|
+
text: "ask why is checkout failing?",
|
|
506
|
+
from: fromSender(),
|
|
507
|
+
recipient: { id: "28:oneuptime-bot" },
|
|
508
|
+
conversation: { conversationType: "personal", id: "a:personal-chat" },
|
|
509
|
+
channelData: { tenant: { id: TENANT_ID } },
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
function connectYourAccount(purpose: string): string {
|
|
514
|
+
return `To ${purpose}, first connect your Microsoft Teams account to OneUptime in [OneUptime → User Settings → Microsoft Teams](${SETTINGS_LINK}), then try again.`;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// What every "connect your account" reply says, whatever its wording.
|
|
518
|
+
const CONNECT_YOUR_ACCOUNT: string = "connect your Microsoft Teams account";
|
|
519
|
+
|
|
520
|
+
/*
|
|
521
|
+
* A private static of MicrosoftTeamsUtil, reached through a cast the way
|
|
522
|
+
* MicrosoftTeamsBotMessageHandling.test.ts reaches it.
|
|
523
|
+
*/
|
|
524
|
+
interface MicrosoftTeamsUtilInternals {
|
|
525
|
+
captureChatFromBotActivity: (data: {
|
|
526
|
+
activity: JSONObject;
|
|
527
|
+
turnContext: TurnContext;
|
|
528
|
+
onlyIfMissingOrStale?: boolean | undefined;
|
|
529
|
+
}) => Promise<void>;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
describe("what a Teams user without a linked account is told (the real lookup; only the link table is stubbed)", (): void => {
|
|
533
|
+
let memberPropsSpy: SpyInstance<
|
|
534
|
+
typeof WorkspaceActionAuthorization.getProjectMemberProps
|
|
535
|
+
>;
|
|
536
|
+
|
|
537
|
+
beforeEach((): void => {
|
|
538
|
+
const projectAuth: WorkspaceProjectAuthToken =
|
|
539
|
+
new WorkspaceProjectAuthToken();
|
|
540
|
+
projectAuth.projectId = PROJECT_ID;
|
|
541
|
+
|
|
542
|
+
jest
|
|
543
|
+
.spyOn(MicrosoftTeamsUtil, "resolveProjectByTenantId")
|
|
544
|
+
.mockResolvedValue({
|
|
545
|
+
projectAuth: projectAuth,
|
|
546
|
+
isAmbiguous: false,
|
|
547
|
+
candidateProjectIds: [PROJECT_ID],
|
|
548
|
+
});
|
|
549
|
+
jest
|
|
550
|
+
.spyOn(DatabaseConfig, "getDashboardUrl")
|
|
551
|
+
.mockResolvedValue(URL.fromString(DASHBOARD_URL));
|
|
552
|
+
memberPropsSpy = jest
|
|
553
|
+
.spyOn(WorkspaceActionAuthorization, "getProjectMemberProps")
|
|
554
|
+
.mockResolvedValue({ userId: LINKED_USER_ID, tenantId: PROJECT_ID });
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
describe("a card button (handleBotInvokeActivity)", (): void => {
|
|
558
|
+
let acknowledgeSpy: SpyInstance<typeof IncidentService.acknowledgeIncident>;
|
|
559
|
+
|
|
560
|
+
beforeEach((): void => {
|
|
561
|
+
acknowledgeSpy = jest
|
|
562
|
+
.spyOn(IncidentService, "acknowledgeIncident")
|
|
563
|
+
.mockRejectedValue(new Error("The action must not run."));
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
async function pressAcknowledge(): Promise<FakeTurn> {
|
|
567
|
+
const activity: JSONObject = acknowledgeButtonActivity();
|
|
568
|
+
const turn: FakeTurn = createFakeTurn(activity);
|
|
569
|
+
|
|
570
|
+
await MicrosoftTeamsUtil.handleBotInvokeActivity({
|
|
571
|
+
activity: activity,
|
|
572
|
+
turnContext: turn.turnContext,
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
return turn;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
test.each(UNLINKED)(
|
|
579
|
+
"$name: one reply that says where to connect the account; the action does not run",
|
|
580
|
+
async (unlinked: UnlinkedCase): Promise<void> => {
|
|
581
|
+
stubLinkTable(unlinked.row());
|
|
582
|
+
|
|
583
|
+
const turn: FakeTurn = await pressAcknowledge();
|
|
584
|
+
|
|
585
|
+
// master: ["Sorry, that action failed. Please try again later."]
|
|
586
|
+
expect(turn.replies).toEqual([
|
|
587
|
+
connectYourAccount("use OneUptime actions in Microsoft Teams"),
|
|
588
|
+
]);
|
|
589
|
+
expect(memberPropsSpy).not.toHaveBeenCalled();
|
|
590
|
+
expect(acknowledgeSpy).not.toHaveBeenCalled();
|
|
591
|
+
expect(errorLog).not.toHaveBeenCalled();
|
|
592
|
+
},
|
|
593
|
+
);
|
|
594
|
+
|
|
595
|
+
test("without a dashboard URL the reply still says where to connect the account", async (): Promise<void> => {
|
|
596
|
+
stubLinkTable(null);
|
|
597
|
+
jest
|
|
598
|
+
.spyOn(DatabaseConfig, "getDashboardUrl")
|
|
599
|
+
.mockRejectedValue(new Error("No host is configured."));
|
|
600
|
+
|
|
601
|
+
const turn: FakeTurn = await pressAcknowledge();
|
|
602
|
+
|
|
603
|
+
expect(turn.replies).toEqual([
|
|
604
|
+
"To use OneUptime actions in Microsoft Teams, first connect your Microsoft Teams account to OneUptime in OneUptime under User Settings → Microsoft Teams, then try again.",
|
|
605
|
+
]);
|
|
606
|
+
expect(errorLog).not.toHaveBeenCalled();
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
// What handleBotInvokeActivity's log lines carry for this button.
|
|
610
|
+
const ACKNOWLEDGE_LOG_ATTRIBUTES: LogAttributes = {
|
|
611
|
+
actionType: MicrosoftTeamsIncidentActionType.AckIncident,
|
|
612
|
+
projectId: PROJECT_ID.toString(),
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
test("a link table that cannot be read: the generic failure, logged as an error - never 'connect your account'", async (): Promise<void> => {
|
|
616
|
+
const lookupError: Error = new Error(
|
|
617
|
+
"Connection terminated unexpectedly",
|
|
618
|
+
);
|
|
619
|
+
stubUnreadableLinkTable(lookupError);
|
|
620
|
+
|
|
621
|
+
const turn: FakeTurn = await pressAcknowledge();
|
|
622
|
+
|
|
623
|
+
expect(turn.replies).toEqual([
|
|
624
|
+
"Sorry, that action failed. Please try again later.",
|
|
625
|
+
]);
|
|
626
|
+
expect(errorLog).toHaveBeenCalledWith(
|
|
627
|
+
LOOKUP_FAILED_LOG_LINE,
|
|
628
|
+
LOG_ATTRIBUTES,
|
|
629
|
+
);
|
|
630
|
+
expect(acknowledgeSpy).not.toHaveBeenCalled();
|
|
631
|
+
expect(errorLogCalls()).toStrictEqual([
|
|
632
|
+
[LOOKUP_FAILED_LOG_LINE, LOG_ATTRIBUTES],
|
|
633
|
+
[lookupError],
|
|
634
|
+
[
|
|
635
|
+
"Error handling bot invoke activity: Error: Connection terminated unexpectedly",
|
|
636
|
+
ACKNOWLEDGE_LOG_ATTRIBUTES,
|
|
637
|
+
],
|
|
638
|
+
[lookupError, ACKNOWLEDGE_LOG_ATTRIBUTES],
|
|
639
|
+
]);
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
test("a BadDataException of the data layer's own is answered with its reason, not with 'connect your account'", async (): Promise<void> => {
|
|
643
|
+
const lookupError: BadDataException = new BadDataException(
|
|
644
|
+
"Invalid select: userId",
|
|
645
|
+
);
|
|
646
|
+
stubUnreadableLinkTable(lookupError);
|
|
647
|
+
|
|
648
|
+
const turn: FakeTurn = await pressAcknowledge();
|
|
649
|
+
|
|
650
|
+
expect(turn.replies).toEqual([
|
|
651
|
+
"Sorry, that action failed: Invalid select: userId",
|
|
652
|
+
]);
|
|
653
|
+
expect(errorLog).toHaveBeenCalledWith(
|
|
654
|
+
LOOKUP_FAILED_LOG_LINE,
|
|
655
|
+
LOG_ATTRIBUTES,
|
|
656
|
+
);
|
|
657
|
+
// Named by its class, so the log does not read it as "not linked".
|
|
658
|
+
expect(errorLogCalls()).toStrictEqual([
|
|
659
|
+
[LOOKUP_FAILED_LOG_LINE, LOG_ATTRIBUTES],
|
|
660
|
+
[lookupError],
|
|
661
|
+
[
|
|
662
|
+
"Error handling bot invoke activity: BadDataException: Invalid select: userId",
|
|
663
|
+
ACKNOWLEDGE_LOG_ATTRIBUTES,
|
|
664
|
+
],
|
|
665
|
+
[lookupError, ACKNOWLEDGE_LOG_ATTRIBUTES],
|
|
666
|
+
]);
|
|
667
|
+
});
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
// A spy, as far as these tests read it.
|
|
671
|
+
interface CallRecorder {
|
|
672
|
+
mock: { calls: Array<unknown> };
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
interface CreateCommandCase {
|
|
676
|
+
name: string;
|
|
677
|
+
purpose: string;
|
|
678
|
+
what: string;
|
|
679
|
+
run: (turn: FakeTurn, activity: JSONObject) => Promise<void>;
|
|
680
|
+
// Stubs the read of the form's lists; the returned spy must stay unused.
|
|
681
|
+
stubFormLists: () => CallRecorder;
|
|
682
|
+
// Stubs the read of the form's lists with a small project's.
|
|
683
|
+
stubReadableFormLists: () => CallRecorder;
|
|
684
|
+
// The form's heading, and the action its submit button sends.
|
|
685
|
+
formTitle: string;
|
|
686
|
+
submitAction: string;
|
|
687
|
+
// The form filled in, as its submit carries it.
|
|
688
|
+
submittedFields: JSONObject;
|
|
689
|
+
// Stubs the create, which must not run: it rejects if it does.
|
|
690
|
+
stubCreateThatMustNotRun: () => CallRecorder;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
function noChoices(): MicrosoftTeamsCardChoiceList {
|
|
694
|
+
return { choices: [], totalCount: 0 };
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
const CREATE_COMMANDS: ReadonlyArray<CreateCommandCase> = [
|
|
698
|
+
{
|
|
699
|
+
name: "create incident",
|
|
700
|
+
purpose: "create incidents from Microsoft Teams",
|
|
701
|
+
what: "an incident",
|
|
702
|
+
run: (turn: FakeTurn, activity: JSONObject): Promise<void> => {
|
|
703
|
+
return MicrosoftTeamsCreateCommands.handleCreateIncidentCommand({
|
|
704
|
+
turnContext: turn.turnContext,
|
|
705
|
+
activity: activity,
|
|
706
|
+
projectId: PROJECT_ID,
|
|
707
|
+
initialTitle: undefined,
|
|
708
|
+
});
|
|
709
|
+
},
|
|
710
|
+
stubFormLists: (): CallRecorder => {
|
|
711
|
+
return jest
|
|
712
|
+
.spyOn(MicrosoftTeamsIncidentActions, "getNewIncidentFormChoices")
|
|
713
|
+
.mockRejectedValue(new Error("The form's lists must not be read."));
|
|
714
|
+
},
|
|
715
|
+
stubReadableFormLists: (): CallRecorder => {
|
|
716
|
+
const choices: MicrosoftTeamsNewIncidentFormChoices = {
|
|
717
|
+
severities: {
|
|
718
|
+
choices: [{ title: "Critical", value: SEVERITY_ID }],
|
|
719
|
+
totalCount: 1,
|
|
720
|
+
},
|
|
721
|
+
monitors: noChoices(),
|
|
722
|
+
monitorStatuses: noChoices(),
|
|
723
|
+
labels: noChoices(),
|
|
724
|
+
onCallDutyPolicies: noChoices(),
|
|
725
|
+
};
|
|
726
|
+
|
|
727
|
+
return jest
|
|
728
|
+
.spyOn(MicrosoftTeamsIncidentActions, "getNewIncidentFormChoices")
|
|
729
|
+
.mockResolvedValue(choices);
|
|
730
|
+
},
|
|
731
|
+
formTitle: "Create New Incident",
|
|
732
|
+
submitAction: MicrosoftTeamsIncidentActionType.SubmitNewIncident,
|
|
733
|
+
submittedFields: {
|
|
734
|
+
incidentTitle: "Checkout is failing",
|
|
735
|
+
incidentDescription: "Payments time out after 30 seconds.",
|
|
736
|
+
incidentSeverity: SEVERITY_ID,
|
|
737
|
+
},
|
|
738
|
+
stubCreateThatMustNotRun: (): CallRecorder => {
|
|
739
|
+
return jest
|
|
740
|
+
.spyOn(IncidentService, "create")
|
|
741
|
+
.mockRejectedValue(new Error("The incident must not be created."));
|
|
742
|
+
},
|
|
743
|
+
},
|
|
744
|
+
{
|
|
745
|
+
name: "create maintenance",
|
|
746
|
+
purpose: "schedule maintenance from Microsoft Teams",
|
|
747
|
+
what: "a scheduled maintenance event",
|
|
748
|
+
run: (turn: FakeTurn, activity: JSONObject): Promise<void> => {
|
|
749
|
+
return MicrosoftTeamsCreateCommands.handleCreateScheduledMaintenanceCommand(
|
|
750
|
+
{
|
|
751
|
+
turnContext: turn.turnContext,
|
|
752
|
+
activity: activity,
|
|
753
|
+
projectId: PROJECT_ID,
|
|
754
|
+
initialTitle: undefined,
|
|
755
|
+
},
|
|
756
|
+
);
|
|
757
|
+
},
|
|
758
|
+
stubFormLists: (): CallRecorder => {
|
|
759
|
+
return jest
|
|
760
|
+
.spyOn(
|
|
761
|
+
MicrosoftTeamsScheduledMaintenanceActions,
|
|
762
|
+
"getNewScheduledMaintenanceFormChoices",
|
|
763
|
+
)
|
|
764
|
+
.mockRejectedValue(new Error("The form's lists must not be read."));
|
|
765
|
+
},
|
|
766
|
+
stubReadableFormLists: (): CallRecorder => {
|
|
767
|
+
const choices: MicrosoftTeamsNewScheduledMaintenanceFormChoices = {
|
|
768
|
+
monitors: noChoices(),
|
|
769
|
+
monitorStatuses: noChoices(),
|
|
770
|
+
labels: noChoices(),
|
|
771
|
+
};
|
|
772
|
+
|
|
773
|
+
return jest
|
|
774
|
+
.spyOn(
|
|
775
|
+
MicrosoftTeamsScheduledMaintenanceActions,
|
|
776
|
+
"getNewScheduledMaintenanceFormChoices",
|
|
777
|
+
)
|
|
778
|
+
.mockResolvedValue(choices);
|
|
779
|
+
},
|
|
780
|
+
formTitle: "Create New Scheduled Maintenance",
|
|
781
|
+
submitAction:
|
|
782
|
+
MicrosoftTeamsScheduledMaintenanceActionType.SubmitNewScheduledMaintenance,
|
|
783
|
+
submittedFields: {
|
|
784
|
+
scheduledMaintenanceTitle: "Database upgrade",
|
|
785
|
+
scheduledMaintenanceDescription: "Upgrading the primary to 16.4.",
|
|
786
|
+
startDate: "2099-06-01",
|
|
787
|
+
startTime: "10:00",
|
|
788
|
+
endDate: "2099-06-01",
|
|
789
|
+
endTime: "11:00",
|
|
790
|
+
},
|
|
791
|
+
stubCreateThatMustNotRun: (): CallRecorder => {
|
|
792
|
+
return jest
|
|
793
|
+
.spyOn(ScheduledMaintenanceService, "create")
|
|
794
|
+
.mockRejectedValue(new Error("The event must not be created."));
|
|
795
|
+
},
|
|
796
|
+
},
|
|
797
|
+
];
|
|
798
|
+
|
|
799
|
+
describe("the create commands (MicrosoftTeamsCreateCommands)", (): void => {
|
|
800
|
+
test.each(CREATE_COMMANDS)(
|
|
801
|
+
"'$name': one reply that says where to connect the account, and no form",
|
|
802
|
+
async (command: CreateCommandCase): Promise<void> => {
|
|
803
|
+
stubLinkTable(null);
|
|
804
|
+
const formLists: { mock: { calls: Array<unknown> } } =
|
|
805
|
+
command.stubFormLists();
|
|
806
|
+
const activity: JSONObject = commandActivity(command.name);
|
|
807
|
+
const turn: FakeTurn = createFakeTurn(activity);
|
|
808
|
+
|
|
809
|
+
await command.run(turn, activity);
|
|
810
|
+
|
|
811
|
+
expect(turn.replies).toEqual([connectYourAccount(command.purpose)]);
|
|
812
|
+
// Told before filling the form in: its lists were never read.
|
|
813
|
+
expect(formLists.mock.calls).toHaveLength(0);
|
|
814
|
+
expect(memberPropsSpy).not.toHaveBeenCalled();
|
|
815
|
+
expect(errorLog).not.toHaveBeenCalled();
|
|
816
|
+
},
|
|
817
|
+
);
|
|
818
|
+
|
|
819
|
+
test.each(CREATE_COMMANDS)(
|
|
820
|
+
"'$name' while the link table cannot be read: 'try again in a minute', logged as an error - never 'connect your account'",
|
|
821
|
+
async (command: CreateCommandCase): Promise<void> => {
|
|
822
|
+
const lookupError: Error = new Error(
|
|
823
|
+
"Connection terminated unexpectedly",
|
|
824
|
+
);
|
|
825
|
+
stubUnreadableLinkTable(lookupError);
|
|
826
|
+
const formLists: { mock: { calls: Array<unknown> } } =
|
|
827
|
+
command.stubFormLists();
|
|
828
|
+
const activity: JSONObject = commandActivity(command.name);
|
|
829
|
+
const turn: FakeTurn = createFakeTurn(activity);
|
|
830
|
+
|
|
831
|
+
await command.run(turn, activity);
|
|
832
|
+
|
|
833
|
+
expect(turn.replies).toEqual([
|
|
834
|
+
`Sorry, I couldn't open the form to create ${command.what} because OneUptime could not check your account just now. Please try again in a minute.`,
|
|
835
|
+
]);
|
|
836
|
+
expect(formLists.mock.calls).toHaveLength(0);
|
|
837
|
+
expect(errorLog).toHaveBeenCalledWith(
|
|
838
|
+
LOOKUP_FAILED_LOG_LINE,
|
|
839
|
+
LOG_ATTRIBUTES,
|
|
840
|
+
);
|
|
841
|
+
const attributes: LogAttributes = { projectId: PROJECT_ID.toString() };
|
|
842
|
+
expect(errorLogCalls()).toStrictEqual([
|
|
843
|
+
[LOOKUP_FAILED_LOG_LINE, LOG_ATTRIBUTES],
|
|
844
|
+
[lookupError],
|
|
845
|
+
[
|
|
846
|
+
"Could not check the Microsoft Teams sender of a create command: Error: Connection terminated unexpectedly",
|
|
847
|
+
attributes,
|
|
848
|
+
],
|
|
849
|
+
[lookupError, attributes],
|
|
850
|
+
]);
|
|
851
|
+
},
|
|
852
|
+
);
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
describe("the create commands in a team channel or a group chat, where anyone there may submit the form", (): void => {
|
|
856
|
+
/*
|
|
857
|
+
* Whoever types the command need not be who fills the form in, so the
|
|
858
|
+
* sender is not looked up: a sender without a linked account still gets
|
|
859
|
+
* the form, for the channel. The personal-chat tests above show the check
|
|
860
|
+
* where the sender is the only one who can submit it.
|
|
861
|
+
*/
|
|
862
|
+
interface SharedCreateCase {
|
|
863
|
+
command: CreateCommandCase;
|
|
864
|
+
where: SharedConversation;
|
|
865
|
+
// The conversation, as a test title names it.
|
|
866
|
+
place: string;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
const SHARED_CREATE_CASES: ReadonlyArray<SharedCreateCase> =
|
|
870
|
+
CREATE_COMMANDS.flatMap(
|
|
871
|
+
(command: CreateCommandCase): Array<SharedCreateCase> => {
|
|
872
|
+
return [
|
|
873
|
+
{ command: command, where: "channel", place: "team channel" },
|
|
874
|
+
{ command: command, where: "groupChat", place: "group chat" },
|
|
875
|
+
];
|
|
876
|
+
},
|
|
877
|
+
);
|
|
878
|
+
|
|
879
|
+
test.each(SHARED_CREATE_CASES)(
|
|
880
|
+
"'$command.name' in a $place, from a sender without a linked account: the form, and the sender is not looked up",
|
|
881
|
+
async (sharedCase: SharedCreateCase): Promise<void> => {
|
|
882
|
+
const { command, where } = sharedCase;
|
|
883
|
+
const linkTable: LinkTableSpy = stubLinkTable(null);
|
|
884
|
+
const assertCanCreate: SpyInstance<
|
|
885
|
+
typeof WorkspaceActionAuthorization.assertCanCreate
|
|
886
|
+
> = jest.spyOn(WorkspaceActionAuthorization, "assertCanCreate");
|
|
887
|
+
const formLists: CallRecorder = command.stubReadableFormLists();
|
|
888
|
+
const activity: JSONObject = inSharedConversation(
|
|
889
|
+
commandActivity(command.name),
|
|
890
|
+
where,
|
|
891
|
+
);
|
|
892
|
+
const turn: FakeTurn = createFakeTurn(activity);
|
|
893
|
+
|
|
894
|
+
await command.run(turn, activity);
|
|
895
|
+
|
|
896
|
+
// One reply: the form, with its submit button.
|
|
897
|
+
expect(turn.replies).toHaveLength(1);
|
|
898
|
+
expect(JSON.parse(turn.replies[0] || "{}") as JSONObject).toMatchObject(
|
|
899
|
+
{
|
|
900
|
+
attachments: [
|
|
901
|
+
{
|
|
902
|
+
contentType: MICROSOFT_TEAMS_ADAPTIVE_CARD_CONTENT_TYPE,
|
|
903
|
+
content: {
|
|
904
|
+
body: expect.arrayContaining([
|
|
905
|
+
expect.objectContaining({ text: command.formTitle }),
|
|
906
|
+
]),
|
|
907
|
+
actions: [
|
|
908
|
+
expect.objectContaining({
|
|
909
|
+
data: expect.objectContaining({
|
|
910
|
+
action: command.submitAction,
|
|
911
|
+
}),
|
|
912
|
+
}),
|
|
913
|
+
],
|
|
914
|
+
},
|
|
915
|
+
},
|
|
916
|
+
],
|
|
917
|
+
},
|
|
918
|
+
);
|
|
919
|
+
expect(formLists.mock.calls).toHaveLength(1);
|
|
920
|
+
|
|
921
|
+
// Nobody was looked up: the submit checks whoever submits it.
|
|
922
|
+
expect(linkTable).not.toHaveBeenCalled();
|
|
923
|
+
expect(memberPropsSpy).not.toHaveBeenCalled();
|
|
924
|
+
expect(assertCanCreate).not.toHaveBeenCalled();
|
|
925
|
+
expect(errorLog).not.toHaveBeenCalled();
|
|
926
|
+
},
|
|
927
|
+
);
|
|
928
|
+
|
|
929
|
+
test.each(SHARED_CREATE_CASES)(
|
|
930
|
+
"the '$command.name' form submitted in a $place by someone without a linked account: where to connect it, and nothing is created",
|
|
931
|
+
async (sharedCase: SharedCreateCase): Promise<void> => {
|
|
932
|
+
const { command, where } = sharedCase;
|
|
933
|
+
stubLinkTable(null);
|
|
934
|
+
const create: CallRecorder = command.stubCreateThatMustNotRun();
|
|
935
|
+
const activity: JSONObject = inSharedConversation(
|
|
936
|
+
{
|
|
937
|
+
type: "message",
|
|
938
|
+
id: "1727611320123",
|
|
939
|
+
replyToId: "1727611300999",
|
|
940
|
+
value: { action: command.submitAction, ...command.submittedFields },
|
|
941
|
+
from: fromSender(),
|
|
942
|
+
recipient: { id: "28:oneuptime-bot" },
|
|
943
|
+
channelData: { tenant: { id: TENANT_ID } },
|
|
944
|
+
},
|
|
945
|
+
where,
|
|
946
|
+
);
|
|
947
|
+
const turn: FakeTurn = createFakeTurn(activity);
|
|
948
|
+
|
|
949
|
+
await MicrosoftTeamsUtil.handleBotInvokeActivity({
|
|
950
|
+
activity: activity,
|
|
951
|
+
turnContext: turn.turnContext,
|
|
952
|
+
});
|
|
953
|
+
|
|
954
|
+
expect(turn.replies).toEqual([
|
|
955
|
+
connectYourAccount("use OneUptime actions in Microsoft Teams"),
|
|
956
|
+
]);
|
|
957
|
+
expect(create.mock.calls).toHaveLength(0);
|
|
958
|
+
expect(memberPropsSpy).not.toHaveBeenCalled();
|
|
959
|
+
expect(errorLog).not.toHaveBeenCalled();
|
|
960
|
+
},
|
|
961
|
+
);
|
|
962
|
+
});
|
|
963
|
+
|
|
964
|
+
describe("the AI assistant ('ask ...', through handleBotMessageActivity)", (): void => {
|
|
965
|
+
let aiEnabledSpy: SpyInstance<typeof AIService.isProjectAIEnabled>;
|
|
966
|
+
|
|
967
|
+
beforeEach((): void => {
|
|
968
|
+
// Recording the chat reads the database; it is not what this is about.
|
|
969
|
+
jest
|
|
970
|
+
.spyOn(
|
|
971
|
+
MicrosoftTeamsUtil as unknown as MicrosoftTeamsUtilInternals,
|
|
972
|
+
"captureChatFromBotActivity",
|
|
973
|
+
)
|
|
974
|
+
.mockResolvedValue(undefined);
|
|
975
|
+
// The first thing the assistant reads once it knows who is asking.
|
|
976
|
+
aiEnabledSpy = jest
|
|
977
|
+
.spyOn(AIService, "isProjectAIEnabled")
|
|
978
|
+
.mockResolvedValue(false);
|
|
979
|
+
});
|
|
980
|
+
|
|
981
|
+
/*
|
|
982
|
+
* Each question gets an activity id of its own: handleBotMessageActivity
|
|
983
|
+
* drops a second delivery of the same id, for ten minutes.
|
|
984
|
+
*/
|
|
985
|
+
let lastAskActivityId: number = 1727611300100;
|
|
986
|
+
|
|
987
|
+
async function ask(): Promise<FakeTurn> {
|
|
988
|
+
lastAskActivityId += 1;
|
|
989
|
+
const activity: JSONObject = askActivity(String(lastAskActivityId));
|
|
990
|
+
const turn: FakeTurn = createFakeTurn(activity);
|
|
991
|
+
|
|
992
|
+
await MicrosoftTeamsUtil.handleBotMessageActivity({
|
|
993
|
+
activity: activity,
|
|
994
|
+
turnContext: turn.turnContext,
|
|
995
|
+
});
|
|
996
|
+
|
|
997
|
+
return turn;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
test.each(UNLINKED)(
|
|
1001
|
+
"$name: one reply that says to connect the account; the assistant is not asked",
|
|
1002
|
+
async (unlinked: UnlinkedCase): Promise<void> => {
|
|
1003
|
+
stubLinkTable(unlinked.row());
|
|
1004
|
+
|
|
1005
|
+
const turn: FakeTurn = await ask();
|
|
1006
|
+
|
|
1007
|
+
expect(turn.replies).toHaveLength(1);
|
|
1008
|
+
expect(turn.replies[0]).toContain(CONNECT_YOUR_ACCOUNT);
|
|
1009
|
+
// The same guidance as a card button's, with the link to the setting.
|
|
1010
|
+
expect(turn.replies).toEqual([
|
|
1011
|
+
connectYourAccount("ask OneUptime questions from Microsoft Teams"),
|
|
1012
|
+
]);
|
|
1013
|
+
expect(memberPropsSpy).not.toHaveBeenCalled();
|
|
1014
|
+
expect(aiEnabledSpy).not.toHaveBeenCalled();
|
|
1015
|
+
expect(errorLog).not.toHaveBeenCalled();
|
|
1016
|
+
},
|
|
1017
|
+
);
|
|
1018
|
+
|
|
1019
|
+
test("without a dashboard URL the reply still says where to connect the account", async (): Promise<void> => {
|
|
1020
|
+
stubLinkTable(null);
|
|
1021
|
+
jest
|
|
1022
|
+
.spyOn(DatabaseConfig, "getDashboardUrl")
|
|
1023
|
+
.mockRejectedValue(new Error("No host is configured."));
|
|
1024
|
+
|
|
1025
|
+
const turn: FakeTurn = await ask();
|
|
1026
|
+
|
|
1027
|
+
expect(turn.replies).toEqual([
|
|
1028
|
+
"To ask OneUptime questions from Microsoft Teams, first connect your Microsoft Teams account to OneUptime in OneUptime under User Settings → Microsoft Teams, then try again.",
|
|
1029
|
+
]);
|
|
1030
|
+
expect(errorLog).not.toHaveBeenCalled();
|
|
1031
|
+
});
|
|
1032
|
+
|
|
1033
|
+
/*
|
|
1034
|
+
* Pinned a reported bug, now fixed: answerObservabilityQuestion
|
|
1035
|
+
* (MicrosoftTeams.ts) caught every error of the lookup and answered
|
|
1036
|
+
* "I couldn't find your OneUptime account. Please connect your Microsoft
|
|
1037
|
+
* Teams account in OneUptime User Settings before asking me questions.",
|
|
1038
|
+
* the very confusion MicrosoftTeamsAccountNotLinkedException exists to
|
|
1039
|
+
* prevent. Any one reply that does not send the user to connect an
|
|
1040
|
+
* account passes here; the tests below pin which reply it is.
|
|
1041
|
+
*/
|
|
1042
|
+
test("a link table that cannot be read: one reply, which does not tell a linked user to connect the account they have connected", async (): Promise<void> => {
|
|
1043
|
+
stubUnreadableLinkTable(new Error("Connection terminated unexpectedly"));
|
|
1044
|
+
|
|
1045
|
+
const turn: FakeTurn = await ask();
|
|
1046
|
+
|
|
1047
|
+
expect(turn.replies).toHaveLength(1);
|
|
1048
|
+
expect(turn.replies[0]).not.toContain(CONNECT_YOUR_ACCOUNT);
|
|
1049
|
+
expect(memberPropsSpy).not.toHaveBeenCalled();
|
|
1050
|
+
expect(aiEnabledSpy).not.toHaveBeenCalled();
|
|
1051
|
+
expect(errorLog).toHaveBeenCalledWith(
|
|
1052
|
+
LOOKUP_FAILED_LOG_LINE,
|
|
1053
|
+
LOG_ATTRIBUTES,
|
|
1054
|
+
);
|
|
1055
|
+
});
|
|
1056
|
+
|
|
1057
|
+
/*
|
|
1058
|
+
* The lookup's error is not the assistant's to answer: it is rethrown,
|
|
1059
|
+
* and handleBotMessageActivity answers it as any failed message, once.
|
|
1060
|
+
*/
|
|
1061
|
+
test.each(LOOKUP_FAILURES)(
|
|
1062
|
+
"$name: the message handler's one reply, and the failure logged by the command, not by the question",
|
|
1063
|
+
async (failure: LookupFailureCase): Promise<void> => {
|
|
1064
|
+
const lookupError: unknown = failure.error();
|
|
1065
|
+
stubUnreadableLinkTable(lookupError);
|
|
1066
|
+
|
|
1067
|
+
const turn: FakeTurn = await ask();
|
|
1068
|
+
|
|
1069
|
+
expect(turn.replies).toEqual([
|
|
1070
|
+
MicrosoftTeamsUtil.getUnexpectedErrorMessage(turn.activity),
|
|
1071
|
+
]);
|
|
1072
|
+
expect(memberPropsSpy).not.toHaveBeenCalled();
|
|
1073
|
+
expect(aiEnabledSpy).not.toHaveBeenCalled();
|
|
1074
|
+
|
|
1075
|
+
const attributes: LogAttributes = { projectId: PROJECT_ID.toString() };
|
|
1076
|
+
expect(errorLogCalls()).toStrictEqual([
|
|
1077
|
+
// The lookup's own lines.
|
|
1078
|
+
[LOOKUP_FAILED_LOG_LINE, LOG_ATTRIBUTES],
|
|
1079
|
+
[lookupError],
|
|
1080
|
+
// The message handler's, under the reference the reply gives.
|
|
1081
|
+
[
|
|
1082
|
+
`Microsoft Teams message ${turn.activity["id"] as string} ("ask") failed: ${failure.described}`,
|
|
1083
|
+
attributes,
|
|
1084
|
+
],
|
|
1085
|
+
[lookupError, attributes],
|
|
1086
|
+
]);
|
|
1087
|
+
for (const call of errorLogCalls()) {
|
|
1088
|
+
expect(String(call[0])).not.toContain("checkout");
|
|
1089
|
+
}
|
|
1090
|
+
},
|
|
1091
|
+
);
|
|
1092
|
+
});
|
|
1093
|
+
});
|