@oneuptime/common 12.0.6 → 12.0.8
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/AIInsight.ts +1 -1
- package/Models/DatabaseModels/DatabaseBaseModel/FileModel.ts +2 -3
- package/Models/DatabaseModels/DeletedProject.ts +595 -0
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/Monitor.ts +111 -0
- package/Models/DatabaseModels/Project.ts +3 -3
- package/Models/DatabaseModels/TelemetryEntity.ts +45 -0
- package/Models/DatabaseModels/TelemetryEntityRelationship.ts +26 -0
- package/Models/DatabaseModels/WorkflowLog.ts +38 -0
- package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +19 -1
- package/Server/API/FileAPI.ts +15 -2
- package/Server/API/MicrosoftTeamsAPI.ts +6 -1
- package/Server/API/ProjectAPI.ts +214 -0
- package/Server/API/StatusPageAPI.ts +39 -6
- package/Server/API/UserAPI.ts +16 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.ts +50 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.ts +67 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.ts +39 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786551733814-MigrationName.ts +41 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786559879134-AddWorkflowLogStepTrace.ts +17 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Middleware/MasterAdminAuthorization.ts +11 -6
- package/Server/Services/AIAgentService.ts +20 -0
- package/Server/Services/DashboardDomainService.ts +73 -28
- package/Server/Services/DatabaseService.ts +1 -0
- package/Server/Services/DeletedProjectService.ts +138 -0
- package/Server/Services/FileService.ts +61 -0
- package/Server/Services/IncidentEpisodePublicNoteService.ts +18 -0
- package/Server/Services/IncidentPublicNoteService.ts +18 -0
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/MonitorService.ts +311 -0
- package/Server/Services/ProbeService.ts +20 -0
- package/Server/Services/ProjectService.ts +297 -1
- package/Server/Services/PushNotificationService.ts +71 -0
- package/Server/Services/ScheduledMaintenancePublicNoteService.ts +18 -0
- package/Server/Services/StatusPageAnnouncementService.ts +53 -0
- package/Server/Services/StatusPageDomainService.ts +73 -28
- package/Server/Services/TeamMemberService.ts +117 -12
- package/Server/Services/TelemetryEntityRelationshipService.ts +3 -0
- package/Server/Services/TelemetryEntityService.ts +114 -1
- package/Server/Services/TelemetryIngestionKeyService.ts +1 -0
- package/Server/Services/UserWebhookService.ts +34 -109
- package/Server/Services/WorkspaceNotificationRuleService.ts +69 -0
- package/Server/Services/WorkspaceProjectAuthTokenService.ts +37 -1
- package/Server/Types/Database/DeleteById.ts +2 -0
- package/Server/Types/Database/DeleteOneBy.ts +6 -0
- package/Server/Types/Domain.ts +41 -0
- package/Server/Types/Workflow/Components/API/Delete.ts +2 -1
- package/Server/Types/Workflow/Components/API/Get.ts +2 -1
- package/Server/Types/Workflow/Components/API/Patch.ts +2 -1
- package/Server/Types/Workflow/Components/API/Post.ts +2 -1
- package/Server/Types/Workflow/Components/API/Put.ts +2 -1
- package/Server/Types/Workflow/Components/API/Utils.ts +85 -3
- package/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts +25 -19
- package/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts +6 -5
- package/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.ts +32 -14
- package/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.ts +31 -13
- package/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.ts +29 -20
- package/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.ts +28 -21
- package/Server/Types/Workflow/Components/BaseModel/LogComponentError.ts +89 -0
- package/Server/Types/Workflow/Components/BaseModel/ModelArguments.ts +208 -0
- package/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.ts +11 -0
- package/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.ts +41 -18
- package/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.ts +45 -19
- package/Server/Types/Workflow/Components/Discord/SendMessageToChannel.ts +16 -9
- package/Server/Types/Workflow/Components/IncomingWebhookUtils.ts +66 -0
- package/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.ts +15 -9
- package/Server/Types/Workflow/Components/Slack/SendMessageToChannel.ts +17 -0
- package/Server/Types/Workflow/TriggerCode.ts +12 -0
- package/Server/Types/Workflow/Workflow.ts +5 -0
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
- package/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.ts +171 -0
- package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +3 -3
- package/Server/Utils/AI/SRE/Insights/FixRouting.ts +3 -2
- package/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.ts +1 -1
- package/Server/Utils/AI/Toolbox/CodeWriteTools.ts +6 -6
- package/Server/Utils/CodeRepository/GitHub/GitHub.ts +43 -5
- package/Server/Utils/DataSource/EgressGuard.ts +176 -16
- package/Server/Utils/DataSource/HttpFetch.ts +6 -45
- package/Server/Utils/Execute.ts +8 -0
- package/Server/Utils/InlineImageAccessTokenSync.ts +23 -0
- package/Server/Utils/LLM/LLMService.ts +57 -12
- package/Server/Utils/Monitor/MonitorAlert.ts +40 -0
- package/Server/Utils/Monitor/MonitorDependencySuppression.ts +192 -0
- package/Server/Utils/Monitor/MonitorIncident.ts +40 -0
- package/Server/Utils/Monitor/MonitorResource.ts +36 -0
- package/Server/Utils/Response.ts +142 -6
- package/Server/Utils/SSRFProtection.ts +273 -60
- package/Server/Utils/StartServer.ts +8 -0
- package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +689 -0
- package/Server/Utils/VM/VMAPI.ts +56 -8
- package/Server/Utils/VM/VMRunner.ts +88 -1
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +555 -49
- package/Server/Utils/Workspace/Slack/Slack.ts +25 -2
- package/Server/Utils/Workspace/WorkspaceBase.ts +6 -0
- package/Tests/App/Dashboard/DangerZone.test.tsx +334 -0
- package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +539 -0
- package/Tests/App/Dashboard/DashboardVariableSelector.test.tsx +678 -0
- package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +706 -0
- package/Tests/App/Dashboard/DashboardVariablesModal.test.tsx +508 -0
- package/Tests/App/Dashboard/MonitorCriteriaAttributeFilter.test.tsx +574 -0
- package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +470 -0
- package/Tests/App/StatusPage/StatusPageDetailPagesNotFound.test.tsx +308 -0
- package/Tests/Models/DatabaseModels/DeletedProjectModel.test.ts +251 -0
- package/Tests/Models/DatabaseModels/SavedViewJSONColumnTuples.test.ts +115 -0
- package/Tests/Server/API/FileAPIAccessControl.test.ts +316 -0
- package/Tests/Server/API/ProjectAPI.test.ts +299 -1
- package/Tests/Server/API/ProjectAPIAdjustBalance.test.ts +459 -0
- package/Tests/Server/API/ProjectAPIAdjustBalanceBillingDisabled.test.ts +177 -0
- package/Tests/Server/API/UserProjectsAPI.test.ts +478 -4
- package/Tests/Server/Services/DatabaseServiceDeletionReason.test.ts +123 -0
- package/Tests/Server/Services/DeletedProjectService.test.ts +415 -0
- package/Tests/Server/Services/DeletedProjectServiceSelfHosted.test.ts +70 -0
- package/Tests/Server/Services/DomainSubdomainHooks.test.ts +94 -0
- package/Tests/Server/Services/FileIsPublicBooleanMigration.test.ts +244 -0
- package/Tests/Server/Services/FileServiceMimeType.test.ts +89 -0
- package/Tests/Server/Services/MonitorServiceDependencyValidation.test.ts +702 -0
- package/Tests/Server/Services/ProjectServiceAdjustBalance.test.ts +615 -0
- package/Tests/Server/Services/ProjectServiceDeleteAudit.test.ts +406 -0
- package/Tests/Server/Services/PublishTimeImageVisibility.test.ts +450 -0
- package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +669 -0
- package/Tests/Server/Services/TelemetryEntityManualCreate.test.ts +248 -0
- package/Tests/Server/Services/UserWebhookSSRF.test.ts +174 -0
- package/Tests/Server/Services/WebPushEndpointAllowlist.test.ts +133 -0
- package/Tests/Server/Services/WorkspaceProjectAuthTokenRepoint.test.ts +618 -0
- package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +26 -1
- package/Tests/Server/Types/Workflow/Components/ApiComponentHeaders.test.ts +192 -0
- package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +215 -0
- package/Tests/Server/Types/Workflow/Components/BaseModelDatabaseComponents.test.ts +742 -0
- package/Tests/Server/Types/Workflow/Components/ChatWebhookComponents.test.ts +256 -0
- package/Tests/Server/Types/Workflow/Components/ModelArguments.test.ts +371 -0
- package/Tests/Server/Utils/AI/CodeAgentCommandGuard.test.ts +204 -0
- package/Tests/Server/Utils/AI/CodeAgentWriteLimits.test.ts +213 -0
- package/Tests/Server/Utils/AI/CodeWriteTools.test.ts +52 -5
- package/Tests/Server/Utils/AI/LLMServiceBaseUrl.test.ts +3 -0
- package/Tests/Server/Utils/AI/LLMServiceEgressGuard.test.ts +315 -0
- package/Tests/Server/Utils/AI/LLMServiceModelCompatibility.test.ts +3 -0
- package/Tests/Server/Utils/AI/LLMServiceRequestPolicy.test.ts +17 -5
- package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +14 -1
- package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +35 -0
- package/Tests/Server/Utils/AI/StubLLMEgressGuard.ts +25 -0
- package/Tests/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.test.ts +152 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +62 -7
- package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +69 -0
- package/Tests/Server/Utils/DataSource/EgressGuardPinning.test.ts +330 -0
- package/Tests/Server/Utils/GitHubCreatePullRequestWithToken.test.ts +393 -0
- package/Tests/Server/Utils/InlineImageAccessTokenSync.test.ts +202 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppression.test.ts +811 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +604 -0
- package/Tests/Server/Utils/ResponseSendFileResponse.test.ts +192 -0
- package/Tests/Server/Utils/SSRFProtectionBypasses.test.ts +406 -0
- package/Tests/Server/Utils/Telemetry/InventoryEntityRegistry.test.ts +322 -0
- package/Tests/Server/Utils/VM/VMAPISubstitution.test.ts +243 -0
- package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +194 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +1169 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelsList.test.ts +2 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsTeamInstalls.test.ts +1605 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsTenantResolution.test.ts +1218 -0
- package/Tests/Types/AI/AIChatMessageStatus.test.ts +79 -0
- package/Tests/Types/AI/AIInsightStatus.test.ts +40 -0
- package/Tests/Types/API/HostnameAuthorityParsing.test.ts +157 -0
- package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +27 -0
- package/Tests/Types/DataSource/DataSourceLimits.test.ts +71 -0
- package/Tests/Types/DataSource/DataSourceType.test.ts +181 -0
- package/Tests/Types/DomainSubdomainValidation.test.ts +90 -0
- package/Tests/Types/JSONFunctions.test.ts +252 -1
- package/Tests/Types/Monitor/SnmpMonitor/SnmpAuthProtocol.test.ts +61 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpPrivProtocol.test.ts +62 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpSecurityLevel.test.ts +68 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpVersion.test.ts +51 -0
- package/Tests/Types/SerializableObjectDictionaryImportCycle.test.ts +197 -0
- package/Tests/Types/Telemetry/EntityTypeGroups.test.ts +140 -0
- package/Tests/Types/Workflow/StepTrace.test.ts +235 -0
- package/Tests/Types/Workflow/TemplateSyntax.test.ts +379 -0
- package/Tests/Types/Workflow/Templates.test.ts +403 -0
- package/Tests/UI/Components/404.test.tsx +1 -1
- package/Tests/UI/Components/Alert.test.tsx +1 -1
- package/Tests/UI/Components/Badge.test.tsx +1 -1
- package/Tests/UI/Components/BasicForm.test.tsx +39 -10
- package/Tests/UI/Components/Button.test.tsx +1 -1
- package/Tests/UI/Components/Card.test.tsx +1 -1
- package/Tests/UI/Components/Charts/AxisTickColor.test.tsx +1 -1
- package/Tests/UI/Components/ColorViewer.test.tsx +1 -1
- package/Tests/UI/Components/ComponentsModal.test.tsx +7 -1
- package/Tests/UI/Components/CustomTimeRangeModal.test.tsx +459 -0
- package/Tests/UI/Components/DictionaryAttributeFilterRow.test.tsx +477 -0
- package/Tests/UI/Components/DictionaryOfStrings.test.tsx +1 -1
- package/Tests/UI/Components/Dropdown.test.tsx +1 -1
- package/Tests/UI/Components/FilePicker.test.tsx +1 -1
- package/Tests/UI/Components/Forms/AnchoredFieldPopupKeyboard.test.tsx +382 -0
- package/Tests/UI/Components/Forms/ColorPickerPicking.test.tsx +569 -0
- package/Tests/UI/Components/Forms/ValidationJSON.test.ts +241 -0
- package/Tests/UI/Components/HiddenText.test.tsx +1 -1
- package/Tests/UI/Components/Input.test.tsx +1 -1
- package/Tests/UI/Components/Loader.test.tsx +1 -1
- package/Tests/UI/Components/LogTimeRangePicker.test.tsx +43 -1
- package/Tests/UI/Components/MasterPage.test.tsx +1 -1
- package/Tests/UI/Components/ModalPortalDismissal.test.tsx +579 -0
- package/Tests/UI/Components/ModelDelete.test.tsx +214 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkSelectAll.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableSearchLabels.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1 -1
- package/Tests/UI/Components/NavBar.test.tsx +1 -1
- package/Tests/UI/Components/OperatorSelectorKeyboard.test.tsx +1 -1
- package/Tests/UI/Components/Pagination.test.tsx +1 -1
- package/Tests/UI/Components/Pill.test.tsx +1 -1
- package/Tests/UI/Components/Probe.test.tsx +1 -1
- package/Tests/UI/Components/ProgressBar.test.tsx +1 -1
- package/Tests/UI/Components/RadioButtons.test.tsx +1 -1
- package/Tests/UI/Components/SideMenuItem.test.tsx +1 -1
- package/Tests/UI/Components/SideOver.test.tsx +500 -6
- package/Tests/UI/Components/Tabs.test.tsx +1 -1
- package/Tests/UI/Components/TelemetrySearchBar.test.tsx +1 -1
- package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +50 -8
- package/Tests/UI/Components/TextArea.test.tsx +1 -1
- package/Tests/UI/Components/TimeRangePickerDropdown.test.tsx +325 -0
- package/Tests/UI/Components/Toast.test.tsx +1 -1
- package/Tests/UI/Components/Toggle.test.tsx +1 -1
- package/Tests/UI/Components/TopSection.test.tsx +1 -1
- package/Tests/UI/Components/UseLiveLogsRefresh.test.tsx +1 -1
- package/Tests/UI/Components/Workflow/GraphLint.test.ts +821 -0
- package/Tests/UI/Components/Workflow/ModelColumnEditor.test.ts +287 -0
- package/Tests/UI/Components/Workflow/ModelColumnEditorServerContract.test.ts +185 -0
- package/Tests/UI/Components/Workflow/ModelSchema.test.ts +174 -0
- package/Tests/UI/Components/Workflow/RunStatusWatcher.test.ts +152 -0
- package/Tests/UI/Components/Workflow/Utils.test.ts +192 -0
- package/Tests/UI/Monitor/MonitorStepCriteriaView.test.tsx +432 -0
- package/Tests/UI/Rum/ReplayScrubber.test.tsx +1 -1
- package/Tests/UI/Rum/ReplayStage.test.tsx +1 -1
- package/Tests/UI/Telemetry/TelemetrySnapshotWindowAlert.test.tsx +1 -1
- package/Tests/UI/Utils/LocalStorageArrayRoundTrip.test.ts +72 -0
- package/Tests/Utils/Dashboard/HtmlWidgetDocument.test.ts +19 -2
- package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +44 -0
- package/Tests/Utils/Dashboard/VariableInterpolation.test.ts +288 -5
- package/Tests/Utils/Dashboard/VariableUrlState.test.ts +42 -0
- package/Tests/Utils/DataSource/DataSourceQueryText.test.ts +27 -0
- package/Tests/Utils/LegacySerializedArray.test.ts +139 -0
- package/Tests/Utils/Monitor/MonitorDependencyRule.test.ts +190 -0
- package/Tests/Utils/Monitor/NetworkDeviceRoleUtil.test.ts +514 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +240 -0
- package/Tests/Utils/Realtime.test.ts +78 -0
- package/Tests/Utils/Schema/AnalyticsModelSchema.test.ts +469 -0
- package/Tests/Utils/Schema/ModelSchema.test.ts +268 -0
- package/Tests/Utils/Telemetry/EntityKeyNonTelemetry.test.ts +193 -0
- package/Tests/Utils/Telemetry/SavedViewFilters.test.ts +246 -0
- package/Tests/__mocks__/i18next-browser-languagedetector.js +21 -0
- package/Types/AI/FixPullRequestCiStatus.ts +1 -1
- package/Types/AI/FixVerificationStatus.ts +2 -2
- package/Types/API/Hostname.ts +92 -4
- package/Types/API/URL.ts +43 -25
- package/Types/Billing/BalanceAdjustmentType.ts +14 -0
- package/Types/Billing/ProjectBalanceType.ts +13 -0
- package/Types/Domain.ts +26 -0
- package/Types/File/MimeType.ts +11 -0
- package/Types/JSONFunctions.ts +15 -0
- package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +31 -0
- package/Types/SerializableObjectDictionary.ts +133 -39
- package/Types/Telemetry/EntitySource.ts +40 -0
- package/Types/Telemetry/EntityType.ts +27 -0
- package/Types/Telemetry/EntityTypeGroups.ts +65 -0
- package/Types/Telemetry/TelemetrySavedViewState.ts +9 -1
- package/Types/Workflow/Component.ts +29 -0
- package/Types/Workflow/Components/API.ts +35 -0
- package/Types/Workflow/Components/BaseModel.ts +96 -28
- package/Types/Workflow/StepTrace.ts +181 -0
- package/Types/Workflow/TemplateSyntax.ts +499 -0
- package/Types/Workflow/Templates.ts +316 -0
- package/Typings/Index.d.ts +12 -0
- package/UI/Components/Date/CustomTimeRangeModal.tsx +278 -0
- package/UI/Components/Date/TimeRangePickerDropdown.tsx +250 -0
- package/UI/Components/Dictionary/Dictionary.tsx +23 -6
- package/UI/Components/Forms/Fields/ColorPicker.tsx +66 -10
- package/UI/Components/Forms/Fields/IconPicker.tsx +48 -10
- package/UI/Components/Forms/Types/Field.ts +7 -0
- package/UI/Components/Forms/Validation.ts +63 -1
- package/UI/Components/GanttChart/ChartContainer.tsx +4 -3
- package/UI/Components/Input/Input.tsx +31 -3
- package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +11 -216
- package/UI/Components/Modal/ConfirmModal.tsx +10 -5
- package/UI/Components/Modal/Modal.tsx +64 -51
- package/UI/Components/ModelDelete/ModelDelete.tsx +23 -6
- package/UI/Components/SideOver/SideOver.tsx +195 -68
- package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +11 -210
- package/UI/Components/Workflow/ArgumentsForm.tsx +194 -7
- package/UI/Components/Workflow/Component.tsx +28 -26
- package/UI/Components/Workflow/ComponentSettingsModal.tsx +69 -8
- package/UI/Components/Workflow/GraphLint.ts +591 -0
- package/UI/Components/Workflow/ModelColumnEditor.tsx +396 -0
- package/UI/Components/Workflow/ModelSchema.ts +196 -0
- package/UI/Components/Workflow/RunForm.tsx +41 -7
- package/UI/Components/Workflow/RunStatusWatcher.ts +122 -0
- package/UI/Components/Workflow/StepTraceViewer.tsx +186 -0
- package/UI/Components/Workflow/Utils.ts +93 -1
- package/UI/Components/Workflow/Workflow.tsx +77 -4
- package/UI/Types/LayeredDismissal.ts +31 -0
- package/UI/Types/UseAnchoredFieldPopup.ts +99 -0
- package/UI/Utils/PageScrollLock.ts +66 -0
- package/Utils/Dashboard/HtmlWidgetDocument.ts +4 -2
- package/Utils/Dashboard/VariableInterpolation.ts +19 -1
- package/Utils/LegacySerializedArray.ts +60 -0
- package/Utils/Monitor/MonitorDependencyRule.ts +88 -0
- package/Utils/Monitor/NetworkDeviceRoleUtil.ts +533 -0
- package/Utils/Monitor/NetworkTopologyUtil.ts +45 -7
- package/Utils/Telemetry/EntityKey.ts +66 -0
- package/Utils/Telemetry/SavedViewFilters.ts +88 -0
- package/build/dist/Models/DatabaseModels/AIInsight.js +1 -1
- package/build/dist/Models/DatabaseModels/AIInsight.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js +2 -3
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DeletedProject.js +640 -0
- package/build/dist/Models/DatabaseModels/DeletedProject.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +106 -0
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +3 -3
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryEntity.js +47 -0
- package/build/dist/Models/DatabaseModels/TelemetryEntity.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryEntityRelationship.js +27 -0
- package/build/dist/Models/DatabaseModels/TelemetryEntityRelationship.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowLog.js +39 -0
- package/build/dist/Models/DatabaseModels/WorkflowLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
- package/build/dist/Server/API/FileAPI.js +14 -2
- package/build/dist/Server/API/FileAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +6 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/ProjectAPI.js +157 -4
- package/build/dist/Server/API/ProjectAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +27 -3
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/UserAPI.js +16 -1
- package/build/dist/Server/API/UserAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js +30 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786551733814-MigrationName.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786551733814-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786559879134-AddWorkflowLogStepTrace.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786559879134-AddWorkflowLogStepTrace.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/MasterAdminAuthorization.js +11 -6
- package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -1
- package/build/dist/Server/Services/AIAgentService.js +17 -0
- package/build/dist/Server/Services/AIAgentService.js.map +1 -1
- package/build/dist/Server/Services/DashboardDomainService.js +55 -18
- package/build/dist/Server/Services/DashboardDomainService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +1 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DeletedProjectService.js +124 -0
- package/build/dist/Server/Services/DeletedProjectService.js.map +1 -0
- package/build/dist/Server/Services/FileService.js +52 -0
- package/build/dist/Server/Services/FileService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +10 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js +10 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +232 -0
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/ProbeService.js +17 -0
- package/build/dist/Server/Services/ProbeService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +228 -6
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/PushNotificationService.js +56 -0
- package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +10 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageAnnouncementService.js +54 -0
- package/build/dist/Server/Services/StatusPageAnnouncementService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageDomainService.js +55 -18
- package/build/dist/Server/Services/StatusPageDomainService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +97 -6
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js +3 -0
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryEntityService.js +91 -1
- package/build/dist/Server/Services/TelemetryEntityService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js +1 -0
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
- package/build/dist/Server/Services/UserWebhookService.js +31 -87
- package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +65 -0
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js +23 -0
- package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js.map +1 -1
- package/build/dist/Server/Types/Domain.js +37 -0
- package/build/dist/Server/Types/Domain.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js +63 -2
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js +15 -11
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js +2 -3
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js +21 -10
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js +21 -10
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js +18 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js +18 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js +43 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js.map +1 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js +116 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js.map +1 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js +7 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js +24 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js +27 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js +14 -6
- package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js +42 -0
- package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js.map +1 -0
- package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js +15 -6
- package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js +10 -2
- package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/TriggerCode.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js +141 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/FixRouting.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.js +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js +6 -6
- package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +39 -5
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
- package/build/dist/Server/Utils/DataSource/EgressGuard.js +94 -10
- package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
- package/build/dist/Server/Utils/DataSource/HttpFetch.js +1 -19
- package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
- package/build/dist/Server/Utils/Execute.js +2 -2
- package/build/dist/Server/Utils/Execute.js.map +1 -1
- package/build/dist/Server/Utils/InlineImageAccessTokenSync.js +13 -0
- package/build/dist/Server/Utils/InlineImageAccessTokenSync.js.map +1 -1
- package/build/dist/Server/Utils/LLM/LLMService.js +43 -12
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +44 -24
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js +158 -0
- package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +50 -30
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +32 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Response.js +112 -5
- package/build/dist/Server/Utils/Response.js.map +1 -1
- package/build/dist/Server/Utils/SSRFProtection.js +219 -53
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +7 -0
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +507 -0
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -0
- package/build/dist/Server/Utils/VM/VMAPI.js +51 -4
- package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMRunner.js +73 -1
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +445 -43
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js +18 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
- package/build/dist/Types/AI/FixPullRequestCiStatus.js +1 -1
- package/build/dist/Types/AI/FixVerificationStatus.js +2 -2
- package/build/dist/Types/API/Hostname.js +73 -4
- package/build/dist/Types/API/Hostname.js.map +1 -1
- package/build/dist/Types/API/URL.js +42 -24
- package/build/dist/Types/API/URL.js.map +1 -1
- package/build/dist/Types/Billing/BalanceAdjustmentType.js +15 -0
- package/build/dist/Types/Billing/BalanceAdjustmentType.js.map +1 -0
- package/build/dist/Types/Billing/ProjectBalanceType.js +14 -0
- package/build/dist/Types/Billing/ProjectBalanceType.js.map +1 -0
- package/build/dist/Types/Domain.js +22 -0
- package/build/dist/Types/Domain.js.map +1 -1
- package/build/dist/Types/File/MimeType.js +11 -0
- package/build/dist/Types/File/MimeType.js.map +1 -1
- package/build/dist/Types/JSONFunctions.js +14 -0
- package/build/dist/Types/JSONFunctions.js.map +1 -1
- package/build/dist/Types/SerializableObjectDictionary.js +133 -39
- package/build/dist/Types/SerializableObjectDictionary.js.map +1 -1
- package/build/dist/Types/Telemetry/EntitySource.js +39 -0
- package/build/dist/Types/Telemetry/EntitySource.js.map +1 -0
- package/build/dist/Types/Telemetry/EntityType.js +27 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/EntityTypeGroups.js +57 -0
- package/build/dist/Types/Telemetry/EntityTypeGroups.js.map +1 -0
- package/build/dist/Types/Workflow/Component.js +21 -0
- package/build/dist/Types/Workflow/Component.js.map +1 -1
- package/build/dist/Types/Workflow/Components/API.js +35 -0
- package/build/dist/Types/Workflow/Components/API.js.map +1 -1
- package/build/dist/Types/Workflow/Components/BaseModel.js +87 -28
- package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
- package/build/dist/Types/Workflow/StepTrace.js +104 -0
- package/build/dist/Types/Workflow/StepTrace.js.map +1 -0
- package/build/dist/Types/Workflow/TemplateSyntax.js +326 -0
- package/build/dist/Types/Workflow/TemplateSyntax.js.map +1 -0
- package/build/dist/Types/Workflow/Templates.js +218 -0
- package/build/dist/Types/Workflow/Templates.js.map +1 -0
- package/build/dist/UI/Components/Date/CustomTimeRangeModal.js +126 -0
- package/build/dist/UI/Components/Date/CustomTimeRangeModal.js.map +1 -0
- package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js +123 -0
- package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js.map +1 -0
- package/build/dist/UI/Components/Dictionary/Dictionary.js +22 -6
- package/build/dist/UI/Components/Dictionary/Dictionary.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/ColorPicker.js +52 -13
- package/build/dist/UI/Components/Forms/Fields/ColorPicker.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/IconPicker.js +28 -12
- package/build/dist/UI/Components/Forms/Fields/IconPicker.js.map +1 -1
- package/build/dist/UI/Components/Forms/Validation.js +44 -0
- package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
- package/build/dist/UI/Components/GanttChart/ChartContainer.js +4 -3
- package/build/dist/UI/Components/GanttChart/ChartContainer.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +12 -4
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +5 -108
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js +3 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +55 -39
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/ModelDelete/ModelDelete.js +11 -6
- package/build/dist/UI/Components/ModelDelete/ModelDelete.js.map +1 -1
- package/build/dist/UI/Components/SideOver/SideOver.js +105 -30
- package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +5 -105
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js +140 -11
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
- package/build/dist/UI/Components/Workflow/Component.js +20 -19
- package/build/dist/UI/Components/Workflow/Component.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js +31 -3
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/GraphLint.js +396 -0
- package/build/dist/UI/Components/Workflow/GraphLint.js.map +1 -0
- package/build/dist/UI/Components/Workflow/ModelColumnEditor.js +225 -0
- package/build/dist/UI/Components/Workflow/ModelColumnEditor.js.map +1 -0
- package/build/dist/UI/Components/Workflow/ModelSchema.js +118 -0
- package/build/dist/UI/Components/Workflow/ModelSchema.js.map +1 -0
- package/build/dist/UI/Components/Workflow/RunForm.js +22 -6
- package/build/dist/UI/Components/Workflow/RunForm.js.map +1 -1
- package/build/dist/UI/Components/Workflow/RunStatusWatcher.js +76 -0
- package/build/dist/UI/Components/Workflow/RunStatusWatcher.js.map +1 -0
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js +76 -0
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js.map +1 -0
- package/build/dist/UI/Components/Workflow/Utils.js +73 -1
- package/build/dist/UI/Components/Workflow/Utils.js.map +1 -1
- package/build/dist/UI/Components/Workflow/Workflow.js +51 -6
- package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
- package/build/dist/UI/Types/LayeredDismissal.js +21 -0
- package/build/dist/UI/Types/LayeredDismissal.js.map +1 -0
- package/build/dist/UI/Types/UseAnchoredFieldPopup.js +74 -1
- package/build/dist/UI/Types/UseAnchoredFieldPopup.js.map +1 -1
- package/build/dist/UI/Utils/PageScrollLock.js +52 -0
- package/build/dist/UI/Utils/PageScrollLock.js.map +1 -0
- package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js +4 -2
- package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js.map +1 -1
- package/build/dist/Utils/Dashboard/VariableInterpolation.js +19 -1
- package/build/dist/Utils/Dashboard/VariableInterpolation.js.map +1 -1
- package/build/dist/Utils/LegacySerializedArray.js +51 -0
- package/build/dist/Utils/LegacySerializedArray.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorDependencyRule.js +47 -0
- package/build/dist/Utils/Monitor/MonitorDependencyRule.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js +386 -0
- package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +35 -6
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/Telemetry/EntityKey.js +52 -0
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- package/build/dist/Utils/Telemetry/SavedViewFilters.js +52 -0
- package/build/dist/Utils/Telemetry/SavedViewFilters.js.map +1 -0
- package/jest.config.json +3 -0
- package/package.json +1 -1
- package/tsconfig.json +3 -1
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import "@testing-library/jest-dom";
|
|
2
|
+
import { render, screen, waitFor } from "@testing-library/react";
|
|
3
|
+
import React, { act } from "react";
|
|
4
|
+
import {
|
|
5
|
+
afterEach,
|
|
6
|
+
beforeEach,
|
|
7
|
+
describe,
|
|
8
|
+
expect,
|
|
9
|
+
jest,
|
|
10
|
+
test,
|
|
11
|
+
} from "@jest/globals";
|
|
12
|
+
import AnnouncementDetail from "../../../../App/FeatureSet/StatusPage/src/Pages/Announcement/Detail";
|
|
13
|
+
import IncidentDetail from "../../../../App/FeatureSet/StatusPage/src/Pages/Incidents/Detail";
|
|
14
|
+
import ScheduledEventDetail from "../../../../App/FeatureSet/StatusPage/src/Pages/ScheduledEvent/Detail";
|
|
15
|
+
import Route from "../../../Types/API/Route";
|
|
16
|
+
import HTTPErrorResponse from "../../../Types/API/HTTPErrorResponse";
|
|
17
|
+
import HTTPResponse from "../../../Types/API/HTTPResponse";
|
|
18
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
19
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
20
|
+
import LocalStorage from "../../../UI/Utils/LocalStorage";
|
|
21
|
+
import Navigation from "../../../UI/Utils/Navigation";
|
|
22
|
+
|
|
23
|
+
const STATUS_PAGE_ID: string = "33333333-3333-4333-8333-333333333333";
|
|
24
|
+
const ITEM_ID: string = "44444444-4444-4444-8444-444444444444";
|
|
25
|
+
|
|
26
|
+
type PostResponse = HTTPResponse<JSONObject> | HTTPErrorResponse;
|
|
27
|
+
type RespondToPostFunction = (url: string) => PostResponse;
|
|
28
|
+
|
|
29
|
+
/*
|
|
30
|
+
* Each test swaps this out to describe what the status page API returns for the
|
|
31
|
+
* request the page under test makes.
|
|
32
|
+
*/
|
|
33
|
+
let mockRespondToPost: RespondToPostFunction = (): PostResponse => {
|
|
34
|
+
throw new Error("mockRespondToPost was not set by the test");
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
let mockLogoutCallCount: number = 0;
|
|
38
|
+
|
|
39
|
+
// Logging out hits the network and navigates, neither of which belongs in this test.
|
|
40
|
+
jest.mock("../../../../App/FeatureSet/StatusPage/src/Utils/User", () => {
|
|
41
|
+
return {
|
|
42
|
+
__esModule: true,
|
|
43
|
+
default: {
|
|
44
|
+
isLoggedIn: () => {
|
|
45
|
+
return true;
|
|
46
|
+
},
|
|
47
|
+
logout: () => {
|
|
48
|
+
mockLogoutCallCount++;
|
|
49
|
+
return Promise.resolve();
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
jest.mock("../../../../App/FeatureSet/StatusPage/src/Utils/API", () => {
|
|
56
|
+
return {
|
|
57
|
+
__esModule: true,
|
|
58
|
+
default: {
|
|
59
|
+
post: (options: { url: { toString: () => string } }) => {
|
|
60
|
+
return Promise.resolve(mockRespondToPost(options.url.toString()));
|
|
61
|
+
},
|
|
62
|
+
getDefaultHeaders: () => {
|
|
63
|
+
return {};
|
|
64
|
+
},
|
|
65
|
+
getFriendlyMessage: (error: { message?: string }) => {
|
|
66
|
+
return error?.message || "Something went wrong";
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
/*
|
|
73
|
+
* The real page chrome renders breadcrumb links, which need a router. None of
|
|
74
|
+
* these tests are about the chrome, so keep it to a plain wrapper.
|
|
75
|
+
*/
|
|
76
|
+
jest.mock(
|
|
77
|
+
"../../../../App/FeatureSet/StatusPage/src/Components/Page/Page",
|
|
78
|
+
() => {
|
|
79
|
+
return {
|
|
80
|
+
__esModule: true,
|
|
81
|
+
default: (props: { children: React.ReactNode }) => {
|
|
82
|
+
return <div>{props.children}</div>;
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
type SuccessResponseFunction = (data: JSONObject) => HTTPResponse<JSONObject>;
|
|
89
|
+
|
|
90
|
+
const successResponse: SuccessResponseFunction = (
|
|
91
|
+
data: JSONObject,
|
|
92
|
+
): HTTPResponse<JSONObject> => {
|
|
93
|
+
return new HTTPResponse<JSONObject>(200, data, {});
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
type ErrorResponseFunction = (
|
|
97
|
+
statusCode: number,
|
|
98
|
+
message: string,
|
|
99
|
+
) => HTTPErrorResponse;
|
|
100
|
+
|
|
101
|
+
const errorResponse: ErrorResponseFunction = (
|
|
102
|
+
statusCode: number,
|
|
103
|
+
message: string,
|
|
104
|
+
): HTTPErrorResponse => {
|
|
105
|
+
return new HTTPErrorResponse(statusCode, { message: message }, {});
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
type PageComponent = React.FunctionComponent<{
|
|
109
|
+
pageRoute: Route;
|
|
110
|
+
onLoadComplete: () => void;
|
|
111
|
+
}>;
|
|
112
|
+
|
|
113
|
+
type RenderPageFunction = (
|
|
114
|
+
Component: PageComponent,
|
|
115
|
+
) => Promise<ReturnType<typeof render>>;
|
|
116
|
+
|
|
117
|
+
/*
|
|
118
|
+
* These pages load themselves from an effect, so the render has to be flushed
|
|
119
|
+
* inside act() for the resulting state updates to be settled.
|
|
120
|
+
*/
|
|
121
|
+
const renderPage: RenderPageFunction = async (
|
|
122
|
+
Component: PageComponent,
|
|
123
|
+
): Promise<ReturnType<typeof render>> => {
|
|
124
|
+
let result: ReturnType<typeof render> | null = null;
|
|
125
|
+
|
|
126
|
+
await act(async () => {
|
|
127
|
+
result = render(
|
|
128
|
+
<Component
|
|
129
|
+
pageRoute={new Route(`/incidents/${ITEM_ID}`)}
|
|
130
|
+
onLoadComplete={() => {}}
|
|
131
|
+
/>,
|
|
132
|
+
);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
return result!;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
describe("Status page detail pages when the item is not available", () => {
|
|
139
|
+
const navigate: typeof Navigation.navigate = Navigation.navigate;
|
|
140
|
+
|
|
141
|
+
beforeEach(() => {
|
|
142
|
+
mockLogoutCallCount = 0;
|
|
143
|
+
localStorage.clear();
|
|
144
|
+
LocalStorage.setItem("statusPageId", new ObjectID(STATUS_PAGE_ID));
|
|
145
|
+
window.history.replaceState({}, "", `/incidents/${ITEM_ID}`);
|
|
146
|
+
|
|
147
|
+
// jsdom cannot leave the page, and it logs a noisy error when asked to.
|
|
148
|
+
Navigation.navigate = (): void => {};
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
afterEach(() => {
|
|
152
|
+
Navigation.navigate = navigate;
|
|
153
|
+
jest.clearAllMocks();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test("incident page shows the empty state when neither an incident nor an episode is found", async () => {
|
|
157
|
+
/*
|
|
158
|
+
* This is the production case that hung the page: the incident exists but has
|
|
159
|
+
* no monitors on this status page, so the API filters it out and returns an
|
|
160
|
+
* empty list with a 200.
|
|
161
|
+
*/
|
|
162
|
+
mockRespondToPost = (url: string): PostResponse => {
|
|
163
|
+
if (url.includes("/incidents/")) {
|
|
164
|
+
return successResponse({
|
|
165
|
+
incidents: [],
|
|
166
|
+
incidentPublicNotes: [],
|
|
167
|
+
incidentStateTimelines: [],
|
|
168
|
+
statusPageResources: [],
|
|
169
|
+
monitorsInGroup: {},
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Most status pages have episodes turned off, so the fallback lookup fails.
|
|
174
|
+
return errorResponse(
|
|
175
|
+
400,
|
|
176
|
+
"Episodes are not enabled on this status page.",
|
|
177
|
+
);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const { container } = await renderPage(IncidentDetail);
|
|
181
|
+
|
|
182
|
+
await waitFor(() => {
|
|
183
|
+
expect(container.querySelector("#item-empty-state")).toBeInTheDocument();
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
expect(
|
|
187
|
+
screen.getByText("Incident not found on this status page."),
|
|
188
|
+
).toBeInTheDocument();
|
|
189
|
+
expect(screen.queryByTestId("bar-loader")).not.toBeInTheDocument();
|
|
190
|
+
|
|
191
|
+
// The episode fallback's error is an implementation detail. It must not leak.
|
|
192
|
+
expect(
|
|
193
|
+
screen.queryByText("Episodes are not enabled on this status page."),
|
|
194
|
+
).not.toBeInTheDocument();
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
test("incident page surfaces the error when the incident lookup itself fails", async () => {
|
|
198
|
+
mockRespondToPost = (): PostResponse => {
|
|
199
|
+
return errorResponse(403, "This status page is not public.");
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const { container } = await renderPage(IncidentDetail);
|
|
203
|
+
|
|
204
|
+
await waitFor(() => {
|
|
205
|
+
expect(
|
|
206
|
+
screen.getByText("This status page is not public."),
|
|
207
|
+
).toBeInTheDocument();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
expect(
|
|
211
|
+
container.querySelector("#item-empty-state"),
|
|
212
|
+
).not.toBeInTheDocument();
|
|
213
|
+
expect(screen.queryByTestId("bar-loader")).not.toBeInTheDocument();
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
test("incident page logs the user out when the lookup comes back unauthorized", async () => {
|
|
217
|
+
// An expired session has to reach the auth check rather than read as "not found".
|
|
218
|
+
mockRespondToPost = (): PostResponse => {
|
|
219
|
+
return errorResponse(401, "Not authorized.");
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
await renderPage(IncidentDetail);
|
|
223
|
+
|
|
224
|
+
await waitFor(() => {
|
|
225
|
+
expect(mockLogoutCallCount).toBeGreaterThan(0);
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test("incident page still renders the incident when one is found", async () => {
|
|
230
|
+
mockRespondToPost = (url: string): PostResponse => {
|
|
231
|
+
if (url.includes("/incidents/")) {
|
|
232
|
+
return successResponse({
|
|
233
|
+
incidents: [
|
|
234
|
+
{
|
|
235
|
+
_id: ITEM_ID,
|
|
236
|
+
title: "Checkout is degraded",
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
incidentPublicNotes: [],
|
|
240
|
+
incidentStateTimelines: [],
|
|
241
|
+
statusPageResources: [],
|
|
242
|
+
monitorsInGroup: {},
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
throw new Error("The episode fallback should not be reached");
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const { container } = await renderPage(IncidentDetail);
|
|
250
|
+
|
|
251
|
+
await waitFor(() => {
|
|
252
|
+
expect(screen.getByText("Checkout is degraded")).toBeInTheDocument();
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
expect(
|
|
256
|
+
container.querySelector("#item-empty-state"),
|
|
257
|
+
).not.toBeInTheDocument();
|
|
258
|
+
expect(screen.queryByTestId("bar-loader")).not.toBeInTheDocument();
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
test("scheduled maintenance page shows the empty state when the event is not found", async () => {
|
|
262
|
+
mockRespondToPost = (): PostResponse => {
|
|
263
|
+
return successResponse({
|
|
264
|
+
scheduledMaintenanceEvents: [],
|
|
265
|
+
scheduledMaintenanceEventsPublicNotes: [],
|
|
266
|
+
scheduledMaintenanceStateTimelines: [],
|
|
267
|
+
statusPageResources: [],
|
|
268
|
+
monitorsInGroup: {},
|
|
269
|
+
});
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const { container } = await renderPage(ScheduledEventDetail);
|
|
273
|
+
|
|
274
|
+
await waitFor(() => {
|
|
275
|
+
expect(
|
|
276
|
+
container.querySelector("#scheduled-event-empty-state"),
|
|
277
|
+
).toBeInTheDocument();
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
expect(
|
|
281
|
+
screen.getByText("No scheduled event found for this status page."),
|
|
282
|
+
).toBeInTheDocument();
|
|
283
|
+
expect(screen.queryByTestId("bar-loader")).not.toBeInTheDocument();
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
test("announcement page shows the empty state when the announcement is not found", async () => {
|
|
287
|
+
mockRespondToPost = (): PostResponse => {
|
|
288
|
+
return successResponse({
|
|
289
|
+
announcements: [],
|
|
290
|
+
statusPageResources: [],
|
|
291
|
+
monitorsInGroup: {},
|
|
292
|
+
});
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const { container } = await renderPage(AnnouncementDetail);
|
|
296
|
+
|
|
297
|
+
await waitFor(() => {
|
|
298
|
+
expect(
|
|
299
|
+
container.querySelector("#announcement-empty-state"),
|
|
300
|
+
).toBeInTheDocument();
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
expect(
|
|
304
|
+
screen.getByText("Announcement not found on this status page."),
|
|
305
|
+
).toBeInTheDocument();
|
|
306
|
+
expect(screen.queryByTestId("bar-loader")).not.toBeInTheDocument();
|
|
307
|
+
});
|
|
308
|
+
});
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import Models from "../../../Models/DatabaseModels/Index";
|
|
2
|
+
import DeletedProject from "../../../Models/DatabaseModels/DeletedProject";
|
|
3
|
+
import Project from "../../../Models/DatabaseModels/Project";
|
|
4
|
+
import User from "../../../Models/DatabaseModels/User";
|
|
5
|
+
import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
6
|
+
import Migrations from "../../../Server/Infrastructure/Postgres/SchemaMigrations/Index";
|
|
7
|
+
import { ColumnAccessControl } from "../../../Types/BaseDatabase/AccessControl";
|
|
8
|
+
import TableColumnType from "../../../Types/Database/TableColumnType";
|
|
9
|
+
import Permission from "../../../Types/Permission";
|
|
10
|
+
import { describe, expect, it } from "@jest/globals";
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* DeletedProject is the only record that a deleted project ever existed -
|
|
14
|
+
* projects are hard deleted, so anything this table does not carry is gone for
|
|
15
|
+
* good. These tests pin the two properties that cannot be observed from the
|
|
16
|
+
* service tests: that the snapshot is genuinely standalone (no relation to the
|
|
17
|
+
* row it describes), and that customer data in it is not reachable by ordinary
|
|
18
|
+
* project users.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
describe("DeletedProject model", () => {
|
|
22
|
+
const model: DeletedProject = new DeletedProject();
|
|
23
|
+
|
|
24
|
+
it("is registered in the model index, so its table is created", () => {
|
|
25
|
+
const isRegistered: boolean = Models.some(
|
|
26
|
+
(registered: { new (): BaseModel }) => {
|
|
27
|
+
return registered === DeletedProject;
|
|
28
|
+
},
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
expect(isRegistered).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("is a global table, not scoped to the project it describes", () => {
|
|
35
|
+
/*
|
|
36
|
+
* A tenant column here would be a foreign key to Project, and Postgres
|
|
37
|
+
* would cascade the audit row away with the very project it records.
|
|
38
|
+
*/
|
|
39
|
+
expect(model.getTenantColumn()).toBeFalsy();
|
|
40
|
+
expect(model.isTenantModel()).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("is served from its own CRUD endpoint", () => {
|
|
44
|
+
expect(model.getCrudApiPath()?.toString()).toBe("/deleted-project");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("uses its own table", () => {
|
|
48
|
+
expect(model.tableName).toBe("DeletedProject");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("records the project identity, so a deleted project can still be identified", () => {
|
|
52
|
+
const columns: Array<string> = model.getTableColumns().columns;
|
|
53
|
+
|
|
54
|
+
for (const column of [
|
|
55
|
+
"projectId",
|
|
56
|
+
"projectName",
|
|
57
|
+
"projectSlug",
|
|
58
|
+
"projectCreatedAt",
|
|
59
|
+
"projectDeletedAt",
|
|
60
|
+
]) {
|
|
61
|
+
expect(columns).toContain(column);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("records who deleted the project and how to reach them", () => {
|
|
66
|
+
const columns: Array<string> = model.getTableColumns().columns;
|
|
67
|
+
|
|
68
|
+
for (const column of [
|
|
69
|
+
"projectDeletedByUserId",
|
|
70
|
+
"projectDeletedByUserName",
|
|
71
|
+
"projectDeletedByUserEmail",
|
|
72
|
+
"projectCreatedByUserId",
|
|
73
|
+
"projectCreatedByUserName",
|
|
74
|
+
"projectCreatedByUserEmail",
|
|
75
|
+
"companyName",
|
|
76
|
+
"companyPhoneNumber",
|
|
77
|
+
"companySize",
|
|
78
|
+
"jobRole",
|
|
79
|
+
]) {
|
|
80
|
+
expect(columns).toContain(column);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("records why the customer said they were leaving", () => {
|
|
85
|
+
expect(model.getTableColumns().columns).toContain("deletionReason");
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("stores the reason as unbounded text, so a long answer is not truncated", () => {
|
|
89
|
+
expect(model.getTableColumnMetadata("deletionReason").type).toBe(
|
|
90
|
+
TableColumnType.VeryLongText,
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("records what the customer was worth and how much they had built", () => {
|
|
95
|
+
const columns: Array<string> = model.getTableColumns().columns;
|
|
96
|
+
|
|
97
|
+
for (const column of [
|
|
98
|
+
"planName",
|
|
99
|
+
"paymentProviderPlanId",
|
|
100
|
+
"paymentProviderCustomerId",
|
|
101
|
+
"paymentProviderSubscriptionId",
|
|
102
|
+
"paymentProviderSubscriptionStatus",
|
|
103
|
+
"paymentProviderSubscriptionSeats",
|
|
104
|
+
"trialEndsAt",
|
|
105
|
+
"activeMonitorCount",
|
|
106
|
+
"wasProjectBlocked",
|
|
107
|
+
]) {
|
|
108
|
+
expect(columns).toContain(column);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
/*
|
|
113
|
+
* The project row is deleted before this one is written. A relation would
|
|
114
|
+
* have nothing to point at - which is why projectId is a plain uuid and the
|
|
115
|
+
* name, slug and dates are copied rather than joined.
|
|
116
|
+
*/
|
|
117
|
+
it("keeps the project id as a plain column, not a relation to Project", () => {
|
|
118
|
+
expect(model.getTableColumnMetadata("projectId").type).toBe(
|
|
119
|
+
TableColumnType.ObjectID,
|
|
120
|
+
);
|
|
121
|
+
expect(model.getTableColumnMetadata("projectId").modelType).toBeUndefined();
|
|
122
|
+
expect(model.getTableColumns().columns).not.toContain("project");
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("requires the project id, name and deletion time on every row", () => {
|
|
126
|
+
expect(model.getTableColumnMetadata("projectId").required).toBe(true);
|
|
127
|
+
expect(model.getTableColumnMetadata("projectName").required).toBe(true);
|
|
128
|
+
expect(model.getTableColumnMetadata("projectDeletedAt").required).toBe(
|
|
129
|
+
true,
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
/*
|
|
134
|
+
* The user relations exist only so staff can jump to the account. They must
|
|
135
|
+
* be nullable and non-cascading: a user who later deletes their account must
|
|
136
|
+
* not take the record of the project deletion with them, which is also why
|
|
137
|
+
* the name and email are copied onto the row.
|
|
138
|
+
*/
|
|
139
|
+
it("relates to the users involved without depending on them surviving", () => {
|
|
140
|
+
expect(model.getTableColumnMetadata("projectDeletedByUser").modelType).toBe(
|
|
141
|
+
User,
|
|
142
|
+
);
|
|
143
|
+
expect(model.getTableColumnMetadata("projectCreatedByUser").modelType).toBe(
|
|
144
|
+
User,
|
|
145
|
+
);
|
|
146
|
+
expect(model.getTableColumnMetadata("projectDeletedByUser").required).toBe(
|
|
147
|
+
undefined,
|
|
148
|
+
);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
/*
|
|
152
|
+
* Every column carries names, emails and phone numbers of customers who have
|
|
153
|
+
* already left. Empty permission arrays are how this repo says "master admin
|
|
154
|
+
* only" - no user permission can intersect an empty list, and root and
|
|
155
|
+
* master admin bypass the check entirely.
|
|
156
|
+
*/
|
|
157
|
+
it("cannot be read, written or deleted by any project user", () => {
|
|
158
|
+
expect(model.getCreatePermissions()).toEqual([]);
|
|
159
|
+
expect(model.getReadPermissions()).toEqual([]);
|
|
160
|
+
expect(model.getUpdatePermissions()).toEqual([]);
|
|
161
|
+
expect(model.getDeletePermissions()).toEqual([]);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("locks down every single column, not just the table", () => {
|
|
165
|
+
const accessControl: Record<string, ColumnAccessControl> =
|
|
166
|
+
model.getColumnAccessControlForAllColumns();
|
|
167
|
+
|
|
168
|
+
/*
|
|
169
|
+
* _id and the timestamps come from the base model and carry no column
|
|
170
|
+
* access control of their own. Every column this model declares must have
|
|
171
|
+
* one - a column added without the decorator is the case worth catching,
|
|
172
|
+
* so its absence fails rather than being skipped.
|
|
173
|
+
*/
|
|
174
|
+
const baseModelColumns: Array<string> = [
|
|
175
|
+
"_id",
|
|
176
|
+
"createdAt",
|
|
177
|
+
"updatedAt",
|
|
178
|
+
"deletedAt",
|
|
179
|
+
"version",
|
|
180
|
+
];
|
|
181
|
+
|
|
182
|
+
const declaredColumns: Array<string> = model
|
|
183
|
+
.getTableColumns()
|
|
184
|
+
.columns.filter((columnName: string) => {
|
|
185
|
+
return !baseModelColumns.includes(columnName);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
expect(declaredColumns.length).toBeGreaterThan(20);
|
|
189
|
+
|
|
190
|
+
for (const columnName of declaredColumns) {
|
|
191
|
+
const columnAccess: ColumnAccessControl | undefined =
|
|
192
|
+
accessControl[columnName];
|
|
193
|
+
|
|
194
|
+
expect(columnAccess).toBeDefined();
|
|
195
|
+
expect(columnAccess?.create).toEqual([]);
|
|
196
|
+
expect(columnAccess?.read).toEqual([]);
|
|
197
|
+
expect(columnAccess?.update).toEqual([]);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it("does not hand a project owner any permission over it", () => {
|
|
202
|
+
expect(model.getReadPermissions()).not.toContain(Permission.ProjectOwner);
|
|
203
|
+
expect(model.getReadPermissions()).not.toContain(Permission.ProjectAdmin);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
describe("Project model - deletion snapshot source columns", () => {
|
|
208
|
+
const project: Project = new Project();
|
|
209
|
+
|
|
210
|
+
/*
|
|
211
|
+
* ProjectService.onBeforeDelete reads these off the project before it is
|
|
212
|
+
* deleted and DeletedProjectService copies them onto the audit row. If one
|
|
213
|
+
* is renamed the snapshot silently loses a field, so pin them here.
|
|
214
|
+
*/
|
|
215
|
+
it("still has every column the deletion snapshot copies", () => {
|
|
216
|
+
const columns: Array<string> = project.getTableColumns().columns;
|
|
217
|
+
|
|
218
|
+
for (const column of [
|
|
219
|
+
"name",
|
|
220
|
+
"slug",
|
|
221
|
+
"planName",
|
|
222
|
+
"paymentProviderPlanId",
|
|
223
|
+
"paymentProviderCustomerId",
|
|
224
|
+
"paymentProviderSubscriptionId",
|
|
225
|
+
"paymentProviderSubscriptionStatus",
|
|
226
|
+
"paymentProviderSubscriptionSeats",
|
|
227
|
+
"trialEndsAt",
|
|
228
|
+
"currentActiveMonitorsCount",
|
|
229
|
+
"isBlocked",
|
|
230
|
+
"createdByUserId",
|
|
231
|
+
]) {
|
|
232
|
+
expect(columns).toContain(column);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
describe("DeletedProject migration", () => {
|
|
238
|
+
/*
|
|
239
|
+
* A migration that is not in this array never runs, so the table simply does
|
|
240
|
+
* not exist in a fresh database and every project delete logs an error.
|
|
241
|
+
*/
|
|
242
|
+
it("is registered, so the table is actually created", () => {
|
|
243
|
+
const registeredNames: Array<string> = (
|
|
244
|
+
Migrations as unknown as Array<{ name: string }>
|
|
245
|
+
).map((migration: { name: string }) => {
|
|
246
|
+
return migration.name;
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
expect(registeredNames).toContain("AddDeletedProjectTable1786461136170");
|
|
250
|
+
});
|
|
251
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
2
|
+
import MetricSavedView from "../../../Models/DatabaseModels/MetricSavedView";
|
|
3
|
+
import TraceSavedView from "../../../Models/DatabaseModels/TraceSavedView";
|
|
4
|
+
import { JSONArray, JSONObject } from "../../../Types/JSON";
|
|
5
|
+
import TelemetrySavedViewState from "../../../Types/Telemetry/TelemetrySavedViewState";
|
|
6
|
+
import { readSavedViewFilters } from "../../../Utils/Telemetry/SavedViewFilters";
|
|
7
|
+
import { describe, expect, test } from "@jest/globals";
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* A saved view's filter tuples pass through DatabaseBaseModel.toJSON twice:
|
|
11
|
+
* once in the browser on the way to the API, and once on the server on the way
|
|
12
|
+
* back out — every REST response for a model goes through it. Both directions
|
|
13
|
+
* ran the serializer that flattened nested arrays, so a row could be perfectly
|
|
14
|
+
* intact in Postgres and still reach the browser as
|
|
15
|
+
* { "0": facetKey, "1": value }.
|
|
16
|
+
*
|
|
17
|
+
* That is why this is pinned at the model layer and not only on the helper:
|
|
18
|
+
* the read path has to hold on its own, or a patched browser talking to an
|
|
19
|
+
* unpatched API is still broken.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const SAVED_STATE: TelemetrySavedViewState = {
|
|
23
|
+
search: "status:error",
|
|
24
|
+
filters: [
|
|
25
|
+
["primaryEntityId", "6512f1a0a1b2c3d4e5f60718"],
|
|
26
|
+
["attributes.http.method", "GET"],
|
|
27
|
+
],
|
|
28
|
+
timeRange: { range: "Past one hour" },
|
|
29
|
+
pageSize: 50,
|
|
30
|
+
rootOnly: false,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function readFiltersFromJSON(json: JSONObject): JSONArray {
|
|
34
|
+
return (json["query"] as JSONObject)["filters"] as JSONArray;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe("Saved view JSON columns keep their filter tuples through toJSON", () => {
|
|
38
|
+
test("TraceSavedView keeps filters as arrays", () => {
|
|
39
|
+
const view: TraceSavedView = new TraceSavedView();
|
|
40
|
+
view.name = "Errors in checkout";
|
|
41
|
+
view.query = SAVED_STATE;
|
|
42
|
+
|
|
43
|
+
const json: JSONObject = BaseModel.toJSON(view, TraceSavedView);
|
|
44
|
+
const filters: JSONArray = readFiltersFromJSON(json);
|
|
45
|
+
|
|
46
|
+
expect(Array.isArray(filters)).toBe(true);
|
|
47
|
+
expect(Array.isArray(filters[0])).toBe(true);
|
|
48
|
+
expect(filters).toEqual(SAVED_STATE.filters);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("MetricSavedView keeps filters as arrays", () => {
|
|
52
|
+
const view: MetricSavedView = new MetricSavedView();
|
|
53
|
+
view.name = "Hot services";
|
|
54
|
+
view.query = SAVED_STATE;
|
|
55
|
+
|
|
56
|
+
const json: JSONObject = BaseModel.toJSON(view, MetricSavedView);
|
|
57
|
+
const filters: JSONArray = readFiltersFromJSON(json);
|
|
58
|
+
|
|
59
|
+
expect(Array.isArray(filters)).toBe(true);
|
|
60
|
+
expect(Array.isArray(filters[0])).toBe(true);
|
|
61
|
+
expect(filters).toEqual(SAVED_STATE.filters);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("A serialized view is still readable by the explorer", () => {
|
|
65
|
+
const view: TraceSavedView = new TraceSavedView();
|
|
66
|
+
view.query = SAVED_STATE;
|
|
67
|
+
|
|
68
|
+
const json: JSONObject = BaseModel.toJSON(view, TraceSavedView);
|
|
69
|
+
|
|
70
|
+
expect(readSavedViewFilters(readFiltersFromJSON(json))).toEqual(
|
|
71
|
+
SAVED_STATE.filters,
|
|
72
|
+
);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test("The rest of the saved state is untouched", () => {
|
|
76
|
+
const view: TraceSavedView = new TraceSavedView();
|
|
77
|
+
view.query = SAVED_STATE;
|
|
78
|
+
|
|
79
|
+
const query: JSONObject = BaseModel.toJSON(view, TraceSavedView)[
|
|
80
|
+
"query"
|
|
81
|
+
] as JSONObject;
|
|
82
|
+
|
|
83
|
+
expect(query["search"]).toBe("status:error");
|
|
84
|
+
expect(query["pageSize"]).toBe(50);
|
|
85
|
+
expect(query["rootOnly"]).toBe(false);
|
|
86
|
+
expect(query["timeRange"]).toEqual({ range: "Past one hour" });
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("A view survives two passes, the way it does browser-to-API-to-browser", () => {
|
|
90
|
+
const view: TraceSavedView = new TraceSavedView();
|
|
91
|
+
view.query = SAVED_STATE;
|
|
92
|
+
|
|
93
|
+
// Write side (browser -> API), then read side (API -> browser).
|
|
94
|
+
const written: JSONObject = BaseModel.toJSON(view, TraceSavedView);
|
|
95
|
+
const reloaded: TraceSavedView = BaseModel.fromJSON(
|
|
96
|
+
written,
|
|
97
|
+
TraceSavedView,
|
|
98
|
+
) as TraceSavedView;
|
|
99
|
+
const returned: JSONObject = BaseModel.toJSON(reloaded, TraceSavedView);
|
|
100
|
+
|
|
101
|
+
expect(readFiltersFromJSON(returned)).toEqual(SAVED_STATE.filters);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("A view with no filters serializes without inventing any", () => {
|
|
105
|
+
const view: TraceSavedView = new TraceSavedView();
|
|
106
|
+
view.query = { search: "status:error" };
|
|
107
|
+
|
|
108
|
+
const query: JSONObject = BaseModel.toJSON(view, TraceSavedView)[
|
|
109
|
+
"query"
|
|
110
|
+
] as JSONObject;
|
|
111
|
+
|
|
112
|
+
expect(query["filters"]).toBeUndefined();
|
|
113
|
+
expect(readSavedViewFilters(query["filters"])).toEqual([]);
|
|
114
|
+
});
|
|
115
|
+
});
|