From 9a35e400831792084abd369e4e1e2d019fbdfb6e Mon Sep 17 00:00:00 2001 From: Matt Batchelder Date: Mon, 23 Mar 2026 21:28:14 -0400 Subject: [PATCH] feat: Add initial deployment setup for OTSSignsOrchestrator - Create index.html for the web application interface. - Implement deploy.sh script for building and deploying the application to a Docker Swarm manager. - Add docker-compose.yml for defining application and PostgreSQL service configurations. --- .dockerignore | 42 + .env.example | 50 +- .github/copilot-instructions.md | 79 +- .gitignore | 32 +- CLAUDE.md | 125 + Dockerfile | 51 + .../Data/DesignTimeDbContextFactory.cs | 27 - OTSSignsOrchestrator.Core/Data/XiboContext.cs | 53 - .../20260217004115_DesktopInitial.Designer.cs | 290 -- .../20260217004115_DesktopInitial.cs | 175 - ...260218140239_AddCustomerAbbrev.Designer.cs | 295 -- .../20260218140239_AddCustomerAbbrev.cs | 30 - .../20260218143812_AddAppSettings.Designer.cs | 323 -- .../20260218143812_AddAppSettings.cs | 42 - ..._AddPerInstanceCifsCredentials.Designer.cs | 343 -- ...218144537_AddPerInstanceCifsCredentials.cs | 73 - ...RenameShareBasePathToShareName.Designer.cs | 343 -- ...18180240_RenameShareBasePathToShareName.cs | 28 - ...60218202617_AddCifsShareFolder.Designer.cs | 347 -- .../20260218202617_AddCifsShareFolder.cs | 29 - ...60219005507_ReplaceCifsWithNfs.Designer.cs | 339 -- .../20260219005507_ReplaceCifsWithNfs.cs | 98 - ...60219020727_AddNewtCredentials.Designer.cs | 347 -- .../20260219020727_AddNewtCredentials.cs | 40 - ...eCmsInstancesAndSecretMetadata.Designer.cs | 153 - ...529_RemoveCmsInstancesAndSecretMetadata.cs | 159 - ...20260225135644_DropAppSettings.Designer.cs | 125 - .../20260225135644_DropAppSettings.cs | 42 - .../Migrations/XiboContextModelSnapshot.cs | 122 - .../Models/Entities/AppSetting.cs | 23 - .../OTSSignsOrchestrator.Core.csproj | 29 - .../Services/IInvitationSetupService.cs | 57 - .../Services/InvitationSetupService.cs | 230 -- OTSSignsOrchestrator.Desktop/App.axaml | 184 - OTSSignsOrchestrator.Desktop/App.axaml.cs | 208 -- .../Assets/OTS-Signs.png | Bin 1078214 -> 0 bytes .../Models/LiveStackItem.cs | 31 - .../OTSSignsOrchestrator.Desktop.csproj | 62 - OTSSignsOrchestrator.Desktop/Program.cs | 40 - .../Services/IServerApiClient.cs | 152 - .../Services/ServerSignalRService.cs | 112 - .../Services/SignalRMessages.cs | 35 - .../Services/SshDockerCliService.cs | 780 ----- .../Services/TokenStoreService.cs | 268 -- .../ViewModels/CreateInstanceViewModel.cs | 362 -- .../ViewModels/HostsViewModel.cs | 276 -- .../ViewModels/InstanceDetailsViewModel.cs | 387 -- .../ViewModels/InstancesViewModel.cs | 627 ---- .../ViewModels/LogsViewModel.cs | 55 - .../ViewModels/MainWindowViewModel.cs | 71 - .../ViewModels/SecretsViewModel.cs | 68 - .../ViewModels/SettingsViewModel.cs | 584 ---- .../Views/ConfirmationDialog.axaml | 27 - .../Views/ConfirmationDialog.axaml.cs | 50 - .../Views/CreateInstanceView.axaml | 218 -- .../Views/CreateInstanceView.axaml.cs | 11 - .../Views/HostsView.axaml | 127 - .../Views/HostsView.axaml.cs | 11 - .../Views/InstanceDetailsWindow.axaml | 240 -- .../Views/InstanceDetailsWindow.axaml.cs | 22 - .../Views/InstancesView.axaml | 168 - .../Views/InstancesView.axaml.cs | 47 - .../Views/LogsView.axaml | 39 - .../Views/LogsView.axaml.cs | 11 - .../Views/MainWindow.axaml | 123 - .../Views/MainWindow.axaml.cs | 11 - .../Views/SecretsView.axaml | 48 - .../Views/SecretsView.axaml.cs | 11 - .../Views/SettingsView.axaml | 407 --- .../Views/SettingsView.axaml.cs | 11 - OTSSignsOrchestrator.Desktop/app.manifest | 13 - OTSSignsOrchestrator.Desktop/appsettings.json | 53 - .../ByoiCertExpiryThresholdTests.cs | 4 +- .../OTSSignsOrchestrator.Tests.csproj | 2 +- OTSSignsOrchestrator.sln | 54 +- OTSSignsOrchestrator/Api/AuditApi.cs | 46 + .../Api/CustomerPortalApi.cs | 12 +- OTSSignsOrchestrator/Api/CustomersApi.cs | 140 + .../Api/FleetApi.cs | 10 +- OTSSignsOrchestrator/Api/HealthApi.cs | 98 + OTSSignsOrchestrator/Api/HostsApi.cs | 121 + OTSSignsOrchestrator/Api/InstancesApi.cs | 185 + OTSSignsOrchestrator/Api/LogsApi.cs | 40 + OTSSignsOrchestrator/Api/OperatorsApi.cs | 100 + OTSSignsOrchestrator/Api/ProvisionApi.cs | 242 ++ OTSSignsOrchestrator/Api/SecretsApi.cs | 21 + OTSSignsOrchestrator/Api/SettingsApi.cs | 135 + .../Api/SignupApi.cs | 8 +- .../Auth/JwtOptions.cs | 2 +- .../Auth/OperatorAuthService.cs | 6 +- OTSSignsOrchestrator/ClientApp/index.html | 12 + .../ClientApp/package-lock.json | 3101 +++++++++++++++++ OTSSignsOrchestrator/ClientApp/package.json | 32 + OTSSignsOrchestrator/ClientApp/src/App.tsx | 56 + .../ClientApp/src/api/auditLogs.ts | 33 + .../ClientApp/src/api/auth.ts | 13 + .../ClientApp/src/api/client.ts | 61 + .../ClientApp/src/api/customers.ts | 75 + .../ClientApp/src/api/fleet.ts | 44 + .../ClientApp/src/api/healthEvents.ts | 39 + .../ClientApp/src/api/hosts.ts | 34 + .../ClientApp/src/api/instances.ts | 46 + .../ClientApp/src/api/jobs.ts | 41 + .../ClientApp/src/api/logs.ts | 26 + .../ClientApp/src/api/operators.ts | 27 + .../ClientApp/src/api/provision.ts | 50 + .../ClientApp/src/api/reports.ts | 31 + .../ClientApp/src/api/secrets.ts | 8 + .../ClientApp/src/api/settings.ts | 28 + .../src/components/jobs/JobProgressPanel.tsx | 129 + .../src/components/layout/AppShell.tsx | 38 + .../src/components/layout/Sidebar.tsx | 42 + .../src/components/shared/ConfirmDialog.tsx | 48 + .../src/components/shared/StatusBanner.tsx | 30 + .../ClientApp/src/hooks/useSignalR.ts | 59 + OTSSignsOrchestrator/ClientApp/src/index.css | 1 + OTSSignsOrchestrator/ClientApp/src/main.tsx | 22 + .../ClientApp/src/pages/AuditPage.tsx | 85 + .../src/pages/CreateInstancePage.tsx | 280 ++ .../src/pages/CustomerDetailPage.tsx | 284 ++ .../ClientApp/src/pages/CustomersPage.tsx | 258 ++ .../ClientApp/src/pages/FleetPage.tsx | 100 + .../ClientApp/src/pages/HealthPage.tsx | 185 + .../ClientApp/src/pages/HostsPage.tsx | 178 + .../ClientApp/src/pages/InstancesPage.tsx | 187 + .../ClientApp/src/pages/LoginPage.tsx | 61 + .../ClientApp/src/pages/LogsPage.tsx | 93 + .../ClientApp/src/pages/OperatorsPage.tsx | 166 + .../ClientApp/src/pages/ReportsPage.tsx | 199 ++ .../ClientApp/src/pages/SecretsPage.tsx | 51 + .../ClientApp/src/pages/SettingsPage.tsx | 123 + .../ClientApp/src/store/alertStore.ts | 29 + .../ClientApp/src/store/authStore.ts | 15 + .../ClientApp/src/store/jobProgressStore.ts | 36 + OTSSignsOrchestrator/ClientApp/tsconfig.json | 25 + .../ClientApp/tsconfig.tsbuildinfo | 1 + OTSSignsOrchestrator/ClientApp/vite.config.ts | 26 + .../Clients/IAuthentikClient.cs | 2 +- .../Clients/IXiboApiClient.cs | 2 +- .../Clients/XiboClientFactory.cs | 2 +- .../Configuration/AppConstants.cs | 2 +- .../Configuration/AppOptions.cs | 2 +- .../Data/Entities/AppSetting.cs | 20 + .../Data/Entities/AuditLog.cs | 2 +- .../Data/Entities/AuthentikMetrics.cs | 2 +- .../Data/Entities/ByoiConfig.cs | 2 +- .../Data/Entities/Customer.cs | 2 +- .../Data/Entities/HealthEvent.cs | 2 +- .../Data/Entities/Instance.cs | 2 +- .../Data/Entities/Job.cs | 2 +- .../Data/Entities/JobStep.cs | 2 +- .../Data/Entities/OauthAppRegistry.cs | 2 +- .../Data}/Entities/OperationLog.cs | 4 +- .../Data/Entities/Operator.cs | 2 +- .../Data/Entities/RefreshToken.cs | 2 +- .../Data/Entities/ScreenSnapshot.cs | 2 +- .../Data}/Entities/SshHost.cs | 19 +- .../Data/Entities/StripeEvent.cs | 2 +- .../Data/OrchestratorDbContext.cs | 35 +- .../Health/AuthentikGlobalHealthJob.cs | 4 +- .../Checks/AdminIntegrityHealthCheck.cs | 12 +- .../Checks/AuthentikGlobalHealthCheck.cs | 10 +- .../AuthentikSamlProviderHealthCheck.cs | 6 +- .../Checks/ByoiCertExpiryHealthCheck.cs | 4 +- .../Checks/DisplayAuthorisedHealthCheck.cs | 10 +- .../Checks/GroupStructureHealthCheck.cs | 12 +- .../Checks/InvitationFlowHealthCheck.cs | 6 +- .../Health/Checks/MySqlConnectHealthCheck.cs | 16 +- .../Health/Checks/NfsAccessHealthCheck.cs | 12 +- .../Health/Checks/OauthAppAgeHealthCheck.cs | 4 +- .../Health/Checks/OauthAppHealthCheck.cs | 10 +- .../Health/Checks/StackHealthCheck.cs | 8 +- .../Health/Checks/ThemeHealthCheck.cs | 12 +- .../Health/Checks/XiboApiHealthCheck.cs | 10 +- .../Health/Checks/XiboVersionHealthCheck.cs | 10 +- .../Health/HealthCheckEngine.cs | 8 +- .../Health/IHealthCheck.cs | 4 +- .../Hubs/FleetHub.cs | 3 +- .../Jobs/ByoiCertExpiryJob.cs | 8 +- .../Jobs/DailySnapshotJob.cs | 12 +- .../Jobs/ScheduledReportJob.cs | 10 +- .../20260324004544_AddAppSettings.Designer.cs | 892 +++++ .../20260324004544_AddAppSettings.cs | 514 +++ .../OrchestratorDbContextModelSnapshot.cs | 889 +++++ .../Models/DTOs/AuthentikFlowItem.cs | 2 +- .../Models/DTOs/AuthentikGroupItem.cs | 2 +- .../Models/DTOs/AuthentikKeypairItem.cs | 2 +- .../Models/DTOs/AuthentikSamlConfig.cs | 2 +- .../Models/DTOs/CreateInstanceDto.cs | 2 +- .../Models/DTOs/DeploymentResultDto.cs | 2 +- .../Models/DTOs/NodeInfo.cs | 2 +- .../Models/DTOs/ServiceLogEntry.cs | 2 +- .../Models/DTOs/TemplateConfig.cs | 2 +- .../Models/DTOs/UpdateInstanceDto.cs | 2 +- .../OTSSignsOrchestrator.csproj | 16 +- .../Program.cs | 163 +- .../Properties/launchSettings.json | 11 + .../Reports/BillingReportService.cs | 6 +- .../Reports/FleetHealthPdfService.cs | 6 +- .../Services/AbbreviationService.cs | 4 +- .../Services/AuthentikService.cs | 4 +- .../Services/BitwardenSecretService.cs | 80 +- .../Services/ComposeRenderService.cs | 2 +- .../Services/ComposeValidationService.cs | 4 +- .../Services/EmailService.cs | 38 +- .../Services/GitTemplateService.cs | 6 +- .../Services/IAuthentikService.cs | 4 +- .../Services/IBitwardenSecretService.cs | 2 +- .../Services/IDockerCliService.cs | 6 +- .../Services/IDockerSecretsService.cs | 2 +- .../Services/IInvitationSetupService.cs | 24 + .../Services/IOperationLogger.cs | 13 + .../Services/InstanceService.cs | 38 +- .../Services/InvitationSetupService.cs | 101 + .../Services/PostInstanceInitService.cs | 4 +- .../Services/PostgresOperationLogger.cs | 42 + .../Services/SettingsService.cs | 220 +- .../Services/SshConnectionFactory.cs | 97 +- .../Services/SshDockerCliService.cs | 446 +++ .../Services/SshDockerSecretsService.cs | 53 +- .../Services/XiboApiService.cs | 4 +- .../Webhooks/StripeWebhookHandler.cs | 21 +- .../Workers/ByoiSamlPipeline.cs | 26 +- .../Workers/DecommissionPipeline.cs | 12 +- .../Workers/IProvisioningPipeline.cs | 4 +- .../Workers/Phase1Pipeline.cs | 16 +- .../Workers/Phase2Pipeline.cs | 14 +- .../Workers/ProvisioningWorker.cs | 8 +- .../Workers/ReactivatePipeline.cs | 10 +- .../Workers/RotateCredentialsPipeline.cs | 12 +- .../Workers/StepRunner.cs | 8 +- .../Workers/SuspendPipeline.cs | 10 +- .../Workers/UpdateScreenLimitPipeline.cs | 12 +- .../Workers/XiboFeatureManifests.cs | 2 +- OTSSignsOrchestrator/appsettings.json | 26 + .../wwwroot/assets/index-DalzG2Gn.js | 62 + .../wwwroot/assets/index-Dgjzlkqr.css | 1 + OTSSignsOrchestrator/wwwroot/index.html | 13 + deploy.sh | 80 + docker-compose.yml | 56 + 240 files changed, 11806 insertions(+), 10828 deletions(-) create mode 100644 .dockerignore create mode 100644 CLAUDE.md create mode 100644 Dockerfile delete mode 100644 OTSSignsOrchestrator.Core/Data/DesignTimeDbContextFactory.cs delete mode 100644 OTSSignsOrchestrator.Core/Data/XiboContext.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260217004115_DesktopInitial.Designer.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260217004115_DesktopInitial.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260218140239_AddCustomerAbbrev.Designer.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260218140239_AddCustomerAbbrev.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260218143812_AddAppSettings.Designer.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260218143812_AddAppSettings.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260218144537_AddPerInstanceCifsCredentials.Designer.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260218144537_AddPerInstanceCifsCredentials.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260218180240_RenameShareBasePathToShareName.Designer.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260218180240_RenameShareBasePathToShareName.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260218202617_AddCifsShareFolder.Designer.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260218202617_AddCifsShareFolder.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260219005507_ReplaceCifsWithNfs.Designer.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260219005507_ReplaceCifsWithNfs.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260219020727_AddNewtCredentials.Designer.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260219020727_AddNewtCredentials.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260219121529_RemoveCmsInstancesAndSecretMetadata.Designer.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260219121529_RemoveCmsInstancesAndSecretMetadata.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260225135644_DropAppSettings.Designer.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/20260225135644_DropAppSettings.cs delete mode 100644 OTSSignsOrchestrator.Core/Migrations/XiboContextModelSnapshot.cs delete mode 100644 OTSSignsOrchestrator.Core/Models/Entities/AppSetting.cs delete mode 100644 OTSSignsOrchestrator.Core/OTSSignsOrchestrator.Core.csproj delete mode 100644 OTSSignsOrchestrator.Core/Services/IInvitationSetupService.cs delete mode 100644 OTSSignsOrchestrator.Core/Services/InvitationSetupService.cs delete mode 100644 OTSSignsOrchestrator.Desktop/App.axaml delete mode 100644 OTSSignsOrchestrator.Desktop/App.axaml.cs delete mode 100644 OTSSignsOrchestrator.Desktop/Assets/OTS-Signs.png delete mode 100644 OTSSignsOrchestrator.Desktop/Models/LiveStackItem.cs delete mode 100644 OTSSignsOrchestrator.Desktop/OTSSignsOrchestrator.Desktop.csproj delete mode 100644 OTSSignsOrchestrator.Desktop/Program.cs delete mode 100644 OTSSignsOrchestrator.Desktop/Services/IServerApiClient.cs delete mode 100644 OTSSignsOrchestrator.Desktop/Services/ServerSignalRService.cs delete mode 100644 OTSSignsOrchestrator.Desktop/Services/SignalRMessages.cs delete mode 100644 OTSSignsOrchestrator.Desktop/Services/SshDockerCliService.cs delete mode 100644 OTSSignsOrchestrator.Desktop/Services/TokenStoreService.cs delete mode 100644 OTSSignsOrchestrator.Desktop/ViewModels/CreateInstanceViewModel.cs delete mode 100644 OTSSignsOrchestrator.Desktop/ViewModels/HostsViewModel.cs delete mode 100644 OTSSignsOrchestrator.Desktop/ViewModels/InstanceDetailsViewModel.cs delete mode 100644 OTSSignsOrchestrator.Desktop/ViewModels/InstancesViewModel.cs delete mode 100644 OTSSignsOrchestrator.Desktop/ViewModels/LogsViewModel.cs delete mode 100644 OTSSignsOrchestrator.Desktop/ViewModels/MainWindowViewModel.cs delete mode 100644 OTSSignsOrchestrator.Desktop/ViewModels/SecretsViewModel.cs delete mode 100644 OTSSignsOrchestrator.Desktop/ViewModels/SettingsViewModel.cs delete mode 100644 OTSSignsOrchestrator.Desktop/Views/ConfirmationDialog.axaml delete mode 100644 OTSSignsOrchestrator.Desktop/Views/ConfirmationDialog.axaml.cs delete mode 100644 OTSSignsOrchestrator.Desktop/Views/CreateInstanceView.axaml delete mode 100644 OTSSignsOrchestrator.Desktop/Views/CreateInstanceView.axaml.cs delete mode 100644 OTSSignsOrchestrator.Desktop/Views/HostsView.axaml delete mode 100644 OTSSignsOrchestrator.Desktop/Views/HostsView.axaml.cs delete mode 100644 OTSSignsOrchestrator.Desktop/Views/InstanceDetailsWindow.axaml delete mode 100644 OTSSignsOrchestrator.Desktop/Views/InstanceDetailsWindow.axaml.cs delete mode 100644 OTSSignsOrchestrator.Desktop/Views/InstancesView.axaml delete mode 100644 OTSSignsOrchestrator.Desktop/Views/InstancesView.axaml.cs delete mode 100644 OTSSignsOrchestrator.Desktop/Views/LogsView.axaml delete mode 100644 OTSSignsOrchestrator.Desktop/Views/LogsView.axaml.cs delete mode 100644 OTSSignsOrchestrator.Desktop/Views/MainWindow.axaml delete mode 100644 OTSSignsOrchestrator.Desktop/Views/MainWindow.axaml.cs delete mode 100644 OTSSignsOrchestrator.Desktop/Views/SecretsView.axaml delete mode 100644 OTSSignsOrchestrator.Desktop/Views/SecretsView.axaml.cs delete mode 100644 OTSSignsOrchestrator.Desktop/Views/SettingsView.axaml delete mode 100644 OTSSignsOrchestrator.Desktop/Views/SettingsView.axaml.cs delete mode 100644 OTSSignsOrchestrator.Desktop/app.manifest delete mode 100644 OTSSignsOrchestrator.Desktop/appsettings.json rename {OTSSignsOrchestrator.Server.Tests => OTSSignsOrchestrator.Tests}/ByoiCertExpiryThresholdTests.cs (97%) rename OTSSignsOrchestrator.Server.Tests/OTSSignsOrchestrator.Server.Tests.csproj => OTSSignsOrchestrator.Tests/OTSSignsOrchestrator.Tests.csproj (86%) create mode 100644 OTSSignsOrchestrator/Api/AuditApi.cs rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Api/CustomerPortalApi.cs (97%) create mode 100644 OTSSignsOrchestrator/Api/CustomersApi.cs rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Api/FleetApi.cs (97%) create mode 100644 OTSSignsOrchestrator/Api/HealthApi.cs create mode 100644 OTSSignsOrchestrator/Api/HostsApi.cs create mode 100644 OTSSignsOrchestrator/Api/InstancesApi.cs create mode 100644 OTSSignsOrchestrator/Api/LogsApi.cs create mode 100644 OTSSignsOrchestrator/Api/OperatorsApi.cs create mode 100644 OTSSignsOrchestrator/Api/ProvisionApi.cs create mode 100644 OTSSignsOrchestrator/Api/SecretsApi.cs create mode 100644 OTSSignsOrchestrator/Api/SettingsApi.cs rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Api/SignupApi.cs (97%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Auth/JwtOptions.cs (85%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Auth/OperatorAuthService.cs (96%) create mode 100644 OTSSignsOrchestrator/ClientApp/index.html create mode 100644 OTSSignsOrchestrator/ClientApp/package-lock.json create mode 100644 OTSSignsOrchestrator/ClientApp/package.json create mode 100644 OTSSignsOrchestrator/ClientApp/src/App.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/api/auditLogs.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/api/auth.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/api/client.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/api/customers.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/api/fleet.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/api/healthEvents.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/api/hosts.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/api/instances.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/api/jobs.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/api/logs.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/api/operators.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/api/provision.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/api/reports.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/api/secrets.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/api/settings.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/components/jobs/JobProgressPanel.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/components/layout/AppShell.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/components/layout/Sidebar.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/components/shared/ConfirmDialog.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/components/shared/StatusBanner.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/hooks/useSignalR.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/index.css create mode 100644 OTSSignsOrchestrator/ClientApp/src/main.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/pages/AuditPage.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/pages/CreateInstancePage.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/pages/CustomerDetailPage.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/pages/CustomersPage.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/pages/FleetPage.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/pages/HealthPage.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/pages/HostsPage.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/pages/InstancesPage.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/pages/LoginPage.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/pages/LogsPage.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/pages/OperatorsPage.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/pages/ReportsPage.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/pages/SecretsPage.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/pages/SettingsPage.tsx create mode 100644 OTSSignsOrchestrator/ClientApp/src/store/alertStore.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/store/authStore.ts create mode 100644 OTSSignsOrchestrator/ClientApp/src/store/jobProgressStore.ts create mode 100644 OTSSignsOrchestrator/ClientApp/tsconfig.json create mode 100644 OTSSignsOrchestrator/ClientApp/tsconfig.tsbuildinfo create mode 100644 OTSSignsOrchestrator/ClientApp/vite.config.ts rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Clients/IAuthentikClient.cs (99%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Clients/IXiboApiClient.cs (99%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Clients/XiboClientFactory.cs (99%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Configuration/AppConstants.cs (97%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Configuration/AppOptions.cs (98%) create mode 100644 OTSSignsOrchestrator/Data/Entities/AppSetting.cs rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Data/Entities/AuditLog.cs (88%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Data/Entities/AuthentikMetrics.cs (86%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Data/Entities/ByoiConfig.cs (90%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Data/Entities/Customer.cs (95%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Data/Entities/HealthEvent.cs (89%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Data/Entities/Instance.cs (95%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Data/Entities/Job.cs (92%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Data/Entities/JobStep.cs (89%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Data/Entities/OauthAppRegistry.cs (83%) rename {OTSSignsOrchestrator.Core/Models => OTSSignsOrchestrator/Data}/Entities/OperationLog.cs (76%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Data/Entities/Operator.cs (87%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Data/Entities/RefreshToken.cs (85%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Data/Entities/ScreenSnapshot.cs (84%) rename {OTSSignsOrchestrator.Core/Models => OTSSignsOrchestrator/Data}/Entities/SshHost.cs (65%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Data/Entities/StripeEvent.cs (81%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Data/OrchestratorDbContext.cs (84%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/AuthentikGlobalHealthJob.cs (91%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/Checks/AdminIntegrityHealthCheck.cs (94%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/Checks/AuthentikGlobalHealthCheck.cs (94%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/Checks/AuthentikSamlProviderHealthCheck.cs (93%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/Checks/ByoiCertExpiryHealthCheck.cs (96%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/Checks/DisplayAuthorisedHealthCheck.cs (88%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/Checks/GroupStructureHealthCheck.cs (92%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/Checks/InvitationFlowHealthCheck.cs (94%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/Checks/MySqlConnectHealthCheck.cs (84%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/Checks/NfsAccessHealthCheck.cs (90%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/Checks/OauthAppAgeHealthCheck.cs (95%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/Checks/OauthAppHealthCheck.cs (85%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/Checks/StackHealthCheck.cs (95%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/Checks/ThemeHealthCheck.cs (93%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/Checks/XiboApiHealthCheck.cs (87%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/Checks/XiboVersionHealthCheck.cs (90%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/HealthCheckEngine.cs (98%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Health/IHealthCheck.cs (92%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Hubs/FleetHub.cs (92%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Jobs/ByoiCertExpiryJob.cs (95%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Jobs/DailySnapshotJob.cs (93%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Jobs/ScheduledReportJob.cs (96%) create mode 100644 OTSSignsOrchestrator/Migrations/20260324004544_AddAppSettings.Designer.cs create mode 100644 OTSSignsOrchestrator/Migrations/20260324004544_AddAppSettings.cs create mode 100644 OTSSignsOrchestrator/Migrations/OrchestratorDbContextModelSnapshot.cs rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Models/DTOs/AuthentikFlowItem.cs (91%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Models/DTOs/AuthentikGroupItem.cs (91%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Models/DTOs/AuthentikKeypairItem.cs (89%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Models/DTOs/AuthentikSamlConfig.cs (96%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Models/DTOs/CreateInstanceDto.cs (97%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Models/DTOs/DeploymentResultDto.cs (93%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Models/DTOs/NodeInfo.cs (91%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Models/DTOs/ServiceLogEntry.cs (94%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Models/DTOs/TemplateConfig.cs (88%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Models/DTOs/UpdateInstanceDto.cs (97%) rename OTSSignsOrchestrator.Server/OTSSignsOrchestrator.Server.csproj => OTSSignsOrchestrator/OTSSignsOrchestrator.csproj (71%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Program.cs (63%) create mode 100644 OTSSignsOrchestrator/Properties/launchSettings.json rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Reports/BillingReportService.cs (97%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Reports/FleetHealthPdfService.cs (99%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Services/AbbreviationService.cs (96%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Services/AuthentikService.cs (99%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Services/BitwardenSecretService.cs (76%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Services/ComposeRenderService.cs (99%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Services/ComposeValidationService.cs (98%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Services/EmailService.cs (85%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Services/GitTemplateService.cs (97%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Services/IAuthentikService.cs (98%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Services/IBitwardenSecretService.cs (97%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Services/IDockerCliService.cs (97%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Services/IDockerSecretsService.cs (92%) create mode 100644 OTSSignsOrchestrator/Services/IInvitationSetupService.cs create mode 100644 OTSSignsOrchestrator/Services/IOperationLogger.cs rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Services/InstanceService.cs (97%) create mode 100644 OTSSignsOrchestrator/Services/InvitationSetupService.cs rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Services/PostInstanceInitService.cs (99%) create mode 100644 OTSSignsOrchestrator/Services/PostgresOperationLogger.cs rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Services/SettingsService.cs (51%) rename OTSSignsOrchestrator.Desktop/Services/SshConnectionService.cs => OTSSignsOrchestrator/Services/SshConnectionFactory.cs (67%) create mode 100644 OTSSignsOrchestrator/Services/SshDockerCliService.cs rename {OTSSignsOrchestrator.Desktop => OTSSignsOrchestrator}/Services/SshDockerSecretsService.cs (67%) rename {OTSSignsOrchestrator.Core => OTSSignsOrchestrator}/Services/XiboApiService.cs (99%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Webhooks/StripeWebhookHandler.cs (95%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Workers/ByoiSamlPipeline.cs (90%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Workers/DecommissionPipeline.cs (98%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Workers/IProvisioningPipeline.cs (93%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Workers/Phase1Pipeline.cs (98%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Workers/Phase2Pipeline.cs (98%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Workers/ProvisioningWorker.cs (96%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Workers/ReactivatePipeline.cs (97%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Workers/RotateCredentialsPipeline.cs (98%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Workers/StepRunner.cs (94%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Workers/SuspendPipeline.cs (97%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Workers/UpdateScreenLimitPipeline.cs (96%) rename {OTSSignsOrchestrator.Server => OTSSignsOrchestrator}/Workers/XiboFeatureManifests.cs (98%) create mode 100644 OTSSignsOrchestrator/appsettings.json create mode 100644 OTSSignsOrchestrator/wwwroot/assets/index-DalzG2Gn.js create mode 100644 OTSSignsOrchestrator/wwwroot/assets/index-Dgjzlkqr.css create mode 100644 OTSSignsOrchestrator/wwwroot/index.html create mode 100755 deploy.sh create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..aedbea1 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,42 @@ +# .NET build artifacts +**/bin/ +**/obj/ + +# Node / frontend +**/node_modules/ +OTSSignsOrchestrator/ClientApp/dist/ + +# Built frontend (generated by Vite into wwwroot — included via Docker COPY from frontend-build stage) +OTSSignsOrchestrator/wwwroot/ + +# Test project +OTSSignsOrchestrator.Tests/ + +# Logs +logs/ +*.log + +# User-specific files +.vs/ +.vscode/ +*.user +*.suo + +# Secrets / local config overrides (never bake these into the image) +appsettings.Development.json +**/secrets.json + +# Git +.git/ +.gitignore + +# Docker +Dockerfile +.dockerignore +docker-compose*.yml + +# Misc +README.md +CLAUDE.md +.github/ +templates/ diff --git a/.env.example b/.env.example index 8cfe70c..af8b66b 100644 --- a/.env.example +++ b/.env.example @@ -1,11 +1,47 @@ -# OTSSignsOrchestrator.Server — required environment variables -# Copy to .env and fill in real values. +# OTSSignsOrchestrator — environment variables +# Copy to .env and fill in real values before running. -ConnectionStrings__OrchestratorDb=Host=localhost;Port=5432;Database=orchestrator_dev;Username=ots;Password=devpassword -Stripe__WebhookSecret=whsec_... -Stripe__SecretKey=sk_test_... +# ── PostgreSQL ─────────────────────────────────────────────────────────────── +# Used directly by the app. When running via docker-compose, POSTGRES_PASSWORD +# is also required so the postgres service can initialise the database. +ConnectionStrings__OrchestratorDb=Host=postgres;Port=5432;Database=orchestrator;Username=ots;Password=changeme +POSTGRES_PASSWORD=changeme + +# ── JWT ────────────────────────────────────────────────────────────────────── +# Key must be at least 32 characters (256-bit). Generate with: +# openssl rand -base64 32 Jwt__Key=change-me-to-a-random-256-bit-key +# Jwt__Issuer=OTSSignsOrchestrator # optional — has a default +# Jwt__Audience=OTSSignsOrchestrator # optional — has a default + +# ── Bitwarden Secrets Manager ──────────────────────────────────────────────── +# Machine account access token from https://vault.bitwarden.com +Bitwarden__AccessToken= +Bitwarden__OrganizationId= +# ProjectId is the default project for orchestrator config secrets +Bitwarden__ProjectId= +# InstanceProjectId is optional; instance-level secrets go here when set +# Bitwarden__InstanceProjectId= +# Bitwarden__IdentityUrl=https://identity.bitwarden.com # optional +# Bitwarden__ApiUrl=https://api.bitwarden.com # optional + +# ── Stripe ─────────────────────────────────────────────────────────────────── +Stripe__SecretKey=sk_test_... +Stripe__WebhookSecret=whsec_... + +# ── Authentik (SAML IdP) ───────────────────────────────────────────────────── Authentik__BaseUrl=https://auth.example.com Authentik__ApiToken= -SendGrid__ApiKey=SG.... -OTS_SIGNS_SERVER_URL=http://localhost:5000 +# UUID of the OTS signing certificate-key pair in Authentik +Authentik__OtsSigningKpId= +# Authentik__SourcePreAuthFlowSlug=default-source-pre-authentication # optional +# Authentik__SourceAuthFlowSlug=default-source-authentication # optional + +# ── Email (SendGrid) ───────────────────────────────────────────────────────── +Email__SendGridApiKey=SG.... +# Email__SenderEmail=noreply@otssigns.com # optional +# Email__SenderName=OTS Signs # optional + +# ── Git template repository ─────────────────────────────────────────────────── +# These are stored in Bitwarden at runtime; set here only for local dev without BW. +# Git__CacheDir=.template-cache # optional diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 6a957f1..1a1e189 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -2,27 +2,21 @@ ## Architecture -Layered MVVM desktop app for provisioning and managing Xibo CMS instances on Docker Swarm. +Web-based system for provisioning and managing Xibo CMS instances on Docker Swarm. -- **OTSSignsOrchestrator.Core** — class library: services, EF Core data access, models, configuration. Reusable across UIs. -- **OTSSignsOrchestrator.Desktop** — Avalonia 11 UI: views, view models, DI setup. References Core. -- **templates/** — Docker Compose + PHP templates with `{{PLACEHOLDER}}` substitution. +- **OTSSignsOrchestrator** — ASP.NET Core API + React web UI (Vite + TypeScript + Tailwind CSS) + SignalR + Quartz scheduler. PostgreSQL 16. Contains all services, models, configuration, and business logic. +- **OTSSignsOrchestrator.Tests** — xUnit test project. ### Key patterns -- Services injected via `IServiceProvider` (registered in `App.axaml.cs` → `ConfigureServices()`) -- Singletons: stateful services (SSH connections, Docker CLI). Transient: stateless logic. +- Services injected via DI (registered in `Program.cs`) +- Singletons: stateful services (SSH connection factory). Scoped: per-request services (Docker CLI, secrets). Transient: stateless logic. - Configuration via `IOptions` bound from `appsettings.json` (see `AppOptions.cs` for all sections). - Bitwarden Secrets Manager is the source of truth for all sensitive config. `SettingsService` caches in-memory. -- Local SQLite DB (`otssigns-desktop.db`) stores SSH hosts + operation logs. Credentials encrypted via Data Protection API. - -### Scope & file discipline -**The Server project is net-new — keep concerns separated.** -- Never modify `OTSSignsOrchestrator.Core` or `OTSSignsOrchestrator.Desktop` unless the prompt explicitly says to. -- When in doubt, add new code to `OTSSignsOrchestrator.Server`. -- Never modify `XiboContext.cs` without explicit instruction. +- PostgreSQL database via `OrchestratorDbContext`. Credentials encrypted via Data Protection API. +- React frontend in `ClientApp/`, built to `wwwroot/` via Vite. Cookie-based JWT auth. ### External integrations -Xibo CMS REST API (OAuth2), Authentik SAML IdP, Bitwarden Secrets SDK, Docker Swarm (via SSH), Git (LibGit2Sharp), MySQL 8.4, NFS volumes, Pangolin/Newt VPN. +Xibo CMS REST API (OAuth2), Authentik SAML IdP, Bitwarden Secrets SDK, Docker Swarm (via SSH), Git (LibGit2Sharp), MySQL 8.4, NFS volumes, Pangolin/Newt VPN, Stripe, SendGrid. #### Xibo API rules — non-negotiable - `GET /api/application` is **BLOCKED**. Only POST and DELETE exist. @@ -43,17 +37,20 @@ Xibo CMS REST API (OAuth2), Authentik SAML IdP, Bitwarden Secrets SDK, Docker Sw ```bash # Build -dotnet build OTSSignsOrchestrator.Desktop/OTSSignsOrchestrator.Desktop.csproj +dotnet build -# Run -dotnet run --project OTSSignsOrchestrator.Desktop/OTSSignsOrchestrator.Desktop.csproj +# Run Server +dotnet run --project OTSSignsOrchestrator/OTSSignsOrchestrator.csproj -# No test suite currently — no xUnit/NUnit projects +# Run tests +dotnet test OTSSignsOrchestrator.Tests/OTSSignsOrchestrator.Tests.csproj + +# Frontend dev +cd OTSSignsOrchestrator/ClientApp && npm run dev ``` -- .NET 9.0, Avalonia 11.2.3, CommunityToolkit.Mvvm 8.4 -- Runtime identifiers: `linux-x64`, `win-x64`, `osx-x64`, `osx-arm64` -- EF Core migrations in `OTSSignsOrchestrator.Core/Migrations/` +- .NET 9.0, React 18, Vite, TypeScript, Tailwind CSS, shadcn/ui +- EF Core migrations in `OTSSignsOrchestrator/Migrations/` ### Test coverage non-negotiables Unit tests are **required** for: @@ -67,28 +64,10 @@ Integration tests **require** Testcontainers with a real PostgreSQL 16 instance ## Conventions -### ViewModels -- Inherit `ObservableObject` (CommunityToolkit.Mvvm). Use `[ObservableProperty]` for bindable fields and `[RelayCommand]` for commands. -- React to changes via `partial void OnXxxChanged(T value)` methods generated by the toolkit. -- Resolve services from `IServiceProvider` in constructors. Navigation via `MainWindowViewModel.CurrentView`. -- Confirmation dialogs use `Func> ConfirmAsync` property — wired by the View. - -### Avalonia threading — critical for stability -All SignalR message handlers and background thread continuations that touch `ObservableProperty` or `ObservableCollection` **MUST** be wrapped in: -```csharp -Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(() => { ... }); -``` -**Failure to do this causes silent cross-thread exceptions in Avalonia.** Never suggest direct property assignment from a non-UI thread. - -### Views (Avalonia XAML) -- Compiled bindings enabled (`x:CompileBindings="True"`). DataTemplates in `MainWindow.axaml` map ViewModel types to View UserControls. -- Layout: DockPanel with status bar (bottom), sidebar nav (left), dynamic ContentControl (center). -- Style: Fluent theme, dark palette (`#0C0C14` accents). - ### Services - Interface + implementation pattern for testable services (`IXiboApiService`, `IDockerCliService`, etc.). -- `SshDockerCliService` is a singleton — **must call `SetHost(host)` before each operation** in loops. -- All long operations are `async Task`. Use `IsBusy` + `StatusMessage` properties for UI feedback. +- `SshDockerCliService` is scoped — **must call `SetHost(host)` before each operation** in loops. +- All long operations are `async Task`. ### Naming - Customer abbreviation: exactly 3 lowercase letters (`^[a-z]{3}$`). @@ -97,27 +76,23 @@ Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(() => { ... }); - `AppConstants.SanitizeName()` filters to `[a-z0-9_-]`. ### Credential handling -Never store OAuth2 client secrets, Stripe keys, or SSH passwords in the database. Secrets go to the Bitwarden CLI wrapper only. `OauthAppRegistry` stores `clientId` only — never the secret. Log credentials to `JobStep` output **ONLY** as a last-resort break-glass fallback, and mark it explicitly as emergency recovery data in the log. +Never store OAuth2 client secrets, Stripe keys, or SSH passwords in the database. Secrets go to the Bitwarden CLI wrapper only. `OauthAppRegistry` stores `clientId` only — never the secret. ### Code generation verification -After generating any class that implements an interface, **verify all interface members are implemented.** After generating any pipeline, **verify all steps are implemented as `JobStep` entities with progress broadcast via `IHubContext`.** Do not stub steps as TODO — implement them fully or flag explicitly that the step requires external infrastructure access that cannot be completed in this context. +After generating any class that implements an interface, **verify all interface members are implemented.** After generating any pipeline, **verify all steps are implemented as `JobStep` entities with progress broadcast via `IHubContext`.** Do not stub steps as TODO — implement them fully or flag explicitly. ### Data layer -- Entities in `Core/Models/Entities/`, DTOs in `Core/Models/DTOs/`. -- `XiboContext` applies unique index on `SshHost.Label` and encrypts credential fields. -- Add new migrations via: `dotnet ef migrations add --project OTSSignsOrchestrator.Core --startup-project OTSSignsOrchestrator.Desktop` +- Entities in `Core/Models/Entities/` and `Server/Data/Entities/`. +- DTOs in `Core/Models/DTOs/`. +- `OrchestratorDbContext` is the primary database context (PostgreSQL). ### Immutability enforcement -**AuditLog, Message, and Evidence are append-only by design.** Never generate `Update()` or `Delete()` methods on these repositories. Add an explicit comment on each repository class: -```csharp -// IMMUTABLE — no update or delete operations permitted. -``` +**AuditLog, Message, and Evidence are append-only by design.** Never generate `Update()` or `Delete()` methods on these repositories. ## Pitfalls -- **SSH singleton state**: `SshDockerCliService.SetHost()` must be called before each host operation — stale host causes silent failures. +- **SSH host state**: `SshDockerCliService.SetHost()` must be called before each host operation — stale host causes silent failures. - **Bitwarden cache**: After creating secrets during deployment, call `FlushCacheAsync()` before reading them back. -- **Data Protection keys**: Stored in `%APPDATA%/OTSSignsOrchestrator/keys`. If lost, encrypted SSH passwords are unrecoverable. - **Docker volumes are sticky**: Failed deploys leave volumes with old NFS driver options. Use `PurgeStaleVolumes: true` to force fresh volumes (causes data loss). - **No saga/rollback**: Instance creation spans Git → MySQL → Docker → Xibo. Partial failures leave orphaned resources; cleanup is manual via `OperationLog`. - **Template CIFS→NFS compat**: Old `{{CIFS_*}}` tokens still render correctly as NFS equivalents. diff --git a/.gitignore b/.gitignore index 8865743..0819793 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,14 @@ -# .gitignore for C#/.NET projects on macOS +# .gitignore for ASP.NET Core + React (Vite) project on macOS # Generated for Visual Studio, Rider, and dotnet CLI workflows -# Visual Studio +# Visual Studio & Rider .vs/ +.idea/ *.suo *.user *.userosscache *.sln.docstates +*.DotSettings.user # Build results [Bb]in/ @@ -15,19 +17,15 @@ build/ publish/ artifacts/ -# Rider -.idea/ - # Resharper _ReSharper*/ -*.DotSettings.user # NuGet *.nupkg packages/ project.lock.json -# Dotnet +# Dotnet & EF Core *.db *.db-journal secrets.json @@ -36,6 +34,8 @@ dotnet_user_secrets # Logs *.log TestResults/ +coverage/ +*.trx # OS generated files .DS_Store @@ -51,9 +51,23 @@ Icon *~ *.tmp +# Node/React Frontend (Vite) +OTSSignsOrchestrator/ClientApp/node_modules/ +OTSSignsOrchestrator/ClientApp/dist/ +OTSSignsOrchestrator/ClientApp/.env.local +OTSSignsOrchestrator/ClientApp/.env.*.local +OTSSignsOrchestrator/ClientApp/npm-debug.log* +OTSSignsOrchestrator/ClientApp/yarn-debug.log* +OTSSignsOrchestrator/ClientApp/yarn-error.log* + # Docker docker-compose.override.yml -# Ignore appsettings development files (if you keep secrets locally) +# Configuration & Secrets appsettings.Development.json -.template-cache/ \ No newline at end of file +.template-cache/ +.env +*.env + +# Application-specific +logs/ diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..4ba37dc --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,125 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +OTS Signs Orchestrator — a .NET 9.0 system for provisioning and managing Xibo CMS instances on Docker Swarm. Two projects in one solution: + +- **OTSSignsOrchestrator** — ASP.NET Core API + React web UI + SignalR + Quartz scheduler. PostgreSQL 16. Contains all services, models, configuration, and business logic. +- **OTSSignsOrchestrator.Tests** — xUnit test project. + +External integrations: Xibo CMS API (OAuth2), Authentik (SAML IdP), Bitwarden Secrets, Docker Swarm (SSH), Git (LibGit2Sharp), MySQL 8.4, Stripe, SendGrid, NFS volumes. + +## Build & Run Commands + +```bash +# Build entire solution +dotnet build + +# Run application +dotnet run --project OTSSignsOrchestrator/OTSSignsOrchestrator.csproj + +# Run tests +dotnet test OTSSignsOrchestrator.Tests/OTSSignsOrchestrator.Tests.csproj + +# Run a single test +dotnet test OTSSignsOrchestrator.Tests --filter "FullyQualifiedName~TestClassName.TestMethodName" + +# Frontend dev server (from ClientApp/) +cd OTSSignsOrchestrator/ClientApp && npm run dev + +# Build frontend for production (outputs to wwwroot/) +cd OTSSignsOrchestrator/ClientApp && npm run build + +# EF Core migrations +dotnet ef migrations add --project OTSSignsOrchestrator --startup-project OTSSignsOrchestrator + +# Local dev PostgreSQL +docker compose -f docker-compose.dev.yml up -d +``` + +## Architecture + +The application uses a job-queue architecture with a React web UI: + +1. **React Web UI** (`ClientApp/`) — Vite + React + TypeScript + Tailwind CSS, served from `wwwroot/`. Cookie-based JWT auth (httpOnly, Secure, SameSite=Strict). +2. **REST API** (`Api/`) — Minimal API endpoint groups via `.MapGroup()` with JWT auth +3. **SignalR Hub** (`Hubs/FleetHub.cs`) — Real-time updates to web UI clients +4. **ProvisioningWorker** (`Workers/`) — Background service that polls `Jobs` table, claims jobs, resolves the correct `IProvisioningPipeline`, and executes steps +5. **Pipelines** — Each job type has a pipeline (Phase1, Phase2, BYOI SAML, Suspend, Reactivate, Decommission, etc.). Steps emit `JobStep` records broadcast via SignalR +6. **HealthCheckEngine** (`Health/`) — Background service running 16 health check types +7. **Quartz Jobs** (`Jobs/`) — Scheduled tasks (cert expiry, daily snapshots, reports) +8. **Stripe Webhooks** (`Webhooks/`) — Idempotent webhook processing + +**Data flow:** Web UI creates `Job` → `ProvisioningWorker` claims it → pipeline runs steps → `JobStep` records broadcast via SignalR → Web UI updates in real-time. + +## Project Structure + +``` +OTSSignsOrchestrator/ +├── Api/ # Minimal API endpoint groups +├── Auth/ # JWT/auth services +├── ClientApp/ # React + Vite frontend +├── Clients/ # External API clients (Xibo, Authentik) +├── Configuration/ # AppConstants, AppOptions +├── Data/ # OrchestratorDbContext +│ └── Entities/ # EF Core entity models +├── Health/ # Health check engine + checks +├── Hubs/ # SignalR hubs +├── Jobs/ # Quartz scheduled jobs +├── Models/DTOs/ # Data transfer objects +├── Reports/ # PDF report generation +├── Services/ # Business logic + integrations +├── Webhooks/ # Stripe webhook handler +├── Workers/ # Provisioning pipelines + worker +└── wwwroot/ # Built frontend assets +``` + +## Critical Rules + +### Xibo API — non-negotiable +- `GET /api/application` is **BLOCKED** — only POST and DELETE exist +- Group endpoints are `/api/group`, never `/api/usergroup` +- Feature assignment is `POST /api/group/{id}/acl`, NOT `/features` +- **Always pass `length=200`** and use `GetAllPagesAsync()` — default pagination is 10 items, causing silent data truncation +- OAuth2 client secret returned **ONCE** on creation — capture immediately + +### Stripe webhooks — idempotency mandatory +- Check `StripeEvents` table for `stripe_event_id` before processing +- Insert the `StripeEvent` row first, then process + +### No AI autonomy in infrastructure actions +- All infrastructure actions must flow through the `ProvisioningWorker` job queue via an operator-initiated `Job` record + +### Immutability +`AuditLog`, `Message`, and `Evidence` are append-only. Never generate Update/Delete methods on their repositories. + +### Credential handling +Never store secrets in the database. Secrets go to Bitwarden only. `OauthAppRegistry` stores `clientId` only. + +## Naming Conventions + +- Customer abbreviation: exactly 3 lowercase letters (`^[a-z]{3}$`) +- Stack name: `{abbrev}-cms-stack`, Service: `{abbrev}-web`, DB: `{abbrev}_cms_db` +- Secret names via `AppConstants` helpers +- `AppConstants.SanitizeName()` filters to `[a-z0-9_-]` + +## Testing Requirements + +- Integration tests **require** Testcontainers with real PostgreSQL 16 — no SQLite substitutions +- Unit tests required for: evidence hashing, AI context assembly, pattern detection, abbreviation uniqueness, Stripe idempotency + +## Pitfalls + +- **SSH host state**: `SshDockerCliService.SetHost()` must be called before each host operation in loops +- **Bitwarden cache**: Call `FlushCacheAsync()` after creating secrets before reading them back +- **No saga/rollback**: Partial failures across Git → MySQL → Docker → Xibo leave orphaned resources; cleanup is manual +- **Docker volumes are sticky**: Failed deploys leave volumes with old NFS driver options +- **Template CIFS→NFS compat**: Old `{{CIFS_*}}` tokens still render correctly as NFS equivalents + +## Code Generation Checklist + +- After generating a class implementing an interface, verify all members are implemented +- After generating a pipeline, verify all steps produce `JobStep` entities with progress broadcast via `IHubContext` +- Do not stub steps as TODO — implement fully or flag explicitly diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..db3a7b3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,51 @@ +# ── Stage 1: Build React frontend ──────────────────────────────────────────── +FROM node:20-alpine AS frontend-build +WORKDIR /app/ClientApp +COPY OTSSignsOrchestrator/ClientApp/package.json OTSSignsOrchestrator/ClientApp/package-lock.json* ./ +RUN npm ci +COPY OTSSignsOrchestrator/ClientApp/ ./ +# Build outputs to ../wwwroot (relative to ClientApp) +RUN npm run build + +# ── Stage 2: Publish .NET app ───────────────────────────────────────────────── +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS dotnet-build +WORKDIR /src + +# Restore dependencies (layer-cached separately for fast rebuilds) +COPY OTSSignsOrchestrator/OTSSignsOrchestrator.csproj OTSSignsOrchestrator/ +RUN dotnet restore OTSSignsOrchestrator/OTSSignsOrchestrator.csproj + +# Copy source (excluding ClientApp — frontend handled in stage 1) +COPY OTSSignsOrchestrator/ OTSSignsOrchestrator/ + +# Copy built frontend assets from stage 1 +COPY --from=frontend-build /app/wwwroot OTSSignsOrchestrator/wwwroot/ + +RUN dotnet publish OTSSignsOrchestrator/OTSSignsOrchestrator.csproj \ + -c Release \ + -o /app/publish \ + --no-restore + +# ── Stage 3: Runtime image ──────────────────────────────────────────────────── +FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +WORKDIR /app + +# LibGit2Sharp requires git native libraries (libgit2 is bundled in the NuGet package, +# but git2-ssh requires libssh2 on Linux) +RUN apt-get update && apt-get install -y --no-install-recommends \ + libssl3 \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=dotnet-build /app/publish . + +# Data Protection keys must survive restarts — mount a volume here +VOLUME ["/app/dataprotection-keys"] + +# Expose HTTP only — use a reverse proxy (nginx/Caddy/Traefik) for TLS termination +EXPOSE 8080 + +ENV ASPNETCORE_URLS=http://+:8080 +ENV ASPNETCORE_ENVIRONMENT=Production + +ENTRYPOINT ["dotnet", "OTSSignsOrchestrator.dll"] diff --git a/OTSSignsOrchestrator.Core/Data/DesignTimeDbContextFactory.cs b/OTSSignsOrchestrator.Core/Data/DesignTimeDbContextFactory.cs deleted file mode 100644 index df0722f..0000000 --- a/OTSSignsOrchestrator.Core/Data/DesignTimeDbContextFactory.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.AspNetCore.DataProtection; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.Extensions.DependencyInjection; - -namespace OTSSignsOrchestrator.Core.Data; - -/// -/// Design-time factory for EF Core migrations tooling. -/// -public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory -{ - public XiboContext CreateDbContext(string[] args) - { - var optionsBuilder = new DbContextOptionsBuilder(); - optionsBuilder.UseSqlite("Data Source=design-time.db"); - - // Set up a temporary DataProtection provider for design-time use - var services = new ServiceCollection(); - services.AddDataProtection() - .SetApplicationName("OTSSignsOrchestrator"); - var sp = services.BuildServiceProvider(); - var dpProvider = sp.GetRequiredService(); - - return new XiboContext(optionsBuilder.Options, dpProvider); - } -} diff --git a/OTSSignsOrchestrator.Core/Data/XiboContext.cs b/OTSSignsOrchestrator.Core/Data/XiboContext.cs deleted file mode 100644 index 15ea03d..0000000 --- a/OTSSignsOrchestrator.Core/Data/XiboContext.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Microsoft.AspNetCore.DataProtection; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using OTSSignsOrchestrator.Core.Models.Entities; - -namespace OTSSignsOrchestrator.Core.Data; - -public class XiboContext : DbContext -{ - private readonly IDataProtectionProvider? _dataProtection; - - public XiboContext(DbContextOptions options, IDataProtectionProvider? dataProtection = null) - : base(options) - { - _dataProtection = dataProtection; - } - - public DbSet SshHosts => Set(); - public DbSet OperationLogs => Set(); - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - - // --- SshHost --- - modelBuilder.Entity(entity => - { - entity.HasIndex(e => e.Label).IsUnique(); - - if (_dataProtection != null) - { - var protector = _dataProtection.CreateProtector("OTSSignsOrchestrator.SshHost"); - var passphraseConverter = new ValueConverter( - v => v != null ? protector.Protect(v) : null, - v => v != null ? protector.Unprotect(v) : null); - var passwordConverter = new ValueConverter( - v => v != null ? protector.Protect(v) : null, - v => v != null ? protector.Unprotect(v) : null); - - entity.Property(e => e.KeyPassphrase).HasConversion(passphraseConverter); - entity.Property(e => e.Password).HasConversion(passwordConverter); - } - }); - - // --- OperationLog --- - modelBuilder.Entity(entity => - { - entity.HasIndex(e => e.Timestamp); - entity.HasIndex(e => e.StackName); - entity.HasIndex(e => e.Operation); - }); - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260217004115_DesktopInitial.Designer.cs b/OTSSignsOrchestrator.Core/Migrations/20260217004115_DesktopInitial.Designer.cs deleted file mode 100644 index ee2da66..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260217004115_DesktopInitial.Designer.cs +++ /dev/null @@ -1,290 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using OTSSignsOrchestrator.Core.Data; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - [DbContext(typeof(XiboContext))] - [Migration("20260217004115_DesktopInitial")] - partial class DesktopInitial - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.2"); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CmsServerName") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Constraints") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("DeletedAt") - .HasColumnType("TEXT"); - - b.Property("HostHttpPort") - .HasColumnType("INTEGER"); - - b.Property("LibraryHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("SmtpServer") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SmtpUsername") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SshHostId") - .HasColumnType("TEXT"); - - b.Property("StackName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("TemplateCacheKey") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("TemplateLastFetch") - .HasColumnType("TEXT"); - - b.Property("TemplateRepoPat") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("TemplateRepoUrl") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("ThemeHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("XiboApiTestStatus") - .HasColumnType("INTEGER"); - - b.Property("XiboApiTestedAt") - .HasColumnType("TEXT"); - - b.Property("XiboPassword") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("XiboUsername") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("CustomerName"); - - b.HasIndex("SshHostId"); - - b.HasIndex("StackName") - .IsUnique(); - - b.ToTable("CmsInstances"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("DurationMs") - .HasColumnType("INTEGER"); - - b.Property("InstanceId") - .HasColumnType("TEXT"); - - b.Property("Message") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Operation") - .HasColumnType("INTEGER"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("InstanceId"); - - b.HasIndex("Operation"); - - b.HasIndex("Timestamp"); - - b.ToTable("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SecretMetadata", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("IsGlobal") - .HasColumnType("INTEGER"); - - b.Property("LastRotatedAt") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("SecretMetadata"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("Host") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("KeyPassphrase") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Label") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("LastTestSuccess") - .HasColumnType("INTEGER"); - - b.Property("LastTestedAt") - .HasColumnType("TEXT"); - - b.Property("Password") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Port") - .HasColumnType("INTEGER"); - - b.Property("PrivateKeyPath") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("UseKeyAuth") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Label") - .IsUnique(); - - b.ToTable("SshHosts"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.SshHost", "SshHost") - .WithMany("Instances") - .HasForeignKey("SshHostId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("SshHost"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", "Instance") - .WithMany("OperationLogs") - .HasForeignKey("InstanceId"); - - b.Navigation("Instance"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Navigation("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Navigation("Instances"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260217004115_DesktopInitial.cs b/OTSSignsOrchestrator.Core/Migrations/20260217004115_DesktopInitial.cs deleted file mode 100644 index c112a5f..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260217004115_DesktopInitial.cs +++ /dev/null @@ -1,175 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - /// - public partial class DesktopInitial : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "SecretMetadata", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - Name = table.Column(type: "TEXT", maxLength: 200, nullable: false), - IsGlobal = table.Column(type: "INTEGER", nullable: false), - CustomerName = table.Column(type: "TEXT", maxLength: 100, nullable: true), - CreatedAt = table.Column(type: "TEXT", nullable: false), - LastRotatedAt = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_SecretMetadata", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "SshHosts", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - Label = table.Column(type: "TEXT", maxLength: 200, nullable: false), - Host = table.Column(type: "TEXT", maxLength: 500, nullable: false), - Port = table.Column(type: "INTEGER", nullable: false), - Username = table.Column(type: "TEXT", maxLength: 100, nullable: false), - PrivateKeyPath = table.Column(type: "TEXT", maxLength: 1000, nullable: true), - KeyPassphrase = table.Column(type: "TEXT", maxLength: 2000, nullable: true), - Password = table.Column(type: "TEXT", maxLength: 2000, nullable: true), - UseKeyAuth = table.Column(type: "INTEGER", nullable: false), - CreatedAt = table.Column(type: "TEXT", nullable: false), - UpdatedAt = table.Column(type: "TEXT", nullable: false), - LastTestedAt = table.Column(type: "TEXT", nullable: true), - LastTestSuccess = table.Column(type: "INTEGER", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_SshHosts", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "CmsInstances", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - CustomerName = table.Column(type: "TEXT", maxLength: 100, nullable: false), - StackName = table.Column(type: "TEXT", maxLength: 100, nullable: false), - CmsServerName = table.Column(type: "TEXT", maxLength: 200, nullable: false), - HostHttpPort = table.Column(type: "INTEGER", nullable: false), - ThemeHostPath = table.Column(type: "TEXT", maxLength: 500, nullable: false), - LibraryHostPath = table.Column(type: "TEXT", maxLength: 500, nullable: false), - SmtpServer = table.Column(type: "TEXT", maxLength: 200, nullable: false), - SmtpUsername = table.Column(type: "TEXT", maxLength: 200, nullable: false), - Constraints = table.Column(type: "TEXT", maxLength: 2000, nullable: true), - TemplateRepoUrl = table.Column(type: "TEXT", maxLength: 500, nullable: false), - TemplateRepoPat = table.Column(type: "TEXT", maxLength: 500, nullable: true), - TemplateLastFetch = table.Column(type: "TEXT", nullable: true), - TemplateCacheKey = table.Column(type: "TEXT", maxLength: 100, nullable: true), - Status = table.Column(type: "INTEGER", nullable: false), - XiboUsername = table.Column(type: "TEXT", maxLength: 500, nullable: true), - XiboPassword = table.Column(type: "TEXT", maxLength: 1000, nullable: true), - XiboApiTestStatus = table.Column(type: "INTEGER", nullable: false), - XiboApiTestedAt = table.Column(type: "TEXT", nullable: true), - CreatedAt = table.Column(type: "TEXT", nullable: false), - UpdatedAt = table.Column(type: "TEXT", nullable: false), - DeletedAt = table.Column(type: "TEXT", nullable: true), - SshHostId = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_CmsInstances", x => x.Id); - table.ForeignKey( - name: "FK_CmsInstances_SshHosts_SshHostId", - column: x => x.SshHostId, - principalTable: "SshHosts", - principalColumn: "Id", - onDelete: ReferentialAction.SetNull); - }); - - migrationBuilder.CreateTable( - name: "OperationLogs", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - Operation = table.Column(type: "INTEGER", nullable: false), - InstanceId = table.Column(type: "TEXT", nullable: true), - UserId = table.Column(type: "TEXT", maxLength: 200, nullable: true), - Status = table.Column(type: "INTEGER", nullable: false), - Message = table.Column(type: "TEXT", maxLength: 2000, nullable: true), - DurationMs = table.Column(type: "INTEGER", nullable: true), - Timestamp = table.Column(type: "TEXT", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_OperationLogs", x => x.Id); - table.ForeignKey( - name: "FK_OperationLogs_CmsInstances_InstanceId", - column: x => x.InstanceId, - principalTable: "CmsInstances", - principalColumn: "Id"); - }); - - migrationBuilder.CreateIndex( - name: "IX_CmsInstances_CustomerName", - table: "CmsInstances", - column: "CustomerName"); - - migrationBuilder.CreateIndex( - name: "IX_CmsInstances_SshHostId", - table: "CmsInstances", - column: "SshHostId"); - - migrationBuilder.CreateIndex( - name: "IX_CmsInstances_StackName", - table: "CmsInstances", - column: "StackName", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_OperationLogs_InstanceId", - table: "OperationLogs", - column: "InstanceId"); - - migrationBuilder.CreateIndex( - name: "IX_OperationLogs_Operation", - table: "OperationLogs", - column: "Operation"); - - migrationBuilder.CreateIndex( - name: "IX_OperationLogs_Timestamp", - table: "OperationLogs", - column: "Timestamp"); - - migrationBuilder.CreateIndex( - name: "IX_SecretMetadata_Name", - table: "SecretMetadata", - column: "Name", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_SshHosts_Label", - table: "SshHosts", - column: "Label", - unique: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "OperationLogs"); - - migrationBuilder.DropTable( - name: "SecretMetadata"); - - migrationBuilder.DropTable( - name: "CmsInstances"); - - migrationBuilder.DropTable( - name: "SshHosts"); - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260218140239_AddCustomerAbbrev.Designer.cs b/OTSSignsOrchestrator.Core/Migrations/20260218140239_AddCustomerAbbrev.Designer.cs deleted file mode 100644 index abd7494..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260218140239_AddCustomerAbbrev.Designer.cs +++ /dev/null @@ -1,295 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using OTSSignsOrchestrator.Core.Data; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - [DbContext(typeof(XiboContext))] - [Migration("20260218140239_AddCustomerAbbrev")] - partial class AddCustomerAbbrev - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.2"); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CmsServerName") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Constraints") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerAbbrev") - .IsRequired() - .HasMaxLength(3) - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("DeletedAt") - .HasColumnType("TEXT"); - - b.Property("HostHttpPort") - .HasColumnType("INTEGER"); - - b.Property("LibraryHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("SmtpServer") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SmtpUsername") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SshHostId") - .HasColumnType("TEXT"); - - b.Property("StackName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("TemplateCacheKey") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("TemplateLastFetch") - .HasColumnType("TEXT"); - - b.Property("TemplateRepoPat") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("TemplateRepoUrl") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("ThemeHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("XiboApiTestStatus") - .HasColumnType("INTEGER"); - - b.Property("XiboApiTestedAt") - .HasColumnType("TEXT"); - - b.Property("XiboPassword") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("XiboUsername") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("CustomerName"); - - b.HasIndex("SshHostId"); - - b.HasIndex("StackName") - .IsUnique(); - - b.ToTable("CmsInstances"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("DurationMs") - .HasColumnType("INTEGER"); - - b.Property("InstanceId") - .HasColumnType("TEXT"); - - b.Property("Message") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Operation") - .HasColumnType("INTEGER"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("InstanceId"); - - b.HasIndex("Operation"); - - b.HasIndex("Timestamp"); - - b.ToTable("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SecretMetadata", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("IsGlobal") - .HasColumnType("INTEGER"); - - b.Property("LastRotatedAt") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("SecretMetadata"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("Host") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("KeyPassphrase") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Label") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("LastTestSuccess") - .HasColumnType("INTEGER"); - - b.Property("LastTestedAt") - .HasColumnType("TEXT"); - - b.Property("Password") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Port") - .HasColumnType("INTEGER"); - - b.Property("PrivateKeyPath") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("UseKeyAuth") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Label") - .IsUnique(); - - b.ToTable("SshHosts"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.SshHost", "SshHost") - .WithMany("Instances") - .HasForeignKey("SshHostId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("SshHost"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", "Instance") - .WithMany("OperationLogs") - .HasForeignKey("InstanceId"); - - b.Navigation("Instance"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Navigation("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Navigation("Instances"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260218140239_AddCustomerAbbrev.cs b/OTSSignsOrchestrator.Core/Migrations/20260218140239_AddCustomerAbbrev.cs deleted file mode 100644 index 43b24b8..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260218140239_AddCustomerAbbrev.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - /// - public partial class AddCustomerAbbrev : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "CustomerAbbrev", - table: "CmsInstances", - type: "TEXT", - maxLength: 3, - nullable: false, - defaultValue: ""); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "CustomerAbbrev", - table: "CmsInstances"); - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260218143812_AddAppSettings.Designer.cs b/OTSSignsOrchestrator.Core/Migrations/20260218143812_AddAppSettings.Designer.cs deleted file mode 100644 index 1f66b4e..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260218143812_AddAppSettings.Designer.cs +++ /dev/null @@ -1,323 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using OTSSignsOrchestrator.Core.Data; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - [DbContext(typeof(XiboContext))] - [Migration("20260218143812_AddAppSettings")] - partial class AddAppSettings - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.2"); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.AppSetting", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Category") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("IsSensitive") - .HasColumnType("INTEGER"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasMaxLength(4000) - .HasColumnType("TEXT"); - - b.HasKey("Key"); - - b.HasIndex("Category"); - - b.ToTable("AppSettings"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CmsServerName") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Constraints") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerAbbrev") - .IsRequired() - .HasMaxLength(3) - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("DeletedAt") - .HasColumnType("TEXT"); - - b.Property("HostHttpPort") - .HasColumnType("INTEGER"); - - b.Property("LibraryHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("SmtpServer") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SmtpUsername") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SshHostId") - .HasColumnType("TEXT"); - - b.Property("StackName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("TemplateCacheKey") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("TemplateLastFetch") - .HasColumnType("TEXT"); - - b.Property("TemplateRepoPat") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("TemplateRepoUrl") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("ThemeHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("XiboApiTestStatus") - .HasColumnType("INTEGER"); - - b.Property("XiboApiTestedAt") - .HasColumnType("TEXT"); - - b.Property("XiboPassword") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("XiboUsername") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("CustomerName"); - - b.HasIndex("SshHostId"); - - b.HasIndex("StackName") - .IsUnique(); - - b.ToTable("CmsInstances"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("DurationMs") - .HasColumnType("INTEGER"); - - b.Property("InstanceId") - .HasColumnType("TEXT"); - - b.Property("Message") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Operation") - .HasColumnType("INTEGER"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("InstanceId"); - - b.HasIndex("Operation"); - - b.HasIndex("Timestamp"); - - b.ToTable("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SecretMetadata", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("IsGlobal") - .HasColumnType("INTEGER"); - - b.Property("LastRotatedAt") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("SecretMetadata"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("Host") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("KeyPassphrase") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Label") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("LastTestSuccess") - .HasColumnType("INTEGER"); - - b.Property("LastTestedAt") - .HasColumnType("TEXT"); - - b.Property("Password") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Port") - .HasColumnType("INTEGER"); - - b.Property("PrivateKeyPath") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("UseKeyAuth") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Label") - .IsUnique(); - - b.ToTable("SshHosts"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.SshHost", "SshHost") - .WithMany("Instances") - .HasForeignKey("SshHostId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("SshHost"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", "Instance") - .WithMany("OperationLogs") - .HasForeignKey("InstanceId"); - - b.Navigation("Instance"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Navigation("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Navigation("Instances"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260218143812_AddAppSettings.cs b/OTSSignsOrchestrator.Core/Migrations/20260218143812_AddAppSettings.cs deleted file mode 100644 index 33f6a11..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260218143812_AddAppSettings.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - /// - public partial class AddAppSettings : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "AppSettings", - columns: table => new - { - Key = table.Column(type: "TEXT", maxLength: 200, nullable: false), - Value = table.Column(type: "TEXT", maxLength: 4000, nullable: true), - Category = table.Column(type: "TEXT", maxLength: 50, nullable: false), - IsSensitive = table.Column(type: "INTEGER", nullable: false), - UpdatedAt = table.Column(type: "TEXT", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AppSettings", x => x.Key); - }); - - migrationBuilder.CreateIndex( - name: "IX_AppSettings_Category", - table: "AppSettings", - column: "Category"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AppSettings"); - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260218144537_AddPerInstanceCifsCredentials.Designer.cs b/OTSSignsOrchestrator.Core/Migrations/20260218144537_AddPerInstanceCifsCredentials.Designer.cs deleted file mode 100644 index 44765bd..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260218144537_AddPerInstanceCifsCredentials.Designer.cs +++ /dev/null @@ -1,343 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using OTSSignsOrchestrator.Core.Data; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - [DbContext(typeof(XiboContext))] - [Migration("20260218144537_AddPerInstanceCifsCredentials")] - partial class AddPerInstanceCifsCredentials - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.2"); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.AppSetting", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Category") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("IsSensitive") - .HasColumnType("INTEGER"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasMaxLength(4000) - .HasColumnType("TEXT"); - - b.HasKey("Key"); - - b.HasIndex("Category"); - - b.ToTable("AppSettings"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CifsExtraOptions") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("CifsPassword") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("CifsServer") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("CifsShareBasePath") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("CifsUsername") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("CmsServerName") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Constraints") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerAbbrev") - .IsRequired() - .HasMaxLength(3) - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("DeletedAt") - .HasColumnType("TEXT"); - - b.Property("HostHttpPort") - .HasColumnType("INTEGER"); - - b.Property("LibraryHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("SmtpServer") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SmtpUsername") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SshHostId") - .HasColumnType("TEXT"); - - b.Property("StackName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("TemplateCacheKey") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("TemplateLastFetch") - .HasColumnType("TEXT"); - - b.Property("TemplateRepoPat") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("TemplateRepoUrl") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("ThemeHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("XiboApiTestStatus") - .HasColumnType("INTEGER"); - - b.Property("XiboApiTestedAt") - .HasColumnType("TEXT"); - - b.Property("XiboPassword") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("XiboUsername") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("CustomerName"); - - b.HasIndex("SshHostId"); - - b.HasIndex("StackName") - .IsUnique(); - - b.ToTable("CmsInstances"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("DurationMs") - .HasColumnType("INTEGER"); - - b.Property("InstanceId") - .HasColumnType("TEXT"); - - b.Property("Message") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Operation") - .HasColumnType("INTEGER"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("InstanceId"); - - b.HasIndex("Operation"); - - b.HasIndex("Timestamp"); - - b.ToTable("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SecretMetadata", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("IsGlobal") - .HasColumnType("INTEGER"); - - b.Property("LastRotatedAt") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("SecretMetadata"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("Host") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("KeyPassphrase") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Label") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("LastTestSuccess") - .HasColumnType("INTEGER"); - - b.Property("LastTestedAt") - .HasColumnType("TEXT"); - - b.Property("Password") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Port") - .HasColumnType("INTEGER"); - - b.Property("PrivateKeyPath") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("UseKeyAuth") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Label") - .IsUnique(); - - b.ToTable("SshHosts"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.SshHost", "SshHost") - .WithMany("Instances") - .HasForeignKey("SshHostId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("SshHost"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", "Instance") - .WithMany("OperationLogs") - .HasForeignKey("InstanceId"); - - b.Navigation("Instance"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Navigation("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Navigation("Instances"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260218144537_AddPerInstanceCifsCredentials.cs b/OTSSignsOrchestrator.Core/Migrations/20260218144537_AddPerInstanceCifsCredentials.cs deleted file mode 100644 index 7108a5c..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260218144537_AddPerInstanceCifsCredentials.cs +++ /dev/null @@ -1,73 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - /// - public partial class AddPerInstanceCifsCredentials : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "CifsExtraOptions", - table: "CmsInstances", - type: "TEXT", - maxLength: 500, - nullable: true); - - migrationBuilder.AddColumn( - name: "CifsPassword", - table: "CmsInstances", - type: "TEXT", - maxLength: 1000, - nullable: true); - - migrationBuilder.AddColumn( - name: "CifsServer", - table: "CmsInstances", - type: "TEXT", - maxLength: 200, - nullable: true); - - migrationBuilder.AddColumn( - name: "CifsShareBasePath", - table: "CmsInstances", - type: "TEXT", - maxLength: 500, - nullable: true); - - migrationBuilder.AddColumn( - name: "CifsUsername", - table: "CmsInstances", - type: "TEXT", - maxLength: 200, - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "CifsExtraOptions", - table: "CmsInstances"); - - migrationBuilder.DropColumn( - name: "CifsPassword", - table: "CmsInstances"); - - migrationBuilder.DropColumn( - name: "CifsServer", - table: "CmsInstances"); - - migrationBuilder.DropColumn( - name: "CifsShareBasePath", - table: "CmsInstances"); - - migrationBuilder.DropColumn( - name: "CifsUsername", - table: "CmsInstances"); - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260218180240_RenameShareBasePathToShareName.Designer.cs b/OTSSignsOrchestrator.Core/Migrations/20260218180240_RenameShareBasePathToShareName.Designer.cs deleted file mode 100644 index 69c2455..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260218180240_RenameShareBasePathToShareName.Designer.cs +++ /dev/null @@ -1,343 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using OTSSignsOrchestrator.Core.Data; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - [DbContext(typeof(XiboContext))] - [Migration("20260218180240_RenameShareBasePathToShareName")] - partial class RenameShareBasePathToShareName - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.2"); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.AppSetting", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Category") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("IsSensitive") - .HasColumnType("INTEGER"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasMaxLength(4000) - .HasColumnType("TEXT"); - - b.HasKey("Key"); - - b.HasIndex("Category"); - - b.ToTable("AppSettings"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CifsExtraOptions") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("CifsPassword") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("CifsServer") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("CifsShareName") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("CifsUsername") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("CmsServerName") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Constraints") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerAbbrev") - .IsRequired() - .HasMaxLength(3) - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("DeletedAt") - .HasColumnType("TEXT"); - - b.Property("HostHttpPort") - .HasColumnType("INTEGER"); - - b.Property("LibraryHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("SmtpServer") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SmtpUsername") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SshHostId") - .HasColumnType("TEXT"); - - b.Property("StackName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("TemplateCacheKey") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("TemplateLastFetch") - .HasColumnType("TEXT"); - - b.Property("TemplateRepoPat") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("TemplateRepoUrl") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("ThemeHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("XiboApiTestStatus") - .HasColumnType("INTEGER"); - - b.Property("XiboApiTestedAt") - .HasColumnType("TEXT"); - - b.Property("XiboPassword") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("XiboUsername") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("CustomerName"); - - b.HasIndex("SshHostId"); - - b.HasIndex("StackName") - .IsUnique(); - - b.ToTable("CmsInstances"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("DurationMs") - .HasColumnType("INTEGER"); - - b.Property("InstanceId") - .HasColumnType("TEXT"); - - b.Property("Message") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Operation") - .HasColumnType("INTEGER"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("InstanceId"); - - b.HasIndex("Operation"); - - b.HasIndex("Timestamp"); - - b.ToTable("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SecretMetadata", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("IsGlobal") - .HasColumnType("INTEGER"); - - b.Property("LastRotatedAt") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("SecretMetadata"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("Host") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("KeyPassphrase") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Label") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("LastTestSuccess") - .HasColumnType("INTEGER"); - - b.Property("LastTestedAt") - .HasColumnType("TEXT"); - - b.Property("Password") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Port") - .HasColumnType("INTEGER"); - - b.Property("PrivateKeyPath") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("UseKeyAuth") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Label") - .IsUnique(); - - b.ToTable("SshHosts"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.SshHost", "SshHost") - .WithMany("Instances") - .HasForeignKey("SshHostId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("SshHost"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", "Instance") - .WithMany("OperationLogs") - .HasForeignKey("InstanceId"); - - b.Navigation("Instance"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Navigation("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Navigation("Instances"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260218180240_RenameShareBasePathToShareName.cs b/OTSSignsOrchestrator.Core/Migrations/20260218180240_RenameShareBasePathToShareName.cs deleted file mode 100644 index 9320ae1..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260218180240_RenameShareBasePathToShareName.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - /// - public partial class RenameShareBasePathToShareName : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "CifsShareBasePath", - table: "CmsInstances", - newName: "CifsShareName"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "CifsShareName", - table: "CmsInstances", - newName: "CifsShareBasePath"); - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260218202617_AddCifsShareFolder.Designer.cs b/OTSSignsOrchestrator.Core/Migrations/20260218202617_AddCifsShareFolder.Designer.cs deleted file mode 100644 index a125238..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260218202617_AddCifsShareFolder.Designer.cs +++ /dev/null @@ -1,347 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using OTSSignsOrchestrator.Core.Data; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - [DbContext(typeof(XiboContext))] - [Migration("20260218202617_AddCifsShareFolder")] - partial class AddCifsShareFolder - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.2"); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.AppSetting", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Category") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("IsSensitive") - .HasColumnType("INTEGER"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasMaxLength(4000) - .HasColumnType("TEXT"); - - b.HasKey("Key"); - - b.HasIndex("Category"); - - b.ToTable("AppSettings"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CifsExtraOptions") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("CifsPassword") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("CifsServer") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("CifsShareFolder") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("CifsShareName") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("CifsUsername") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("CmsServerName") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Constraints") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerAbbrev") - .IsRequired() - .HasMaxLength(3) - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("DeletedAt") - .HasColumnType("TEXT"); - - b.Property("HostHttpPort") - .HasColumnType("INTEGER"); - - b.Property("LibraryHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("SmtpServer") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SmtpUsername") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SshHostId") - .HasColumnType("TEXT"); - - b.Property("StackName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("TemplateCacheKey") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("TemplateLastFetch") - .HasColumnType("TEXT"); - - b.Property("TemplateRepoPat") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("TemplateRepoUrl") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("ThemeHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("XiboApiTestStatus") - .HasColumnType("INTEGER"); - - b.Property("XiboApiTestedAt") - .HasColumnType("TEXT"); - - b.Property("XiboPassword") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("XiboUsername") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("CustomerName"); - - b.HasIndex("SshHostId"); - - b.HasIndex("StackName") - .IsUnique(); - - b.ToTable("CmsInstances"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("DurationMs") - .HasColumnType("INTEGER"); - - b.Property("InstanceId") - .HasColumnType("TEXT"); - - b.Property("Message") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Operation") - .HasColumnType("INTEGER"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("InstanceId"); - - b.HasIndex("Operation"); - - b.HasIndex("Timestamp"); - - b.ToTable("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SecretMetadata", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("IsGlobal") - .HasColumnType("INTEGER"); - - b.Property("LastRotatedAt") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("SecretMetadata"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("Host") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("KeyPassphrase") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Label") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("LastTestSuccess") - .HasColumnType("INTEGER"); - - b.Property("LastTestedAt") - .HasColumnType("TEXT"); - - b.Property("Password") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Port") - .HasColumnType("INTEGER"); - - b.Property("PrivateKeyPath") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("UseKeyAuth") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Label") - .IsUnique(); - - b.ToTable("SshHosts"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.SshHost", "SshHost") - .WithMany("Instances") - .HasForeignKey("SshHostId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("SshHost"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", "Instance") - .WithMany("OperationLogs") - .HasForeignKey("InstanceId"); - - b.Navigation("Instance"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Navigation("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Navigation("Instances"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260218202617_AddCifsShareFolder.cs b/OTSSignsOrchestrator.Core/Migrations/20260218202617_AddCifsShareFolder.cs deleted file mode 100644 index f612631..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260218202617_AddCifsShareFolder.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - /// - public partial class AddCifsShareFolder : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "CifsShareFolder", - table: "CmsInstances", - type: "TEXT", - maxLength: 500, - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "CifsShareFolder", - table: "CmsInstances"); - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260219005507_ReplaceCifsWithNfs.Designer.cs b/OTSSignsOrchestrator.Core/Migrations/20260219005507_ReplaceCifsWithNfs.Designer.cs deleted file mode 100644 index 4cca5a8..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260219005507_ReplaceCifsWithNfs.Designer.cs +++ /dev/null @@ -1,339 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using OTSSignsOrchestrator.Core.Data; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - [DbContext(typeof(XiboContext))] - [Migration("20260219005507_ReplaceCifsWithNfs")] - partial class ReplaceCifsWithNfs - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.2"); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.AppSetting", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Category") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("IsSensitive") - .HasColumnType("INTEGER"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasMaxLength(4000) - .HasColumnType("TEXT"); - - b.HasKey("Key"); - - b.HasIndex("Category"); - - b.ToTable("AppSettings"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CmsServerName") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Constraints") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerAbbrev") - .IsRequired() - .HasMaxLength(3) - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("DeletedAt") - .HasColumnType("TEXT"); - - b.Property("HostHttpPort") - .HasColumnType("INTEGER"); - - b.Property("LibraryHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("NfsExport") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("NfsExportFolder") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("NfsExtraOptions") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("NfsServer") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SmtpServer") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SmtpUsername") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SshHostId") - .HasColumnType("TEXT"); - - b.Property("StackName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("TemplateCacheKey") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("TemplateLastFetch") - .HasColumnType("TEXT"); - - b.Property("TemplateRepoPat") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("TemplateRepoUrl") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("ThemeHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("XiboApiTestStatus") - .HasColumnType("INTEGER"); - - b.Property("XiboApiTestedAt") - .HasColumnType("TEXT"); - - b.Property("XiboPassword") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("XiboUsername") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("CustomerName"); - - b.HasIndex("SshHostId"); - - b.HasIndex("StackName") - .IsUnique(); - - b.ToTable("CmsInstances"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("DurationMs") - .HasColumnType("INTEGER"); - - b.Property("InstanceId") - .HasColumnType("TEXT"); - - b.Property("Message") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Operation") - .HasColumnType("INTEGER"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("InstanceId"); - - b.HasIndex("Operation"); - - b.HasIndex("Timestamp"); - - b.ToTable("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SecretMetadata", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("IsGlobal") - .HasColumnType("INTEGER"); - - b.Property("LastRotatedAt") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("SecretMetadata"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("Host") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("KeyPassphrase") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Label") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("LastTestSuccess") - .HasColumnType("INTEGER"); - - b.Property("LastTestedAt") - .HasColumnType("TEXT"); - - b.Property("Password") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Port") - .HasColumnType("INTEGER"); - - b.Property("PrivateKeyPath") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("UseKeyAuth") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Label") - .IsUnique(); - - b.ToTable("SshHosts"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.SshHost", "SshHost") - .WithMany("Instances") - .HasForeignKey("SshHostId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("SshHost"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", "Instance") - .WithMany("OperationLogs") - .HasForeignKey("InstanceId"); - - b.Navigation("Instance"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Navigation("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Navigation("Instances"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260219005507_ReplaceCifsWithNfs.cs b/OTSSignsOrchestrator.Core/Migrations/20260219005507_ReplaceCifsWithNfs.cs deleted file mode 100644 index 5528f95..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260219005507_ReplaceCifsWithNfs.cs +++ /dev/null @@ -1,98 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - /// - public partial class ReplaceCifsWithNfs : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - // 1. Add new NFS columns - migrationBuilder.AddColumn( - name: "NfsServer", - table: "CmsInstances", - type: "TEXT", - maxLength: 200, - nullable: true); - - migrationBuilder.AddColumn( - name: "NfsExport", - table: "CmsInstances", - type: "TEXT", - maxLength: 500, - nullable: true); - - migrationBuilder.AddColumn( - name: "NfsExportFolder", - table: "CmsInstances", - type: "TEXT", - maxLength: 500, - nullable: true); - - migrationBuilder.AddColumn( - name: "NfsExtraOptions", - table: "CmsInstances", - type: "TEXT", - maxLength: 500, - nullable: true); - - // 2. Migrate existing CIFS data into NFS columns - // NfsServer = CifsServer, NfsExport = '/' + CifsShareName, NfsExportFolder = CifsShareFolder - migrationBuilder.Sql( - """ - UPDATE CmsInstances - SET NfsServer = CifsServer, - NfsExport = CASE WHEN CifsShareName IS NOT NULL THEN '/' || CifsShareName ELSE NULL END, - NfsExportFolder = CifsShareFolder, - NfsExtraOptions = CifsExtraOptions - WHERE CifsServer IS NOT NULL; - """); - - // 3. Drop old CIFS columns - migrationBuilder.DropColumn(name: "CifsServer", table: "CmsInstances"); - migrationBuilder.DropColumn(name: "CifsShareName", table: "CmsInstances"); - migrationBuilder.DropColumn(name: "CifsShareFolder", table: "CmsInstances"); - migrationBuilder.DropColumn(name: "CifsUsername", table: "CmsInstances"); - migrationBuilder.DropColumn(name: "CifsPassword", table: "CmsInstances"); - migrationBuilder.DropColumn(name: "CifsExtraOptions", table: "CmsInstances"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - // Re-add CIFS columns - migrationBuilder.AddColumn( - name: "CifsServer", table: "CmsInstances", type: "TEXT", maxLength: 200, nullable: true); - migrationBuilder.AddColumn( - name: "CifsShareName", table: "CmsInstances", type: "TEXT", maxLength: 500, nullable: true); - migrationBuilder.AddColumn( - name: "CifsShareFolder", table: "CmsInstances", type: "TEXT", maxLength: 500, nullable: true); - migrationBuilder.AddColumn( - name: "CifsUsername", table: "CmsInstances", type: "TEXT", maxLength: 200, nullable: true); - migrationBuilder.AddColumn( - name: "CifsPassword", table: "CmsInstances", type: "TEXT", maxLength: 1000, nullable: true); - migrationBuilder.AddColumn( - name: "CifsExtraOptions", table: "CmsInstances", type: "TEXT", maxLength: 500, nullable: true); - - // Copy NFS data back to CIFS columns - migrationBuilder.Sql( - """ - UPDATE CmsInstances - SET CifsServer = NfsServer, - CifsShareName = CASE WHEN NfsExport IS NOT NULL THEN LTRIM(NfsExport, '/') ELSE NULL END, - CifsShareFolder = NfsExportFolder, - CifsExtraOptions = NfsExtraOptions - WHERE NfsServer IS NOT NULL; - """); - - // Drop NFS columns - migrationBuilder.DropColumn(name: "NfsServer", table: "CmsInstances"); - migrationBuilder.DropColumn(name: "NfsExport", table: "CmsInstances"); - migrationBuilder.DropColumn(name: "NfsExportFolder", table: "CmsInstances"); - migrationBuilder.DropColumn(name: "NfsExtraOptions", table: "CmsInstances"); - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260219020727_AddNewtCredentials.Designer.cs b/OTSSignsOrchestrator.Core/Migrations/20260219020727_AddNewtCredentials.Designer.cs deleted file mode 100644 index b9a66ff..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260219020727_AddNewtCredentials.Designer.cs +++ /dev/null @@ -1,347 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using OTSSignsOrchestrator.Core.Data; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - [DbContext(typeof(XiboContext))] - [Migration("20260219020727_AddNewtCredentials")] - partial class AddNewtCredentials - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.2"); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.AppSetting", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Category") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("IsSensitive") - .HasColumnType("INTEGER"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasMaxLength(4000) - .HasColumnType("TEXT"); - - b.HasKey("Key"); - - b.HasIndex("Category"); - - b.ToTable("AppSettings"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CmsServerName") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Constraints") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerAbbrev") - .IsRequired() - .HasMaxLength(3) - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("DeletedAt") - .HasColumnType("TEXT"); - - b.Property("HostHttpPort") - .HasColumnType("INTEGER"); - - b.Property("LibraryHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("NewtId") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("NewtSecret") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("NfsExport") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("NfsExportFolder") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("NfsExtraOptions") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("NfsServer") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SmtpServer") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SmtpUsername") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("SshHostId") - .HasColumnType("TEXT"); - - b.Property("StackName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("TemplateCacheKey") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("TemplateLastFetch") - .HasColumnType("TEXT"); - - b.Property("TemplateRepoPat") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("TemplateRepoUrl") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("ThemeHostPath") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("XiboApiTestStatus") - .HasColumnType("INTEGER"); - - b.Property("XiboApiTestedAt") - .HasColumnType("TEXT"); - - b.Property("XiboPassword") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("XiboUsername") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("CustomerName"); - - b.HasIndex("SshHostId"); - - b.HasIndex("StackName") - .IsUnique(); - - b.ToTable("CmsInstances"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("DurationMs") - .HasColumnType("INTEGER"); - - b.Property("InstanceId") - .HasColumnType("TEXT"); - - b.Property("Message") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Operation") - .HasColumnType("INTEGER"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("InstanceId"); - - b.HasIndex("Operation"); - - b.HasIndex("Timestamp"); - - b.ToTable("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SecretMetadata", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CustomerName") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("IsGlobal") - .HasColumnType("INTEGER"); - - b.Property("LastRotatedAt") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("SecretMetadata"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("Host") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("KeyPassphrase") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Label") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("LastTestSuccess") - .HasColumnType("INTEGER"); - - b.Property("LastTestedAt") - .HasColumnType("TEXT"); - - b.Property("Password") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Port") - .HasColumnType("INTEGER"); - - b.Property("PrivateKeyPath") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("UseKeyAuth") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Label") - .IsUnique(); - - b.ToTable("SshHosts"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.SshHost", "SshHost") - .WithMany("Instances") - .HasForeignKey("SshHostId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("SshHost"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.HasOne("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", "Instance") - .WithMany("OperationLogs") - .HasForeignKey("InstanceId"); - - b.Navigation("Instance"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.CmsInstance", b => - { - b.Navigation("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Navigation("Instances"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260219020727_AddNewtCredentials.cs b/OTSSignsOrchestrator.Core/Migrations/20260219020727_AddNewtCredentials.cs deleted file mode 100644 index ad0d105..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260219020727_AddNewtCredentials.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - /// - public partial class AddNewtCredentials : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "NewtId", - table: "CmsInstances", - type: "TEXT", - maxLength: 500, - nullable: true); - - migrationBuilder.AddColumn( - name: "NewtSecret", - table: "CmsInstances", - type: "TEXT", - maxLength: 500, - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "NewtId", - table: "CmsInstances"); - - migrationBuilder.DropColumn( - name: "NewtSecret", - table: "CmsInstances"); - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260219121529_RemoveCmsInstancesAndSecretMetadata.Designer.cs b/OTSSignsOrchestrator.Core/Migrations/20260219121529_RemoveCmsInstancesAndSecretMetadata.Designer.cs deleted file mode 100644 index ea5f1fc..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260219121529_RemoveCmsInstancesAndSecretMetadata.Designer.cs +++ /dev/null @@ -1,153 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using OTSSignsOrchestrator.Core.Data; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - [DbContext(typeof(XiboContext))] - [Migration("20260219121529_RemoveCmsInstancesAndSecretMetadata")] - partial class RemoveCmsInstancesAndSecretMetadata - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.2"); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.AppSetting", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Category") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("IsSensitive") - .HasColumnType("INTEGER"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasMaxLength(4000) - .HasColumnType("TEXT"); - - b.HasKey("Key"); - - b.HasIndex("Category"); - - b.ToTable("AppSettings"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("DurationMs") - .HasColumnType("INTEGER"); - - b.Property("Message") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Operation") - .HasColumnType("INTEGER"); - - b.Property("StackName") - .HasMaxLength(150) - .HasColumnType("TEXT"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Operation"); - - b.HasIndex("StackName"); - - b.HasIndex("Timestamp"); - - b.ToTable("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("Host") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("KeyPassphrase") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Label") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("LastTestSuccess") - .HasColumnType("INTEGER"); - - b.Property("LastTestedAt") - .HasColumnType("TEXT"); - - b.Property("Password") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Port") - .HasColumnType("INTEGER"); - - b.Property("PrivateKeyPath") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("UseKeyAuth") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Label") - .IsUnique(); - - b.ToTable("SshHosts"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260219121529_RemoveCmsInstancesAndSecretMetadata.cs b/OTSSignsOrchestrator.Core/Migrations/20260219121529_RemoveCmsInstancesAndSecretMetadata.cs deleted file mode 100644 index 46b147e..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260219121529_RemoveCmsInstancesAndSecretMetadata.cs +++ /dev/null @@ -1,159 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - /// - public partial class RemoveCmsInstancesAndSecretMetadata : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_OperationLogs_CmsInstances_InstanceId", - table: "OperationLogs"); - - migrationBuilder.DropTable( - name: "CmsInstances"); - - migrationBuilder.DropTable( - name: "SecretMetadata"); - - migrationBuilder.DropIndex( - name: "IX_OperationLogs_InstanceId", - table: "OperationLogs"); - - migrationBuilder.DropColumn( - name: "InstanceId", - table: "OperationLogs"); - - migrationBuilder.AddColumn( - name: "StackName", - table: "OperationLogs", - type: "TEXT", - maxLength: 150, - nullable: true); - - migrationBuilder.CreateIndex( - name: "IX_OperationLogs_StackName", - table: "OperationLogs", - column: "StackName"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_OperationLogs_StackName", - table: "OperationLogs"); - - migrationBuilder.DropColumn( - name: "StackName", - table: "OperationLogs"); - - migrationBuilder.AddColumn( - name: "InstanceId", - table: "OperationLogs", - type: "TEXT", - nullable: true); - - migrationBuilder.CreateTable( - name: "CmsInstances", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - SshHostId = table.Column(type: "TEXT", nullable: true), - CmsServerName = table.Column(type: "TEXT", maxLength: 200, nullable: false), - Constraints = table.Column(type: "TEXT", maxLength: 2000, nullable: true), - CreatedAt = table.Column(type: "TEXT", nullable: false), - CustomerAbbrev = table.Column(type: "TEXT", maxLength: 3, nullable: false), - CustomerName = table.Column(type: "TEXT", maxLength: 100, nullable: false), - DeletedAt = table.Column(type: "TEXT", nullable: true), - HostHttpPort = table.Column(type: "INTEGER", nullable: false), - LibraryHostPath = table.Column(type: "TEXT", maxLength: 500, nullable: false), - NewtId = table.Column(type: "TEXT", maxLength: 500, nullable: true), - NewtSecret = table.Column(type: "TEXT", maxLength: 500, nullable: true), - NfsExport = table.Column(type: "TEXT", maxLength: 500, nullable: true), - NfsExportFolder = table.Column(type: "TEXT", maxLength: 500, nullable: true), - NfsExtraOptions = table.Column(type: "TEXT", maxLength: 500, nullable: true), - NfsServer = table.Column(type: "TEXT", maxLength: 200, nullable: true), - SmtpServer = table.Column(type: "TEXT", maxLength: 200, nullable: false), - SmtpUsername = table.Column(type: "TEXT", maxLength: 200, nullable: false), - StackName = table.Column(type: "TEXT", maxLength: 100, nullable: false), - Status = table.Column(type: "INTEGER", nullable: false), - TemplateCacheKey = table.Column(type: "TEXT", maxLength: 100, nullable: true), - TemplateLastFetch = table.Column(type: "TEXT", nullable: true), - TemplateRepoPat = table.Column(type: "TEXT", maxLength: 500, nullable: true), - TemplateRepoUrl = table.Column(type: "TEXT", maxLength: 500, nullable: false), - ThemeHostPath = table.Column(type: "TEXT", maxLength: 500, nullable: false), - UpdatedAt = table.Column(type: "TEXT", nullable: false), - XiboApiTestStatus = table.Column(type: "INTEGER", nullable: false), - XiboApiTestedAt = table.Column(type: "TEXT", nullable: true), - XiboPassword = table.Column(type: "TEXT", maxLength: 1000, nullable: true), - XiboUsername = table.Column(type: "TEXT", maxLength: 500, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_CmsInstances", x => x.Id); - table.ForeignKey( - name: "FK_CmsInstances_SshHosts_SshHostId", - column: x => x.SshHostId, - principalTable: "SshHosts", - principalColumn: "Id", - onDelete: ReferentialAction.SetNull); - }); - - migrationBuilder.CreateTable( - name: "SecretMetadata", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - CreatedAt = table.Column(type: "TEXT", nullable: false), - CustomerName = table.Column(type: "TEXT", maxLength: 100, nullable: true), - IsGlobal = table.Column(type: "INTEGER", nullable: false), - LastRotatedAt = table.Column(type: "TEXT", nullable: true), - Name = table.Column(type: "TEXT", maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_SecretMetadata", x => x.Id); - }); - - migrationBuilder.CreateIndex( - name: "IX_OperationLogs_InstanceId", - table: "OperationLogs", - column: "InstanceId"); - - migrationBuilder.CreateIndex( - name: "IX_CmsInstances_CustomerName", - table: "CmsInstances", - column: "CustomerName"); - - migrationBuilder.CreateIndex( - name: "IX_CmsInstances_SshHostId", - table: "CmsInstances", - column: "SshHostId"); - - migrationBuilder.CreateIndex( - name: "IX_CmsInstances_StackName", - table: "CmsInstances", - column: "StackName", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_SecretMetadata_Name", - table: "SecretMetadata", - column: "Name", - unique: true); - - migrationBuilder.AddForeignKey( - name: "FK_OperationLogs_CmsInstances_InstanceId", - table: "OperationLogs", - column: "InstanceId", - principalTable: "CmsInstances", - principalColumn: "Id"); - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260225135644_DropAppSettings.Designer.cs b/OTSSignsOrchestrator.Core/Migrations/20260225135644_DropAppSettings.Designer.cs deleted file mode 100644 index 392ea49..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260225135644_DropAppSettings.Designer.cs +++ /dev/null @@ -1,125 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using OTSSignsOrchestrator.Core.Data; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - [DbContext(typeof(XiboContext))] - [Migration("20260225135644_DropAppSettings")] - partial class DropAppSettings - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.2"); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("DurationMs") - .HasColumnType("INTEGER"); - - b.Property("Message") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Operation") - .HasColumnType("INTEGER"); - - b.Property("StackName") - .HasMaxLength(150) - .HasColumnType("TEXT"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Operation"); - - b.HasIndex("StackName"); - - b.HasIndex("Timestamp"); - - b.ToTable("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("Host") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("KeyPassphrase") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Label") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("LastTestSuccess") - .HasColumnType("INTEGER"); - - b.Property("LastTestedAt") - .HasColumnType("TEXT"); - - b.Property("Password") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Port") - .HasColumnType("INTEGER"); - - b.Property("PrivateKeyPath") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("UseKeyAuth") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Label") - .IsUnique(); - - b.ToTable("SshHosts"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/20260225135644_DropAppSettings.cs b/OTSSignsOrchestrator.Core/Migrations/20260225135644_DropAppSettings.cs deleted file mode 100644 index 8048481..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/20260225135644_DropAppSettings.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - /// - public partial class DropAppSettings : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AppSettings"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "AppSettings", - columns: table => new - { - Key = table.Column(type: "TEXT", maxLength: 200, nullable: false), - Category = table.Column(type: "TEXT", maxLength: 50, nullable: false), - IsSensitive = table.Column(type: "INTEGER", nullable: false), - UpdatedAt = table.Column(type: "TEXT", nullable: false), - Value = table.Column(type: "TEXT", maxLength: 4000, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AppSettings", x => x.Key); - }); - - migrationBuilder.CreateIndex( - name: "IX_AppSettings_Category", - table: "AppSettings", - column: "Category"); - } - } -} diff --git a/OTSSignsOrchestrator.Core/Migrations/XiboContextModelSnapshot.cs b/OTSSignsOrchestrator.Core/Migrations/XiboContextModelSnapshot.cs deleted file mode 100644 index 011fcef..0000000 --- a/OTSSignsOrchestrator.Core/Migrations/XiboContextModelSnapshot.cs +++ /dev/null @@ -1,122 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using OTSSignsOrchestrator.Core.Data; - -#nullable disable - -namespace OTSSignsOrchestrator.Core.Migrations -{ - [DbContext(typeof(XiboContext))] - partial class XiboContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.2"); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.OperationLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("DurationMs") - .HasColumnType("INTEGER"); - - b.Property("Message") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Operation") - .HasColumnType("INTEGER"); - - b.Property("StackName") - .HasMaxLength(150) - .HasColumnType("TEXT"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Operation"); - - b.HasIndex("StackName"); - - b.HasIndex("Timestamp"); - - b.ToTable("OperationLogs"); - }); - - modelBuilder.Entity("OTSSignsOrchestrator.Core.Models.Entities.SshHost", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("Host") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("KeyPassphrase") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Label") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("LastTestSuccess") - .HasColumnType("INTEGER"); - - b.Property("LastTestedAt") - .HasColumnType("TEXT"); - - b.Property("Password") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("Port") - .HasColumnType("INTEGER"); - - b.Property("PrivateKeyPath") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("UpdatedAt") - .HasColumnType("TEXT"); - - b.Property("UseKeyAuth") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Label") - .IsUnique(); - - b.ToTable("SshHosts"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/OTSSignsOrchestrator.Core/Models/Entities/AppSetting.cs b/OTSSignsOrchestrator.Core/Models/Entities/AppSetting.cs deleted file mode 100644 index ddffcf8..0000000 --- a/OTSSignsOrchestrator.Core/Models/Entities/AppSetting.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace OTSSignsOrchestrator.Core.Models.Entities; - -/// -/// Key-value application setting persisted in the local database. -/// Sensitive values are encrypted at rest via DataProtection. -/// -public class AppSetting -{ - [Key, MaxLength(200)] - public string Key { get; set; } = string.Empty; - - [MaxLength(4000)] - public string? Value { get; set; } - - [Required, MaxLength(50)] - public string Category { get; set; } = string.Empty; - - public bool IsSensitive { get; set; } - - public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; -} diff --git a/OTSSignsOrchestrator.Core/OTSSignsOrchestrator.Core.csproj b/OTSSignsOrchestrator.Core/OTSSignsOrchestrator.Core.csproj deleted file mode 100644 index d9241c1..0000000 --- a/OTSSignsOrchestrator.Core/OTSSignsOrchestrator.Core.csproj +++ /dev/null @@ -1,29 +0,0 @@ - - - - net9.0 - enable - enable - - - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - - - - - - diff --git a/OTSSignsOrchestrator.Core/Services/IInvitationSetupService.cs b/OTSSignsOrchestrator.Core/Services/IInvitationSetupService.cs deleted file mode 100644 index 0bf191f..0000000 --- a/OTSSignsOrchestrator.Core/Services/IInvitationSetupService.cs +++ /dev/null @@ -1,57 +0,0 @@ -namespace OTSSignsOrchestrator.Core.Services; - -/// -/// Orchestrates the complete Authentik invitation infrastructure setup for a customer. -/// Creates a group, enrollment flow with stages, role with invitation permissions, -/// and scoping policies so the customer admin can invite new users without OTS involvement. -/// -public interface IInvitationSetupService -{ - /// - /// Sets up the full invitation infrastructure for a customer in Authentik: - /// - /// Create customer group (e.g. customer-acme). - /// Create invitation stage (invite-only, no anonymous enrollment). - /// Create enrollment flow with stages: Invitation → Prompt → UserWrite → UserLogin. - /// Bind expression policy to UserWrite stage to auto-assign users to the customer group. - /// Create invite-manager role with invitation CRUD permissions. - /// Assign role to customer group and bind scoping policy to flow. - /// - /// All operations are idempotent — safe to call multiple times for the same customer. - /// - /// Short customer identifier (e.g. "acme"). - /// Human-readable customer name (e.g. "Acme Corp"). - /// Cancellation token. - /// Result describing what was created and the enrollment flow URL. - Task SetupCustomerInvitationAsync( - string customerAbbrev, - string customerName, - CancellationToken ct = default); -} - -/// -/// Result of the invitation infrastructure setup. -/// -public class InvitationSetupResult -{ - /// Whether the setup completed successfully. - public bool Success { get; set; } - - /// Human-readable status message. - public string Message { get; set; } = string.Empty; - - /// Name of the customer group created in Authentik. - public string GroupName { get; set; } = string.Empty; - - /// Slug of the enrollment flow (used in invite links). - public string EnrollmentFlowSlug { get; set; } = string.Empty; - - /// Name of the role created for invitation management. - public string RoleName { get; set; } = string.Empty; - - /// - /// Full URL to the Authentik user portal where the customer admin - /// can manage invitations. - /// - public string? InvitationManagementUrl { get; set; } -} diff --git a/OTSSignsOrchestrator.Core/Services/InvitationSetupService.cs b/OTSSignsOrchestrator.Core/Services/InvitationSetupService.cs deleted file mode 100644 index 5825e24..0000000 --- a/OTSSignsOrchestrator.Core/Services/InvitationSetupService.cs +++ /dev/null @@ -1,230 +0,0 @@ -using Microsoft.Extensions.Logging; - -namespace OTSSignsOrchestrator.Core.Services; - -/// -/// Orchestrates the 6-step Authentik invitation infrastructure setup for a customer. -/// All operations are idempotent — the underlying Authentik API methods check for -/// existing resources before creating new ones. -/// -/// Per customer, this creates: -/// 1. A group (customer-{abbrev}) -/// 2. An invitation stage ({abbrev}-invitation-stage) -/// 3. An enrollment flow ({abbrev}-enrollment) with stages bound in order -/// 4. An expression policy on the UserWrite stage to auto-assign users to the group -/// 5. A role ({abbrev}-invite-manager) with invitation CRUD permissions -/// 6. A scoping policy on the flow so only group members can access it -/// -public class InvitationSetupService : IInvitationSetupService -{ - private readonly IAuthentikService _authentik; - private readonly SettingsService _settings; - private readonly ILogger _logger; - - public InvitationSetupService( - IAuthentikService authentik, - SettingsService settings, - ILogger logger) - { - _authentik = authentik; - _settings = settings; - _logger = logger; - } - - /// - public async Task SetupCustomerInvitationAsync( - string customerAbbrev, - string customerName, - CancellationToken ct = default) - { - var abbrev = customerAbbrev.Trim().ToLowerInvariant(); - var groupName = $"customer-{abbrev}"; - var flowSlug = $"{abbrev}-enrollment"; - var flowName = $"{customerName} Enrollment"; - var roleName = $"{abbrev}-invite-manager"; - var invitationStageName = $"{abbrev}-invitation-stage"; - - _logger.LogInformation( - "[InviteSetup] Starting invitation infrastructure setup for customer '{Customer}' (abbrev={Abbrev})", - customerName, abbrev); - - try - { - // ═══════════════════════════════════════════════════════════════════ - // Step 1: Create customer group - // ═══════════════════════════════════════════════════════════════════ - _logger.LogInformation("[InviteSetup] Step 1/6: Creating customer group '{Group}'", groupName); - var groupPk = await _authentik.CreateGroupAsync(groupName, ct); - - // ═══════════════════════════════════════════════════════════════════ - // Step 2: Create invitation stage - // ═══════════════════════════════════════════════════════════════════ - _logger.LogInformation("[InviteSetup] Step 2/6: Creating invitation stage '{Stage}'", invitationStageName); - var invitationStagePk = await _authentik.CreateInvitationStageAsync( - invitationStageName, continueWithoutInvitation: false, ct); - - // ═══════════════════════════════════════════════════════════════════ - // Step 3: Create enrollment flow and bind stages - // ═══════════════════════════════════════════════════════════════════ - _logger.LogInformation("[InviteSetup] Step 3/6: Creating enrollment flow '{Slug}'", flowSlug); - var flowPk = await _authentik.CreateEnrollmentFlowAsync(flowName, flowSlug, ct); - - // Resolve built-in Authentik stages for the enrollment pipeline - var promptStagePk = await _authentik.FindStageByNameAsync("default-enrollment-prompt", ct); - var userWriteStagePk = await _authentik.FindStageByNameAsync("default-enrollment-user-write", ct); - var userLoginStagePk = await _authentik.FindStageByNameAsync("default-enrollment-user-login", ct); - - // Bind stages in order: 10=Invitation, 20=Prompt, 30=UserWrite, 40=UserLogin - await _authentik.BindStageToFlowAsync(flowSlug, invitationStagePk, 10, ct); - - if (promptStagePk != null) - { - await _authentik.BindStageToFlowAsync(flowSlug, promptStagePk, 20, ct); - _logger.LogInformation("[InviteSetup] Bound default prompt stage at order 20"); - } - else - { - _logger.LogWarning("[InviteSetup] Built-in 'default-enrollment-prompt' stage not found — " + - "you may need to create a prompt stage manually and bind it to flow '{Slug}' at order 20", flowSlug); - } - - if (userWriteStagePk != null) - { - await _authentik.BindStageToFlowAsync(flowSlug, userWriteStagePk, 30, ct); - _logger.LogInformation("[InviteSetup] Bound default user-write stage at order 30"); - } - else - { - _logger.LogWarning("[InviteSetup] Built-in 'default-enrollment-user-write' stage not found — " + - "you may need to create a user-write stage manually and bind it to flow '{Slug}' at order 30", flowSlug); - } - - if (userLoginStagePk != null) - { - await _authentik.BindStageToFlowAsync(flowSlug, userLoginStagePk, 40, ct); - _logger.LogInformation("[InviteSetup] Bound default user-login stage at order 40"); - } - else - { - _logger.LogWarning("[InviteSetup] Built-in 'default-enrollment-user-login' stage not found — " + - "you may need to create a user-login stage manually and bind it to flow '{Slug}' at order 40", flowSlug); - } - - // ═══════════════════════════════════════════════════════════════════ - // Step 4: Create group-assignment policy and bind to UserWrite stage - // ═══════════════════════════════════════════════════════════════════ - _logger.LogInformation("[InviteSetup] Step 4/6: Creating group-assignment expression policy"); - - var groupAssignPolicyName = $"{abbrev}-auto-assign-group"; - var groupAssignExpression = $""" - from authentik.core.models import Group - - # Auto-assign to customer group on registration - group = Group.objects.filter(name="{groupName}").first() - if group and context.get("pending_user"): - context["pending_user"].ak_groups.add(group) - - return True - """; - - var groupAssignPolicyPk = await _authentik.CreateExpressionPolicyAsync( - groupAssignPolicyName, groupAssignExpression, ct); - - // Bind policy to the UserWrite stage binding (order 30) - if (userWriteStagePk != null) - { - var userWriteBindingPk = await _authentik.GetFlowStageBindingPkAsync(flowSlug, 30, ct); - if (userWriteBindingPk != null) - { - await _authentik.BindPolicyToFlowStageBoundAsync(userWriteBindingPk, groupAssignPolicyPk, ct); - _logger.LogInformation("[InviteSetup] Group-assignment policy bound to UserWrite stage"); - } - else - { - _logger.LogWarning("[InviteSetup] Could not find flow-stage binding at order 30 to attach group policy"); - } - } - - // ═══════════════════════════════════════════════════════════════════ - // Step 5: Create invite-manager role with permissions - // ═══════════════════════════════════════════════════════════════════ - _logger.LogInformation("[InviteSetup] Step 5/6: Creating invite-manager role '{Role}'", roleName); - var rolePk = await _authentik.CreateRoleAsync(roleName, ct); - - // Assign invitation CRUD permissions - var invitationPermissions = new[] - { - "add_invitation", - "view_invitation", - "delete_invitation", - }; - await _authentik.AssignPermissionsToRoleAsync(rolePk, invitationPermissions, ct); - - // Assign role to the customer group - await _authentik.AssignRoleToGroupAsync(rolePk, groupPk, ct); - _logger.LogInformation("[InviteSetup] Role '{Role}' assigned to group '{Group}'", roleName, groupName); - - // ═══════════════════════════════════════════════════════════════════ - // Step 6: Create scoping policy and bind to flow - // ═══════════════════════════════════════════════════════════════════ - _logger.LogInformation("[InviteSetup] Step 6/6: Creating invitation scoping policy"); - - var scopePolicyName = $"scope-invitations-to-{abbrev}"; - var scopeExpression = $""" - # Only allow users in {groupName} group to manage these invitations - user = context.get("pending_user") or request.user - - if user.ak_groups.filter(name="{groupName}").exists(): - return True - - return False - """; - - var scopePolicyPk = await _authentik.CreateExpressionPolicyAsync(scopePolicyName, scopeExpression, ct); - - // Bind scoping policy to the enrollment flow - await _authentik.BindPolicyToFlowAsync(flowSlug, scopePolicyPk, ct); - _logger.LogInformation("[InviteSetup] Scoping policy bound to enrollment flow"); - - // ═══════════════════════════════════════════════════════════════════ - // Build result with management URL - // ═══════════════════════════════════════════════════════════════════ - var authentikUrl = await _settings.GetAsync(SettingsService.AuthentikUrl); - var managementUrl = !string.IsNullOrWhiteSpace(authentikUrl) - ? $"{authentikUrl.TrimEnd('/')}/if/admin/#/core/invitations" - : null; - - var result = new InvitationSetupResult - { - Success = true, - Message = $"Invitation infrastructure created for {customerName}. " + - $"Group: {groupName}, Flow: {flowSlug}, Role: {roleName}.", - GroupName = groupName, - EnrollmentFlowSlug = flowSlug, - RoleName = roleName, - InvitationManagementUrl = managementUrl, - }; - - _logger.LogInformation( - "[InviteSetup] Setup complete for '{Customer}': group={Group}, flow={Flow}, role={Role}, url={Url}", - customerName, groupName, flowSlug, roleName, managementUrl ?? "(no URL)"); - - return result; - } - catch (Exception ex) - { - _logger.LogError(ex, - "[InviteSetup] Invitation setup failed for '{Customer}' (abbrev={Abbrev}): {Message}", - customerName, abbrev, ex.Message); - - return new InvitationSetupResult - { - Success = false, - Message = $"Invitation setup failed: {ex.Message}", - GroupName = groupName, - EnrollmentFlowSlug = flowSlug, - RoleName = roleName, - }; - } - } -} diff --git a/OTSSignsOrchestrator.Desktop/App.axaml b/OTSSignsOrchestrator.Desktop/App.axaml deleted file mode 100644 index 095d24d..0000000 --- a/OTSSignsOrchestrator.Desktop/App.axaml +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - #D93A00 - #E54B14 - #BF3300 - #2A1A14 - - #0C0C14 - #11111B - #181825 - #1E1E2E - #232336 - #2A2A40 - - #CDD6F4 - #A6ADC8 - #6C7086 - - #4ADE80 - #60A5FA - #C084FC - #F472B6 - #FBBF24 - #2DD4BF - #F87171 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/OTSSignsOrchestrator.Desktop/App.axaml.cs b/OTSSignsOrchestrator.Desktop/App.axaml.cs deleted file mode 100644 index 6d42de6..0000000 --- a/OTSSignsOrchestrator.Desktop/App.axaml.cs +++ /dev/null @@ -1,208 +0,0 @@ -using Avalonia; -using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Markup.Xaml; -using Microsoft.AspNetCore.DataProtection; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Http; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Polly; -using Polly.Extensions.Http; -using Refit; -using Serilog; -using OTSSignsOrchestrator.Core.Configuration; -using OTSSignsOrchestrator.Core.Data; -using OTSSignsOrchestrator.Core.Services; -using OTSSignsOrchestrator.Desktop.Services; -using OTSSignsOrchestrator.Desktop.ViewModels; -using OTSSignsOrchestrator.Desktop.Views; - -namespace OTSSignsOrchestrator.Desktop; - -public class App : Application -{ - public static IServiceProvider Services { get; private set; } = null!; - - public override void Initialize() - { - AvaloniaXamlLoader.Load(this); - } - - public override void OnFrameworkInitializationCompleted() - { - var services = new ServiceCollection(); - ConfigureServices(services); - Services = services.BuildServiceProvider(); - - // Apply migrations - using (var scope = Services.CreateScope()) - { - var db = scope.ServiceProvider.GetRequiredService(); - db.Database.Migrate(); - } - - Log.Information("ApplicationLifetime type: {Type}", ApplicationLifetime?.GetType().FullName ?? "null"); - - if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) - { - Log.Information("Creating MainWindow..."); - - // Import existing instance secrets from Bitwarden (fire-and-forget, non-blocking) - _ = Task.Run(async () => - { - try - { - // Pre-load config settings from Bitwarden so they're available immediately - using var scope = Services.CreateScope(); - var settings = scope.ServiceProvider.GetRequiredService(); - await settings.PreloadCacheAsync(); - Log.Information("Bitwarden config settings pre-loaded"); - - // Import existing instance secrets that aren't yet tracked - var postInit = Services.GetRequiredService(); - await postInit.ImportExistingInstanceSecretsAsync(); - } - catch (Exception ex) - { - Log.Warning(ex, "Failed to pre-load settings or import instance secrets on startup"); - } - }); - - var vm = Services.GetRequiredService(); - Log.Information("MainWindowViewModel resolved"); - - var window = new MainWindow - { - DataContext = vm - }; - - desktop.MainWindow = window; - Log.Information("MainWindow assigned to lifetime"); - - window.Show(); - window.Activate(); - Log.Information("MainWindow Show() + Activate() called"); - - // Start the SignalR connection (fire-and-forget, reconnect handles failures) - _ = Task.Run(async () => - { - try - { - var signalR = Services.GetRequiredService(); - await signalR.StartAsync(); - } - catch (Exception ex) - { - Log.Warning(ex, "Failed to start SignalR connection on startup"); - } - }); - - desktop.ShutdownRequested += (_, _) => - { - var ssh = Services.GetService(); - ssh?.Dispose(); - var signalR = Services.GetService(); - signalR?.DisposeAsync().AsTask().GetAwaiter().GetResult(); - }; - } - else - { - Log.Warning("ApplicationLifetime is NOT IClassicDesktopStyleApplicationLifetime — window cannot be shown"); - } - - base.OnFrameworkInitializationCompleted(); - } - - private static void ConfigureServices(IServiceCollection services) - { - // Configuration (reloadOnChange so runtime writes to appsettings.json are picked up) - var config = new ConfigurationBuilder() - .SetBasePath(AppContext.BaseDirectory) - .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) - .Build(); - - services.AddSingleton(config); - - // Options - services.Configure(config.GetSection(GitOptions.SectionName)); - services.Configure(config.GetSection(DockerOptions.SectionName)); - services.Configure(config.GetSection(XiboOptions.SectionName)); - services.Configure(config.GetSection(DatabaseOptions.SectionName)); - services.Configure(config.GetSection(FileLoggingOptions.SectionName)); - services.Configure(config.GetSection(BitwardenOptions.SectionName)); - - // Logging - services.AddLogging(builder => - { - builder.ClearProviders(); - builder.AddSerilog(dispose: true); - }); - - // Data Protection - var keysDir = Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), - "OTSSignsOrchestrator", "keys"); - Directory.CreateDirectory(keysDir); - - services.AddDataProtection() - .PersistKeysToFileSystem(new DirectoryInfo(keysDir)) - .SetApplicationName("OTSSignsOrchestrator"); - - // Database - var connStr = config.GetConnectionString("Default") ?? "Data Source=otssigns-desktop.db"; - services.AddDbContext(options => options.UseSqlite(connStr)); - - // HTTP - services.AddHttpClient(); - services.AddHttpClient("XiboApi"); - services.AddHttpClient("XiboHealth"); - services.AddHttpClient("AuthentikApi"); - - // ── Server API integration ────────────────────────────────────────── - services.AddSingleton(); - services.AddTransient(); - - var serverBaseUrl = config["ServerBaseUrl"] ?? "https://localhost:5001"; - services.AddRefitClient() - .ConfigureHttpClient(c => c.BaseAddress = new Uri(serverBaseUrl)) - .AddHttpMessageHandler() - .AddPolicyHandler(HttpPolicyExtensions - .HandleTransientHttpError() - .WaitAndRetryAsync(3, attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)))); - - services.AddSingleton(); - - // SSH services (singletons — maintain connections) - services.AddSingleton(); - - // Docker services via SSH (singletons — SetHost() must persist across scopes) - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(sp => sp.GetRequiredService()); - services.AddSingleton(sp => sp.GetRequiredService()); - - // Core services - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddSingleton(); - - // ViewModels - services.AddSingleton(); // singleton: one main window, nav state shared - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - } -} diff --git a/OTSSignsOrchestrator.Desktop/Assets/OTS-Signs.png b/OTSSignsOrchestrator.Desktop/Assets/OTS-Signs.png deleted file mode 100644 index 5adc220cdf45a325350f7566446bef3dd6283637..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1078214 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