@oneuptime/common 12.0.6 → 12.0.7
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/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/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/Index.ts +6 -0
- 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/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 +41 -2
- 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/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/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/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/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/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/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/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/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/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/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/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 +1 -1
- package/Tests/UI/Components/MasterPage.test.tsx +1 -1
- package/Tests/UI/Components/ModalPortalDismissal.test.tsx +489 -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 +1 -1
- package/Tests/UI/Components/TextArea.test.tsx +1 -1
- 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/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/Realtime.test.ts +78 -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/Telemetry/TelemetrySavedViewState.ts +9 -1
- package/Types/Workflow/Components/BaseModel.ts +92 -28
- package/Typings/Index.d.ts +12 -0
- package/UI/Components/GanttChart/ChartContainer.tsx +4 -3
- package/UI/Components/Modal/ConfirmModal.tsx +10 -5
- package/UI/Components/Modal/Modal.tsx +27 -47
- package/UI/Components/ModelDelete/ModelDelete.tsx +23 -6
- package/UI/Components/SideOver/SideOver.tsx +195 -68
- 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/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/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/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/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.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/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 +35 -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/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/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/Workflow/Components/BaseModel.js +83 -28
- package/build/dist/Types/Workflow/Components/BaseModel.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/Modal/ConfirmModal.js +3 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +24 -34
- 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/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/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,89 @@
|
|
|
1
|
+
import BaseModel from "../../../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
2
|
+
import logger from "../../../../Utils/Logger";
|
|
3
|
+
import { RunOptions } from "../../ComponentCode";
|
|
4
|
+
import {
|
|
5
|
+
ID_ARGUMENT_KEY,
|
|
6
|
+
PRIMARY_KEY_COLUMN,
|
|
7
|
+
describeModelColumns,
|
|
8
|
+
} from "./ModelArguments";
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* TypeORM's EntityPropertyNotFoundError reads
|
|
12
|
+
* `Property "foo" was not found in "Monitor". Make sure your query is correct.`
|
|
13
|
+
* On its own that tells a workflow builder nothing they can act on: it names
|
|
14
|
+
* neither the argument at fault nor anything they can pick from, and it says
|
|
15
|
+
* "query" even when the offending key was in Data. Everything the builder
|
|
16
|
+
* needs is already on the model, so the components append it.
|
|
17
|
+
*/
|
|
18
|
+
const UNKNOWN_PROPERTY_PATTERN: RegExp =
|
|
19
|
+
/Property "([^"]+)" was not found in "([^"]+)"/;
|
|
20
|
+
|
|
21
|
+
type BuildColumnHintFunction = (
|
|
22
|
+
message: string,
|
|
23
|
+
model: BaseModel,
|
|
24
|
+
) => string | null;
|
|
25
|
+
|
|
26
|
+
export const buildColumnHint: BuildColumnHintFunction = (
|
|
27
|
+
message: string,
|
|
28
|
+
model: BaseModel,
|
|
29
|
+
): string | null => {
|
|
30
|
+
const match: RegExpMatchArray | null = message.match(
|
|
31
|
+
UNKNOWN_PROPERTY_PATTERN,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
if (!match) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const property: string = match[1] as string;
|
|
39
|
+
const modelName: string = model.singularName || (match[2] as string);
|
|
40
|
+
|
|
41
|
+
if (property === ID_ARGUMENT_KEY) {
|
|
42
|
+
return `Tip: "${ID_ARGUMENT_KEY}" is not a column on ${modelName}. Use "${PRIMARY_KEY_COLUMN}" instead. Columns you can use: ${describeModelColumns(
|
|
43
|
+
model,
|
|
44
|
+
)}.`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return `Tip: "${property}" is not a column on ${modelName}. Check every key in this component's Query, Select and Data arguments. Columns you can use: ${describeModelColumns(
|
|
48
|
+
model,
|
|
49
|
+
)}.`;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
type LogComponentErrorFunction = (data: {
|
|
53
|
+
error: unknown;
|
|
54
|
+
model: BaseModel | null;
|
|
55
|
+
log: RunOptions["log"];
|
|
56
|
+
}) => void;
|
|
57
|
+
|
|
58
|
+
/*
|
|
59
|
+
* Every database component failed the same way before this: two lines in the
|
|
60
|
+
* workflow log and, for all but Create One, nothing at all in the server log.
|
|
61
|
+
*/
|
|
62
|
+
const logComponentError: LogComponentErrorFunction = (data: {
|
|
63
|
+
error: unknown;
|
|
64
|
+
model: BaseModel | null;
|
|
65
|
+
log: RunOptions["log"];
|
|
66
|
+
}): void => {
|
|
67
|
+
const { error, model, log } = data;
|
|
68
|
+
|
|
69
|
+
logger.error(error);
|
|
70
|
+
|
|
71
|
+
const errorMessage: unknown = (error as { message?: unknown } | null)
|
|
72
|
+
?.message;
|
|
73
|
+
|
|
74
|
+
const message: string =
|
|
75
|
+
typeof errorMessage === "string" && errorMessage
|
|
76
|
+
? errorMessage
|
|
77
|
+
: JSON.stringify(error, null, 2);
|
|
78
|
+
|
|
79
|
+
log("Error running component");
|
|
80
|
+
log(message);
|
|
81
|
+
|
|
82
|
+
const hint: string | null = model ? buildColumnHint(message, model) : null;
|
|
83
|
+
|
|
84
|
+
if (hint) {
|
|
85
|
+
log(hint);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export default logComponentError;
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import BaseModel from "../../../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
2
|
+
import { TableColumnMetadata } from "../../../../../Types/Database/TableColumn";
|
|
3
|
+
import TableColumnType from "../../../../../Types/Database/TableColumnType";
|
|
4
|
+
import { JSONObject, JSONValue } from "../../../../../Types/JSON";
|
|
5
|
+
import ObjectID from "../../../../../Types/ObjectID";
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
* Workflow builders write "id", because that is what an ID is called
|
|
9
|
+
* everywhere they can see one: in the dashboard, in the API docs, and on the
|
|
10
|
+
* model itself (`monitor.id`). On a database model, though, "id" is only a
|
|
11
|
+
* TypeScript accessor - the persisted primary key column is "_id"
|
|
12
|
+
* (DatabaseBaseModel._id). A query, select or data object keyed on "id"
|
|
13
|
+
* therefore reached TypeORM verbatim and threw
|
|
14
|
+
* `Property "id" was not found in "Monitor". Make sure your query is correct.`,
|
|
15
|
+
* which is what https://github.com/OneUptime/oneuptime/issues/3132 reported.
|
|
16
|
+
*
|
|
17
|
+
* The create path has accepted "id" all along - DatabaseBaseModel._fromJSON
|
|
18
|
+
* rewrites it to "_id" - so the fix is to make every other workflow argument
|
|
19
|
+
* agree with create, rather than to take the alias away from create.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
export const ID_ARGUMENT_KEY: string = "id";
|
|
23
|
+
export const PRIMARY_KEY_COLUMN: string = "_id";
|
|
24
|
+
|
|
25
|
+
/*
|
|
26
|
+
* Only alias when the model actually looks like a DatabaseBaseModel: it has
|
|
27
|
+
* the "_id" primary key and no column of its own literally called "id".
|
|
28
|
+
* No model ships an "id" column today, but a model that grew one would mean
|
|
29
|
+
* something different by "id" and must keep it.
|
|
30
|
+
*/
|
|
31
|
+
type ModelAliasesIdFunction = (model: BaseModel) => boolean;
|
|
32
|
+
|
|
33
|
+
const modelAliasesId: ModelAliasesIdFunction = (model: BaseModel): boolean => {
|
|
34
|
+
return (
|
|
35
|
+
model.hasColumn(PRIMARY_KEY_COLUMN) && !model.hasColumn(ID_ARGUMENT_KEY)
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/*
|
|
40
|
+
* A nested object is only worth walking into when it is a map of column names.
|
|
41
|
+
* Serialized values - ObjectID, Date, and every QueryHelper operator - travel
|
|
42
|
+
* as `{ "_type": "...", "value": ... }` and are values, not column maps, so
|
|
43
|
+
* key rewriting has to stop at them.
|
|
44
|
+
*/
|
|
45
|
+
type IsColumnMapFunction = (value: JSONValue) => boolean;
|
|
46
|
+
|
|
47
|
+
const isColumnMap: IsColumnMapFunction = (value: JSONValue): boolean => {
|
|
48
|
+
if (value === null || value === undefined || typeof value !== "object") {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (Array.isArray(value) || value instanceof Date) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return (value as JSONObject)["_type"] === undefined;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
type NormalizeValueFunction = (
|
|
60
|
+
value: JSONValue,
|
|
61
|
+
columnName: string,
|
|
62
|
+
model: BaseModel,
|
|
63
|
+
) => JSONValue;
|
|
64
|
+
|
|
65
|
+
/*
|
|
66
|
+
* Relations are queried and selected one level deep - `{"project": {"id":
|
|
67
|
+
* true}}` - so the alias has to follow the relation into the related model
|
|
68
|
+
* rather than stopping at the top level.
|
|
69
|
+
*/
|
|
70
|
+
const normalizeValue: NormalizeValueFunction = (
|
|
71
|
+
value: JSONValue,
|
|
72
|
+
columnName: string,
|
|
73
|
+
model: BaseModel,
|
|
74
|
+
): JSONValue => {
|
|
75
|
+
if (!isColumnMap(value)) {
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const metadata: TableColumnMetadata | undefined =
|
|
80
|
+
model.getTableColumnMetadata(columnName);
|
|
81
|
+
|
|
82
|
+
if (
|
|
83
|
+
!metadata ||
|
|
84
|
+
!metadata.modelType ||
|
|
85
|
+
(metadata.type !== TableColumnType.Entity &&
|
|
86
|
+
metadata.type !== TableColumnType.EntityArray)
|
|
87
|
+
) {
|
|
88
|
+
return value;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return normalizeModelKeys(value as JSONObject, new metadata.modelType());
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
type NormalizeModelKeysFunction = (
|
|
95
|
+
json: JSONObject,
|
|
96
|
+
model: BaseModel,
|
|
97
|
+
) => JSONObject;
|
|
98
|
+
|
|
99
|
+
/*
|
|
100
|
+
* Returns a copy of `json` with the "id" alias resolved to the "_id" column,
|
|
101
|
+
* including inside related-model objects one level down. Everything else is
|
|
102
|
+
* copied through untouched - this deliberately does not validate column names,
|
|
103
|
+
* so an argument that works today keeps working.
|
|
104
|
+
*/
|
|
105
|
+
export const normalizeModelKeys: NormalizeModelKeysFunction = (
|
|
106
|
+
json: JSONObject,
|
|
107
|
+
model: BaseModel,
|
|
108
|
+
): JSONObject => {
|
|
109
|
+
const normalized: JSONObject = {};
|
|
110
|
+
const aliasesId: boolean = modelAliasesId(model);
|
|
111
|
+
|
|
112
|
+
/*
|
|
113
|
+
* Someone who spells out "_id" meant "_id". If both spellings are present
|
|
114
|
+
* the explicit column wins and the alias is dropped, so the result never
|
|
115
|
+
* depends on key order.
|
|
116
|
+
*/
|
|
117
|
+
const explicitPrimaryKeyGiven: boolean =
|
|
118
|
+
json[PRIMARY_KEY_COLUMN] !== undefined;
|
|
119
|
+
|
|
120
|
+
for (const key of Object.keys(json)) {
|
|
121
|
+
let columnName: string = key;
|
|
122
|
+
|
|
123
|
+
if (key === ID_ARGUMENT_KEY && aliasesId) {
|
|
124
|
+
if (explicitPrimaryKeyGiven) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
columnName = PRIMARY_KEY_COLUMN;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
normalized[columnName] = normalizeValue(
|
|
132
|
+
json[key] as JSONValue,
|
|
133
|
+
columnName,
|
|
134
|
+
model,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return normalized;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
type ApplyTenantColumnFunction = (
|
|
142
|
+
json: JSONObject,
|
|
143
|
+
model: BaseModel,
|
|
144
|
+
tenantId: ObjectID,
|
|
145
|
+
) => JSONObject;
|
|
146
|
+
|
|
147
|
+
/*
|
|
148
|
+
* Stamps the record being written with the project the workflow runs in.
|
|
149
|
+
*
|
|
150
|
+
* Setting the scalar tenant column is not enough on its own. Every tenant
|
|
151
|
+
* model also exposes that same physical column through its many-to-one
|
|
152
|
+
* relation - Monitor.project is @JoinColumn({name: "projectId"}) - and TypeORM
|
|
153
|
+
* reads the relation property first, writing the column once. So a payload
|
|
154
|
+
* carrying {"project": "<some other project>"} silently beat the stamp and
|
|
155
|
+
* moved the record into that project. The relation keys pointing at the tenant
|
|
156
|
+
* column are therefore dropped before the scalar is written.
|
|
157
|
+
*/
|
|
158
|
+
export const applyTenantColumn: ApplyTenantColumnFunction = (
|
|
159
|
+
json: JSONObject,
|
|
160
|
+
model: BaseModel,
|
|
161
|
+
tenantId: ObjectID,
|
|
162
|
+
): JSONObject => {
|
|
163
|
+
const tenantColumn: string | null = model.getTenantColumn();
|
|
164
|
+
|
|
165
|
+
if (!tenantColumn) {
|
|
166
|
+
return json;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const stamped: JSONObject = {};
|
|
170
|
+
|
|
171
|
+
for (const key of Object.keys(json)) {
|
|
172
|
+
if (key === tenantColumn) {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const metadata: TableColumnMetadata | undefined =
|
|
177
|
+
model.getTableColumnMetadata(key);
|
|
178
|
+
|
|
179
|
+
if (metadata && metadata.manyToOneRelationColumn === tenantColumn) {
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
stamped[key] = json[key];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
stamped[tenantColumn] = tenantId;
|
|
187
|
+
|
|
188
|
+
return stamped;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
type DescribeModelColumnsFunction = (model: BaseModel) => string;
|
|
192
|
+
|
|
193
|
+
/*
|
|
194
|
+
* The raw TypeORM failure ("Property "foo" was not found in "Monitor") names
|
|
195
|
+
* neither the argument at fault nor anything the builder can pick from, so the
|
|
196
|
+
* components append the real column list to it.
|
|
197
|
+
*/
|
|
198
|
+
export const describeModelColumns: DescribeModelColumnsFunction = (
|
|
199
|
+
model: BaseModel,
|
|
200
|
+
): string => {
|
|
201
|
+
const columns: Array<string> = [...model.getTableColumns().columns].sort(
|
|
202
|
+
(a: string, b: string): number => {
|
|
203
|
+
return a.localeCompare(b);
|
|
204
|
+
},
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
return columns.join(", ");
|
|
208
|
+
};
|
|
@@ -24,6 +24,7 @@ import ComponentMetadata, {
|
|
|
24
24
|
import BaseModelComponents from "../../../../../Types/Workflow/Components/BaseModel";
|
|
25
25
|
import Workflow from "../../../../../Models/DatabaseModels/Workflow";
|
|
26
26
|
import CaptureSpan from "../../../../Utils/Telemetry/CaptureSpan";
|
|
27
|
+
import { normalizeModelKeys } from "./ModelArguments";
|
|
27
28
|
|
|
28
29
|
export default class OnTriggerBaseModel<
|
|
29
30
|
TBaseModel extends BaseModel,
|
|
@@ -156,6 +157,16 @@ export default class OnTriggerBaseModel<
|
|
|
156
157
|
(select as any)[key] = false;
|
|
157
158
|
}
|
|
158
159
|
}
|
|
160
|
+
|
|
161
|
+
/*
|
|
162
|
+
* "id" is only a TypeScript accessor on the model - the column is "_id".
|
|
163
|
+
* Selecting "id" reached TypeORM verbatim and threw, and this trigger
|
|
164
|
+
* has no error port, so it took the whole workflow run down with it.
|
|
165
|
+
*/
|
|
166
|
+
select = normalizeModelKeys(
|
|
167
|
+
select as JSONObject,
|
|
168
|
+
this.service!.getModel(),
|
|
169
|
+
) as Select<TBaseModel>;
|
|
159
170
|
}
|
|
160
171
|
|
|
161
172
|
const model: TBaseModel | null = await this.service!.findOneById({
|
|
@@ -14,6 +14,8 @@ import ComponentMetadata, {
|
|
|
14
14
|
} from "../../../../../Types/Workflow/Component";
|
|
15
15
|
import BaseModelComponents from "../../../../../Types/Workflow/Components/BaseModel";
|
|
16
16
|
import CaptureSpan from "../../../../Utils/Telemetry/CaptureSpan";
|
|
17
|
+
import { applyTenantColumn, normalizeModelKeys } from "./ModelArguments";
|
|
18
|
+
import logComponentError from "./LogComponentError";
|
|
17
19
|
|
|
18
20
|
export default class UpdateManyBaseModel<
|
|
19
21
|
TBaseModel extends BaseModel,
|
|
@@ -92,11 +94,14 @@ export default class UpdateManyBaseModel<
|
|
|
92
94
|
);
|
|
93
95
|
}
|
|
94
96
|
|
|
95
|
-
|
|
96
|
-
(
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
args["data"] = applyTenantColumn(
|
|
98
|
+
normalizeModelKeys(
|
|
99
|
+
args["data"] as JSONObject,
|
|
100
|
+
this.modelService.getModel(),
|
|
101
|
+
),
|
|
102
|
+
this.modelService.getModel(),
|
|
103
|
+
options.projectId,
|
|
104
|
+
);
|
|
100
105
|
|
|
101
106
|
if (!args["query"]) {
|
|
102
107
|
throw options.onError(new BadDataException("Query is undefined."));
|
|
@@ -137,22 +142,28 @@ export default class UpdateManyBaseModel<
|
|
|
137
142
|
args["limit"] = LIMIT_PER_PROJECT;
|
|
138
143
|
}
|
|
139
144
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if (query) {
|
|
143
|
-
query = JSONFunctions.deserialize(
|
|
145
|
+
const query: Query<TBaseModel> = JSONFunctions.deserialize(
|
|
146
|
+
normalizeModelKeys(
|
|
144
147
|
args["query"] as JSONObject,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
+
this.modelService.getModel(),
|
|
149
|
+
),
|
|
150
|
+
) as Query<TBaseModel>;
|
|
151
|
+
|
|
152
|
+
/*
|
|
153
|
+
* The tenant column goes on the deserialized query, not on args["query"].
|
|
154
|
+
* JSONFunctions.deserialize returns a new object, so writing the tenant
|
|
155
|
+
* column to args afterwards left the query that actually ran unscoped -
|
|
156
|
+
* and an update as root is not re-scoped by the permission layer, so an
|
|
157
|
+
* Update Many could reach rows in other projects.
|
|
158
|
+
*/
|
|
148
159
|
if (this.modelService.getModel().getTenantColumn()) {
|
|
149
|
-
(
|
|
160
|
+
(query as JSONObject)[
|
|
150
161
|
this.modelService.getModel().getTenantColumn() as string
|
|
151
162
|
] = options.projectId;
|
|
152
163
|
}
|
|
153
164
|
|
|
154
|
-
await this.modelService.updateBy({
|
|
155
|
-
query: query
|
|
165
|
+
const itemsUpdated: number = await this.modelService.updateBy({
|
|
166
|
+
query: query,
|
|
156
167
|
data: args["data"] as QueryDeepPartialEntity<TBaseModel>,
|
|
157
168
|
limit: new PositiveNumber(args["limit"] as number),
|
|
158
169
|
skip: new PositiveNumber(args["skip"] as number),
|
|
@@ -162,13 +173,25 @@ export default class UpdateManyBaseModel<
|
|
|
162
173
|
},
|
|
163
174
|
});
|
|
164
175
|
|
|
176
|
+
options.log(
|
|
177
|
+
`Updated ${itemsUpdated} ${
|
|
178
|
+
this.modelService.getModel().singularName || "record"
|
|
179
|
+
}(s).`,
|
|
180
|
+
);
|
|
181
|
+
|
|
165
182
|
return {
|
|
166
|
-
returnValues: {
|
|
183
|
+
returnValues: {
|
|
184
|
+
"items-updated": itemsUpdated,
|
|
185
|
+
},
|
|
167
186
|
executePort: successPort,
|
|
168
187
|
};
|
|
169
188
|
} catch (err: any) {
|
|
170
|
-
|
|
171
|
-
|
|
189
|
+
logComponentError({
|
|
190
|
+
error: err,
|
|
191
|
+
model: this.modelService?.getModel() || null,
|
|
192
|
+
log: options.log,
|
|
193
|
+
});
|
|
194
|
+
|
|
172
195
|
return {
|
|
173
196
|
returnValues: {},
|
|
174
197
|
executePort: errorPort,
|
|
@@ -12,6 +12,8 @@ import ComponentMetadata, {
|
|
|
12
12
|
} from "../../../../../Types/Workflow/Component";
|
|
13
13
|
import BaseModelComponents from "../../../../../Types/Workflow/Components/BaseModel";
|
|
14
14
|
import CaptureSpan from "../../../../Utils/Telemetry/CaptureSpan";
|
|
15
|
+
import { applyTenantColumn, normalizeModelKeys } from "./ModelArguments";
|
|
16
|
+
import logComponentError from "./LogComponentError";
|
|
15
17
|
|
|
16
18
|
export default class UpdateOneBaseModel<
|
|
17
19
|
TBaseModel extends BaseModel,
|
|
@@ -90,11 +92,14 @@ export default class UpdateOneBaseModel<
|
|
|
90
92
|
);
|
|
91
93
|
}
|
|
92
94
|
|
|
93
|
-
|
|
94
|
-
(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
args["data"] = applyTenantColumn(
|
|
96
|
+
normalizeModelKeys(
|
|
97
|
+
args["data"] as JSONObject,
|
|
98
|
+
this.modelService.getModel(),
|
|
99
|
+
),
|
|
100
|
+
this.modelService.getModel(),
|
|
101
|
+
options.projectId,
|
|
102
|
+
);
|
|
98
103
|
|
|
99
104
|
if (!args["query"]) {
|
|
100
105
|
throw options.onError(new BadDataException("Query is undefined."));
|
|
@@ -110,22 +115,26 @@ export default class UpdateOneBaseModel<
|
|
|
110
115
|
);
|
|
111
116
|
}
|
|
112
117
|
|
|
118
|
+
const query: Query<TBaseModel> = JSONFunctions.deserialize(
|
|
119
|
+
normalizeModelKeys(
|
|
120
|
+
args["query"] as JSONObject,
|
|
121
|
+
this.modelService.getModel(),
|
|
122
|
+
),
|
|
123
|
+
) as Query<TBaseModel>;
|
|
124
|
+
|
|
125
|
+
/*
|
|
126
|
+
* The tenant column goes on the deserialized query, not on args["query"]
|
|
127
|
+
* - JSONFunctions.deserialize returns a new object, so anything written
|
|
128
|
+
* to args after it runs never reaches the database.
|
|
129
|
+
*/
|
|
113
130
|
if (this.modelService.getModel().getTenantColumn()) {
|
|
114
|
-
(
|
|
131
|
+
(query as JSONObject)[
|
|
115
132
|
this.modelService.getModel().getTenantColumn() as string
|
|
116
133
|
] = options.projectId;
|
|
117
134
|
}
|
|
118
135
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (query) {
|
|
122
|
-
query = JSONFunctions.deserialize(
|
|
123
|
-
args["query"] as JSONObject,
|
|
124
|
-
) as Query<TBaseModel>;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
await this.modelService.updateOneBy({
|
|
128
|
-
query: query || {},
|
|
136
|
+
const itemsUpdated: number = await this.modelService.updateOneBy({
|
|
137
|
+
query: query,
|
|
129
138
|
data: args["data"] as QueryDeepPartialEntity<TBaseModel>,
|
|
130
139
|
props: {
|
|
131
140
|
isRoot: true,
|
|
@@ -133,13 +142,30 @@ export default class UpdateOneBaseModel<
|
|
|
133
142
|
},
|
|
134
143
|
});
|
|
135
144
|
|
|
145
|
+
/*
|
|
146
|
+
* A query that matches nothing is not an error, but reporting it as a
|
|
147
|
+
* bare success left builders with no way to tell "updated" from "found
|
|
148
|
+
* nothing to update".
|
|
149
|
+
*/
|
|
150
|
+
options.log(
|
|
151
|
+
`Updated ${itemsUpdated} ${
|
|
152
|
+
this.modelService.getModel().singularName || "record"
|
|
153
|
+
}(s).`,
|
|
154
|
+
);
|
|
155
|
+
|
|
136
156
|
return {
|
|
137
|
-
returnValues: {
|
|
157
|
+
returnValues: {
|
|
158
|
+
"items-updated": itemsUpdated,
|
|
159
|
+
},
|
|
138
160
|
executePort: successPort,
|
|
139
161
|
};
|
|
140
162
|
} catch (err: any) {
|
|
141
|
-
|
|
142
|
-
|
|
163
|
+
logComponentError({
|
|
164
|
+
error: err,
|
|
165
|
+
model: this.modelService?.getModel() || null,
|
|
166
|
+
log: options.log,
|
|
167
|
+
});
|
|
168
|
+
|
|
143
169
|
return {
|
|
144
170
|
returnValues: {},
|
|
145
171
|
executePort: errorPort,
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import ComponentCode, { RunOptions, RunReturnType } from "../../ComponentCode";
|
|
2
|
+
import IncomingWebhookUtils, {
|
|
3
|
+
DISCORD_WEBHOOK_DOMAINS,
|
|
4
|
+
} from "../IncomingWebhookUtils";
|
|
2
5
|
import HTTPErrorResponse from "../../../../../Types/API/HTTPErrorResponse";
|
|
3
6
|
import HTTPResponse from "../../../../../Types/API/HTTPResponse";
|
|
4
7
|
import URL from "../../../../../Types/API/URL";
|
|
@@ -59,15 +62,12 @@ export default class SendMessageToChannel extends ComponentCode {
|
|
|
59
62
|
throw options.onError(new BadDataException("Discord message not found"));
|
|
60
63
|
}
|
|
61
64
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
args["webhook-url"] = URL.fromString(
|
|
69
|
-
args["webhook-url"]?.toString() as string,
|
|
70
|
-
);
|
|
65
|
+
args["webhook-url"] = IncomingWebhookUtils.getPinnedWebhookUrl({
|
|
66
|
+
args,
|
|
67
|
+
options,
|
|
68
|
+
allowedDomains: DISCORD_WEBHOOK_DOMAINS,
|
|
69
|
+
vendorName: "Discord",
|
|
70
|
+
});
|
|
71
71
|
|
|
72
72
|
let apiResult: HTTPResponse<JSONObject> | HTTPErrorResponse | null = null;
|
|
73
73
|
|
|
@@ -78,6 +78,13 @@ export default class SendMessageToChannel extends ComponentCode {
|
|
|
78
78
|
data: {
|
|
79
79
|
content: args["text"] as string,
|
|
80
80
|
},
|
|
81
|
+
/*
|
|
82
|
+
* The host is pinned above; following a redirect would hand the
|
|
83
|
+
* destination back to whoever controls that host.
|
|
84
|
+
*/
|
|
85
|
+
options: {
|
|
86
|
+
doNotFollowRedirects: true,
|
|
87
|
+
},
|
|
81
88
|
});
|
|
82
89
|
|
|
83
90
|
if (apiResult instanceof HTTPErrorResponse) {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { RunOptions } from "../ComponentCode";
|
|
2
|
+
import URL from "../../../../Types/API/URL";
|
|
3
|
+
import BadDataException from "../../../../Types/Exception/BadDataException";
|
|
4
|
+
import { JSONObject } from "../../../../Types/JSON";
|
|
5
|
+
import SSRFProtection from "../../../Utils/SSRFProtection";
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
* The Slack / Discord / Microsoft Teams workflow components each take a
|
|
9
|
+
* free-text "webhook-url" argument off the workflow graph, which any project
|
|
10
|
+
* member can author and which can additionally be templated from trigger data.
|
|
11
|
+
* They then POST to it from the API server - the same SSRF primitive that
|
|
12
|
+
* GHSA-v5xh-rw9h-77fv reported against the API components.
|
|
13
|
+
*
|
|
14
|
+
* These are chat webhooks, so unlike the generic API components there is a
|
|
15
|
+
* vendor host to pin to, and a pin is strictly better than a blocklist: it
|
|
16
|
+
* cannot be walked around with DNS rebinding, an alternate IP notation, or a
|
|
17
|
+
* redirect. Nothing legitimate is lost - a self-hosted OneUptime still posts to
|
|
18
|
+
* hooks.slack.com like everyone else.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export const DISCORD_WEBHOOK_DOMAINS: Array<string> = [
|
|
22
|
+
"discord.com",
|
|
23
|
+
"discordapp.com",
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
export class IncomingWebhookUtils {
|
|
27
|
+
/*
|
|
28
|
+
* Reads the component's "webhook-url" argument, requires it to be on one of
|
|
29
|
+
* `allowedDomains`, and returns it parsed. Throws through options.onError so
|
|
30
|
+
* the workflow stops with a message the author can act on.
|
|
31
|
+
*
|
|
32
|
+
* Validates the RAW string: URL.fromString defaults an unrecognized scheme to
|
|
33
|
+
* https, so converting first would let "gopher://..." arrive looking clean.
|
|
34
|
+
*/
|
|
35
|
+
public static getPinnedWebhookUrl(data: {
|
|
36
|
+
args: JSONObject;
|
|
37
|
+
options: RunOptions;
|
|
38
|
+
allowedDomains: Array<string>;
|
|
39
|
+
vendorName: string;
|
|
40
|
+
}): URL {
|
|
41
|
+
const rawUrl: unknown = data.args["webhook-url"];
|
|
42
|
+
|
|
43
|
+
if (!rawUrl) {
|
|
44
|
+
throw data.options.onError(
|
|
45
|
+
new BadDataException(`${data.vendorName} Webhook URL not found`),
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (
|
|
50
|
+
!SSRFProtection.isUrlOnAllowedDomain(
|
|
51
|
+
rawUrl.toString(),
|
|
52
|
+
data.allowedDomains,
|
|
53
|
+
)
|
|
54
|
+
) {
|
|
55
|
+
throw data.options.onError(
|
|
56
|
+
new BadDataException(
|
|
57
|
+
`${data.vendorName} Webhook URL must be an https URL on ${data.allowedDomains.join(" or ")}.`,
|
|
58
|
+
),
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return URL.fromString(rawUrl.toString());
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export default IncomingWebhookUtils;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import ComponentCode, { RunOptions, RunReturnType } from "../../ComponentCode";
|
|
2
|
+
import IncomingWebhookUtils from "../IncomingWebhookUtils";
|
|
3
|
+
import { MICROSOFT_TEAMS_WEBHOOK_DOMAINS } from "../../../../Utils/Workspace/MicrosoftTeams/MicrosoftTeams";
|
|
2
4
|
import HTTPErrorResponse from "../../../../../Types/API/HTTPErrorResponse";
|
|
3
5
|
import HTTPResponse from "../../../../../Types/API/HTTPResponse";
|
|
4
6
|
import URL from "../../../../../Types/API/URL";
|
|
@@ -60,15 +62,12 @@ export default class SendMessageToChannel extends ComponentCode {
|
|
|
60
62
|
);
|
|
61
63
|
}
|
|
62
64
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
args["webhook-url"] = URL.fromString(
|
|
70
|
-
args["webhook-url"]?.toString() as string,
|
|
71
|
-
);
|
|
65
|
+
args["webhook-url"] = IncomingWebhookUtils.getPinnedWebhookUrl({
|
|
66
|
+
args,
|
|
67
|
+
options,
|
|
68
|
+
allowedDomains: MICROSOFT_TEAMS_WEBHOOK_DOMAINS,
|
|
69
|
+
vendorName: "Microsoft Teams",
|
|
70
|
+
});
|
|
72
71
|
|
|
73
72
|
let apiResult: HTTPResponse<JSONObject> | HTTPErrorResponse | null = null;
|
|
74
73
|
|
|
@@ -100,6 +99,13 @@ export default class SendMessageToChannel extends ComponentCode {
|
|
|
100
99
|
},
|
|
101
100
|
],
|
|
102
101
|
},
|
|
102
|
+
/*
|
|
103
|
+
* The host is pinned above; following a redirect would hand the
|
|
104
|
+
* destination back to whoever controls that host.
|
|
105
|
+
*/
|
|
106
|
+
options: {
|
|
107
|
+
doNotFollowRedirects: true,
|
|
108
|
+
},
|
|
103
109
|
});
|
|
104
110
|
|
|
105
111
|
if (apiResult instanceof HTTPErrorResponse) {
|