From c127f2f38f075425e204ad266624a6aeeb3031d9 Mon Sep 17 00:00:00 2001 From: Artur Lewandowski Date: Fri, 19 Sep 2025 09:05:17 +0200 Subject: [PATCH 1/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 182a63f..21e1778 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 💾 DatabasesBackupServiceDotNet +# 💾 OctoBackup [🇵🇱 Read in Polish](README_PL.md) From 0bf5ae5e662bdd06e99fc37a92ace1048cb405a0 Mon Sep 17 00:00:00 2001 From: Artur Lewandowski Date: Fri, 19 Sep 2025 09:05:30 +0200 Subject: [PATCH 2/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 21e1778..199c796 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ --- -**DatabasesBackupServiceDotNet** is an open-source, containerized application built with **.NET 9 Blazor WebAssembly** using a modular monolith architecture. +**OctoBackup** is an open-source, containerized application built with **.NET 9 Blazor WebAssembly** using a modular monolith architecture. The application allows **centralized management of database backups across multiple servers** – currently supporting **MySQL**, **PostgreSQL** and **MS SQL Server**. --- From 0cd99cc77ea3b9139db57de5cb085845e68c8857 Mon Sep 17 00:00:00 2001 From: Artur Lewandowski Date: Fri, 19 Sep 2025 09:05:40 +0200 Subject: [PATCH 3/7] Update README_PL.md --- README_PL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README_PL.md b/README_PL.md index edfd040..5e4aa7e 100644 --- a/README_PL.md +++ b/README_PL.md @@ -1,4 +1,4 @@ -# 💾 DatabasesBackupServiceDotNet +# 💾 OctoBackup [🇵🇱 Read in English](README.md) @@ -14,7 +14,7 @@ --- -**DatabasesBackupServiceDotNet** to otwarto-źródłowa aplikacja konteneryzowana w **Dockerze**, napisana w **.NET 9 Blazor WebAssembly** w architekturze modularnego monolitu. +**OctoBackup** to otwarto-źródłowa aplikacja konteneryzowana w **Dockerze**, napisana w **.NET 9 Blazor WebAssembly** w architekturze modularnego monolitu. Aplikacja umożliwia **centralne zarządzanie kopiami zapasowymi wielu baz danych** – obecnie wspiera **MySQL**, **PostgreSQL** oraz **MS SQL Server**. --- From cc64c90ac18d7130c03bbd883f413cacd9892b89 Mon Sep 17 00:00:00 2001 From: Artur Lewandowski Date: Fri, 19 Sep 2025 09:06:31 +0200 Subject: [PATCH 4/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 199c796..68158d1 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ The application allows **centralized management of database backups across multi ## 🚀 Setup & Configuration -Go to the **WIKI** section and follow the setup instructions. +Go to the **[WIKI](https://github.com/Lewan24/OctoBackup/wiki)** section and follow the setup instructions. --- From 087e926fa563c8b9367a7ba583165ee94bf80804 Mon Sep 17 00:00:00 2001 From: Artur Lewandowski Date: Fri, 19 Sep 2025 09:06:50 +0200 Subject: [PATCH 5/7] Update README_PL.md --- README_PL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_PL.md b/README_PL.md index 5e4aa7e..d05a6cb 100644 --- a/README_PL.md +++ b/README_PL.md @@ -52,7 +52,7 @@ Aplikacja umożliwia **centralne zarządzanie kopiami zapasowymi wielu baz danyc ## 🚀 Uruchomienie i konfiguracja -Przejdź do sekcji **WIKI** i zapoznaj się z instrukcjami. +Przejdź do sekcji **[WIKI](https://github.com/Lewan24/OctoBackup/wiki)** i zapoznaj się z instrukcjami. ## 🗺️ Roadmap From 0426a07c8903cd5af79278bda91b6f8b27a0c9a2 Mon Sep 17 00:00:00 2001 From: artur Date: Fri, 26 Sep 2025 10:07:26 +0200 Subject: [PATCH 6/7] Change directory that holds configuration and backups to more universal code --- .../Services/DbBackupService.cs | 2 +- .../DbContext/ServerBackupsConfiguration.cs | 13 +------------ .../Shared/Modules.Shared/Common/DbCommon.cs | 12 +----------- 3 files changed, 3 insertions(+), 24 deletions(-) diff --git a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Application/Services/DbBackupService.cs b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Application/Services/DbBackupService.cs index c4c012e..036de51 100644 --- a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Application/Services/DbBackupService.cs +++ b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Application/Services/DbBackupService.cs @@ -282,7 +282,7 @@ await DeleteOldBackup.Delete(backupPath.DirectoryPath, serverConfig.TimeInDaysTo Id = Guid.CreateVersion7(), CreatedOn = DateTime.Now, ServerConnectionId = db.GetServerId(), - Name = $"{serverConn.ServerHost}:{serverConn.ServerPort}_{serverConn.DbName}", + Name = $"{serverConn.ServerHost} -> {serverConn.ServerPort} -> {serverConn.DbName}", FilePath = "" }; diff --git a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Core/Entities/DbContext/ServerBackupsConfiguration.cs b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Core/Entities/DbContext/ServerBackupsConfiguration.cs index ddcb469..9787536 100644 --- a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Core/Entities/DbContext/ServerBackupsConfiguration.cs +++ b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Core/Entities/DbContext/ServerBackupsConfiguration.cs @@ -11,18 +11,7 @@ public sealed class ServerBackupsConfiguration [NotMapped] private string BackupSaveDirectory { get; } = GetBackupDirectory(); private static string GetBackupDirectory() - { - if (OperatingSystem.IsWindows()) - return Path.Combine( - Path.GetDirectoryName(Environment.ProcessPath)!, - "backups"); - - if (OperatingSystem.IsLinux()) - return "/backups"; - - throw new PlatformNotSupportedException("Unsupported OS"); - } - + => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "OctoBackup", "Backups"); /// /// Create required directories for provided server and database diff --git a/DbBackupService/Src/Modules/Shared/Modules.Shared/Common/DbCommon.cs b/DbBackupService/Src/Modules/Shared/Modules.Shared/Common/DbCommon.cs index f9f24d8..226cb54 100644 --- a/DbBackupService/Src/Modules/Shared/Modules.Shared/Common/DbCommon.cs +++ b/DbBackupService/Src/Modules/Shared/Modules.Shared/Common/DbCommon.cs @@ -7,17 +7,7 @@ public static class DbCommon public static readonly string DbPath = Path.Join(DbFolder, "OctoBackup.db"); private static string GetDbDirectory() - { - if (OperatingSystem.IsWindows()) - return Path.Combine( - Path.GetDirectoryName(Environment.ProcessPath)!, - "db"); - - if (OperatingSystem.IsLinux()) - return "/db"; - - throw new PlatformNotSupportedException("Unsupported OS"); - } + => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "OctoBackup"); public static void CreateDbDirectoryIfNotExists() { From 3be77814bb8330526bddc313e59f440124e6708c Mon Sep 17 00:00:00 2001 From: artur Date: Fri, 10 Oct 2025 12:11:27 +0200 Subject: [PATCH 7/7] Cleanup old files. Fix appsettings.json Refactor AutoTestBackupConfigDto.cs Implement managing auto test backup configuration --- .../Data/Services/BackupsHttpClientService.cs | 10 + ...ditServerAutoTestConfigurationDialog.razor | 90 ++++++ .../Pages/BackupsModule/MyServers.razor | 12 + .../Server/Server.Api/Server.Api.http | 6 - .../Server/Server.Api/appsettings.json | 6 +- .../Server.Api/databasesConfigurations.json | 16 - .../Server/Server.Api/oldProgram.txt | 19 -- .../Services/TokenValidationService.cs | 12 +- .../Modules.Backup.Api/Servers/ServersEo.cs | 12 + .../Services/ServersService.cs | 50 ++- .../Workers/BackupWorker.cs | 2 +- .../DbContext/AutomaticBackupTestConfig.cs | 4 +- .../BackupsDbContextModelSnapshot.cs | 9 +- ...225_UpdateAutoTestConfigEntity.Designer.cs | 291 ++++++++++++++++++ ...251010094225_UpdateAutoTestConfigEntity.cs | 50 +++ .../Dtos/AutoTestBackupConfigDto.cs | 7 + .../Dtos/ServerConnectionDto.cs | 2 +- 17 files changed, 536 insertions(+), 62 deletions(-) create mode 100644 DbBackupService/Src/Bootstraper/Client/Client.UI/Pages/BackupsModule/Dialogs/Servers/EditServerAutoTestConfigurationDialog.razor delete mode 100644 DbBackupService/Src/Bootstraper/Server/Server.Api/Server.Api.http delete mode 100644 DbBackupService/Src/Bootstraper/Server/Server.Api/databasesConfigurations.json delete mode 100644 DbBackupService/Src/Bootstraper/Server/Server.Api/oldProgram.txt create mode 100644 DbBackupService/Src/Modules/BackupModule/Modules.Backup.Infrastructure/Migrations/20251010094225_UpdateAutoTestConfigEntity.Designer.cs create mode 100644 DbBackupService/Src/Modules/BackupModule/Modules.Backup.Infrastructure/Migrations/20251010094225_UpdateAutoTestConfigEntity.cs create mode 100644 DbBackupService/Src/Modules/BackupModule/Modules.Backup.Shared/Dtos/AutoTestBackupConfigDto.cs diff --git a/DbBackupService/Src/Bootstraper/Client/Client.UI/Data/Services/BackupsHttpClientService.cs b/DbBackupService/Src/Bootstraper/Client/Client.UI/Data/Services/BackupsHttpClientService.cs index 7f73bb5..e093dfc 100644 --- a/DbBackupService/Src/Bootstraper/Client/Client.UI/Data/Services/BackupsHttpClientService.cs +++ b/DbBackupService/Src/Bootstraper/Client/Client.UI/Data/Services/BackupsHttpClientService.cs @@ -70,4 +70,14 @@ public async Task> BackupServerAsync(Guid serverId) { return await api.PostAsync("/api/backups/PerformBackup", serverId); } + + public async Task> FetchAutoTestBackupConfig(Guid configurationId) + { + return await api.PostAsync("/api/servers/FetchAutoTestConfig", configurationId); + } + + public async Task> EditAutoTestBackupConfig(AutoTestBackupConfigDto config) + { + return await api.PostAsync("/api/servers/EditAutoTestConfig", config); + } } \ No newline at end of file diff --git a/DbBackupService/Src/Bootstraper/Client/Client.UI/Pages/BackupsModule/Dialogs/Servers/EditServerAutoTestConfigurationDialog.razor b/DbBackupService/Src/Bootstraper/Client/Client.UI/Pages/BackupsModule/Dialogs/Servers/EditServerAutoTestConfigurationDialog.razor new file mode 100644 index 0000000..a6c22e0 --- /dev/null +++ b/DbBackupService/Src/Bootstraper/Client/Client.UI/Pages/BackupsModule/Dialogs/Servers/EditServerAutoTestConfigurationDialog.razor @@ -0,0 +1,90 @@ +@using Client.UI.Data.Services +@using Modules.Backup.Shared.Dtos + +@inject BackupsHttpClientService Service +@inject ISnackbar Snackbar + + + + + + @if (_config is null) + { + + Searching for specified server configuration... + } + else + { + + + + + + } + + + + + Close + + + @if (_isSaving) + { + + } + else + { + Save Config + } + + + + + +@code { + [CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = null!; + [Parameter] public Guid ConfigurationId { get; set; } + + private AutoTestBackupConfigDto? _config; + + private bool _isSaving; + + protected override async Task OnInitializedAsync() + { + _isSaving = true; + + var result = await Service.FetchAutoTestBackupConfig(ConfigurationId); + + result.Switch( + config => _config = config, + error => Snackbar.Add(error, Severity.Error) + ); + + _isSaving = false; + } + + private void Close() + => MudDialog.Cancel(); + + private async Task Save() + { + _isSaving = true; + + if (_config is null) + { + Snackbar.Add("Config can't be null", Severity.Error); + + _isSaving = false; + return; + } + + var result = await Service.EditAutoTestBackupConfig(_config); + + result.Switch( + _ => Snackbar.Add("Successfully saved configuration", Severity.Success), + error => Snackbar.Add(error, Severity.Error) + ); + + _isSaving = false; + } +} diff --git a/DbBackupService/Src/Bootstraper/Client/Client.UI/Pages/BackupsModule/MyServers.razor b/DbBackupService/Src/Bootstraper/Client/Client.UI/Pages/BackupsModule/MyServers.razor index 4866147..993c69a 100644 --- a/DbBackupService/Src/Bootstraper/Client/Client.UI/Pages/BackupsModule/MyServers.razor +++ b/DbBackupService/Src/Bootstraper/Client/Client.UI/Pages/BackupsModule/MyServers.razor @@ -91,6 +91,9 @@ Perform Backup + + Auto Tests Configuration + @@ -236,4 +239,13 @@ _isProcessing = false; } + private async Task EditTestsConfig(Guid autoTestConfigId) + { + var parameters = new DialogParameters + { + { x => x.ConfigurationId, autoTestConfigId } + }; + + await DialogService.ShowAsync($"Server Tests Configuration", parameters); + } } \ No newline at end of file diff --git a/DbBackupService/Src/Bootstraper/Server/Server.Api/Server.Api.http b/DbBackupService/Src/Bootstraper/Server/Server.Api/Server.Api.http deleted file mode 100644 index 86485cf..0000000 --- a/DbBackupService/Src/Bootstraper/Server/Server.Api/Server.Api.http +++ /dev/null @@ -1,6 +0,0 @@ -@Server_Api_HostAddress = http://localhost:7001 - -GET {{Server_Api_HostAddress}}/backup/Test -Accept: application/json - -### diff --git a/DbBackupService/Src/Bootstraper/Server/Server.Api/appsettings.json b/DbBackupService/Src/Bootstraper/Server/Server.Api/appsettings.json index 9c42c52..dc139ba 100644 --- a/DbBackupService/Src/Bootstraper/Server/Server.Api/appsettings.json +++ b/DbBackupService/Src/Bootstraper/Server/Server.Api/appsettings.json @@ -1,8 +1,8 @@ { "NotifyServiceSettings": { "Env": "Dev", - "Scheme": "{wsProtocol}", - "DevelopmentPort": "{url.port}", + "Scheme": "https", + "DevelopmentPort": "5000", "ProductionHost": "production.example.com" }, "Logging": { @@ -22,7 +22,7 @@ "MainAdminEmailAddress": "admin@octo.com" }, "AllowedHosts": "*", - "AllowedOrigins": "{wsProtocol}://{url.hostname}:{url.port}", + "AllowedOrigins": "https://localhost, https://localhost:5000, https://localhost:5001", "https_port": 443, "SeqConfiguration": { "ApiKey": "", diff --git a/DbBackupService/Src/Bootstraper/Server/Server.Api/databasesConfigurations.json b/DbBackupService/Src/Bootstraper/Server/Server.Api/databasesConfigurations.json deleted file mode 100644 index ca4780e..0000000 --- a/DbBackupService/Src/Bootstraper/Server/Server.Api/databasesConfigurations.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "DbType": "MySql", - "DbName": "TestDb", - "DbUser": "root", - "DbPasswd": "toor", - "DbServerAndPort": "localhost:3306" - }, - { - "DbType": "PostgreSql", - "DbName": "TestPostgresDb", - "DbUser": "postgres", - "DbPasswd": "Passwd123", - "DbServerAndPort": "localhost:5432" - } -] \ No newline at end of file diff --git a/DbBackupService/Src/Bootstraper/Server/Server.Api/oldProgram.txt b/DbBackupService/Src/Bootstraper/Server/Server.Api/oldProgram.txt deleted file mode 100644 index fb9a153..0000000 --- a/DbBackupService/Src/Bootstraper/Server/Server.Api/oldProgram.txt +++ /dev/null @@ -1,19 +0,0 @@ -var configFilePath = Path.Combine(Directory.GetCurrentDirectory(), "Src", "ConfigurationFiles", "appsettings.json"); -var configJson = File.ReadAllText(configFilePath); -var applicationSettings = await ApplicationSettings.Prepare(configJson); - -var logger = LoggerConfiguration.PrepareSetup(applicationSettings.AppConfiguration).GetCurrentClassLogger(); - -logger.Info("Preparing application services..."); - -IEmailProviderService emailProviderService = - new EmailProviderService(applicationSettings.EmailProviderConfiguration, logger); -IDbBackupService backupService = - new DbBackupService(logger, applicationSettings.AppConfiguration, emailProviderService); -IApplicationService applicationService = new ApplicationService(logger, backupService, emailProviderService); - -logger.Info("Starting application..."); -await applicationService.RunService(); - -logger.Info("Shutting down Application"); -LogManager.Shutdown(); \ No newline at end of file diff --git a/DbBackupService/Src/Modules/AuthModule/Modules.Auth.Application/Services/TokenValidationService.cs b/DbBackupService/Src/Modules/AuthModule/Modules.Auth.Application/Services/TokenValidationService.cs index 956e190..0fbcacc 100644 --- a/DbBackupService/Src/Modules/AuthModule/Modules.Auth.Application/Services/TokenValidationService.cs +++ b/DbBackupService/Src/Modules/AuthModule/Modules.Auth.Application/Services/TokenValidationService.cs @@ -9,9 +9,13 @@ namespace Modules.Auth.Application.Services; internal class TokenValidationService(IUserTokenService tokensRepoService, ILogger logger) : ITokenValidationService { + // TODO: Add this to configurable section in admin's configuration panel + private readonly bool _enableTokenLogging = false; + public OneOf IsValid(string? token, string? userEmail) { - logger.LogInformation("Validating token {Token} for user {Email}...", token, userEmail); + if(_enableTokenLogging) + logger.LogInformation("Validating token {Token} for user {Email}...", token, userEmail); if (string.IsNullOrWhiteSpace(token) || string.IsNullOrWhiteSpace(userEmail)) { @@ -19,7 +23,8 @@ public OneOf IsValid(string? token, string? userEmail) return new False(); } - logger.LogDebug("Searching DB with passed token..."); + if(_enableTokenLogging) + logger.LogDebug("Searching DB with passed token..."); var userToken = tokensRepoService.GetUserTokens(t => t.Token == token && t.Email?.ToUpper() == userEmail.ToUpper()).FirstOrDefault(); @@ -42,7 +47,8 @@ public OneOf IsValid(string? token, string? userEmail) return new False(); } - logger.LogInformation("Token {Token} for user {Email} is Valid.", token, userEmail); + if(_enableTokenLogging) + logger.LogInformation("Token {Token} for user {Email} is Valid.", token, userEmail); return new True(); } } \ No newline at end of file diff --git a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Api/Servers/ServersEo.cs b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Api/Servers/ServersEo.cs index e6a00ef..5b3b9bb 100644 --- a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Api/Servers/ServersEo.cs +++ b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Api/Servers/ServersEo.cs @@ -59,6 +59,12 @@ public static WebApplication MapServersEndpoints(this WebApplication app) api.MapPost("TestServerConnection", ServersOperations.TestServerConnection) .WithSummary("Test server connection and execute test query to check communication with DB"); + + api.MapPost("FetchAutoTestConfig", ServersOperations.GetAutoTestConfig) + .WithSummary("Get specified server's AutoTest configuration"); + + api.MapPost("EditAutoTestConfig", ServersOperations.EditAutoTestConfig) + .WithSummary("Edit provided server's AutoTest configuration"); return app; } @@ -179,4 +185,10 @@ public static async Task TestServerConnection( { return await CallFuncAndReturnIResult(service.TestServerConnection, serverId); } + + public static async Task GetAutoTestConfig(HttpContext context, [FromServices] ServersService service, [FromBody] Guid configurationId) + => await CallFuncAndReturnIResult(service.GetAutoTestConfig, configurationId); + + public static async Task EditAutoTestConfig(HttpContext context, [FromServices] ServersService service, [FromBody] AutoTestBackupConfigDto config) + => await CallFuncAndReturnIResult(service.EditAutoTestConfig, config); } \ No newline at end of file diff --git a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Application/Services/ServersService.cs b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Application/Services/ServersService.cs index 88eaf6e..962eb58 100644 --- a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Application/Services/ServersService.cs +++ b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Application/Services/ServersService.cs @@ -76,7 +76,8 @@ public async Task, string>> GetServers(string? i DbName = server.DbName, DbType = server.DbType, DbUser = server.DbUser, - IsTunnelRequired = server.IsTunnelRequired + IsTunnelRequired = server.IsTunnelRequired, + AutoTestBackupsConfigId = server.AutoTestBackupsConfigId }; var dbTunnel = db.DbServerTunnels.FirstOrDefault(x => x.Id == server.TunnelId); @@ -212,6 +213,16 @@ public async Task> CreateServer(ServerConnectionDto newSe IsDisabled = false }; + var serverAutoTestBackupConfig = new AutomaticBackupTestConfig + { + Id = Guid.CreateVersion7(), + // TODO: Change this to global setting that is configurable in admin's config panel + IsEnabled = false, + ServerId = dbServer.Id + }; + + dbServer.AutoTestBackupsConfigId = serverAutoTestBackupConfig.Id; + // 3. Obsługa tunelu (opcjonalna) if (newServer.IsTunnelRequired) { @@ -243,7 +254,8 @@ public async Task> CreateServer(ServerConnectionDto newSe // 4. Zapis serwera db.DbConnections.Add(dbServer); - + db.AutomaticBackupTestConfigs.Add(serverAutoTestBackupConfig); + if (string.IsNullOrWhiteSpace(identityName)) return "Can't access username"; @@ -638,6 +650,9 @@ public async Task> DeleteServer(Guid serverId) var serverBackupConfig = db.Configurations.FirstOrDefault(x => x.ServerId == serverId); if (serverBackupConfig is not null) db.Configurations.Remove(serverBackupConfig); + + var serverAutoTestConfig = db.AutomaticBackupTestConfigs.FirstOrDefault(x => x.ServerId == serverId); + if (serverAutoTestConfig is not null) db.AutomaticBackupTestConfigs.Remove(serverAutoTestConfig); var backups = db.Backups.Where(x => x.ServerConnectionId == server.Id); if (backups.Any()) @@ -657,4 +672,35 @@ public async Task> DeleteServer(Guid serverId) return new Success(); } + + + public async Task> GetAutoTestConfig(Guid configId) + { + if (configId == Guid.Empty) + return "Invalid config id"; + + logger.LogInformation("Checking if config [{ConfigId}] exists...", configId); + + var config = await db.AutomaticBackupTestConfigs.FindAsync(configId); + if (config is null) + return "Can't find config"; + + return new AutoTestBackupConfigDto + { + Id = config.Id, + IsEnabled = config.IsEnabled + }; + } + + public async Task> EditAutoTestConfig(AutoTestBackupConfigDto config) + { + var dbConfig = await db.AutomaticBackupTestConfigs.FindAsync(config.Id); + if (dbConfig is null) + return "Can't find config"; + + dbConfig.IsEnabled = config.IsEnabled; + await db.SaveChangesAsync(); + + return new Success(); + } } \ No newline at end of file diff --git a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Application/Workers/BackupWorker.cs b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Application/Workers/BackupWorker.cs index 2047f67..a588055 100644 --- a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Application/Workers/BackupWorker.cs +++ b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Application/Workers/BackupWorker.cs @@ -16,7 +16,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) logger.LogInformation("Running backup worker in 20 seconds..."); await Task.Delay(TimeSpan.FromSeconds(20), stoppingToken); - logger.LogInformation("Worker will run each 10 seconds from now..."); + logger.LogInformation("Worker will run each {Interval} minutes from now...", _interval.Minutes); while (await timer.WaitForNextTickAsync(stoppingToken)) try { diff --git a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Core/Entities/DbContext/AutomaticBackupTestConfig.cs b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Core/Entities/DbContext/AutomaticBackupTestConfig.cs index 4e673ab..1843f3d 100644 --- a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Core/Entities/DbContext/AutomaticBackupTestConfig.cs +++ b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Core/Entities/DbContext/AutomaticBackupTestConfig.cs @@ -3,8 +3,6 @@ public sealed record AutomaticBackupTestConfig { public Guid Id { get; init; } - public required string Name { get; set; } + public Guid ServerId { get; set; } public bool IsEnabled { get; set; } = true; - public bool ShouldTestEveryBackup { get; set; } = true; - public short TestFrequency { get; set; } } \ No newline at end of file diff --git a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Infrastructure/DbContexts/Migrations/BackupsDbContextModelSnapshot.cs b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Infrastructure/DbContexts/Migrations/BackupsDbContextModelSnapshot.cs index 2d0fc2c..8aa73a4 100644 --- a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Infrastructure/DbContexts/Migrations/BackupsDbContextModelSnapshot.cs +++ b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Infrastructure/DbContexts/Migrations/BackupsDbContextModelSnapshot.cs @@ -26,16 +26,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("IsEnabled") .HasColumnType("INTEGER"); - b.Property("Name") - .IsRequired() + b.Property("ServerId") .HasColumnType("TEXT"); - b.Property("ShouldTestEveryBackup") - .HasColumnType("INTEGER"); - - b.Property("TestFrequency") - .HasColumnType("INTEGER"); - b.HasKey("Id"); b.ToTable("AutomaticBackupTestConfigs"); diff --git a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Infrastructure/Migrations/20251010094225_UpdateAutoTestConfigEntity.Designer.cs b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Infrastructure/Migrations/20251010094225_UpdateAutoTestConfigEntity.Designer.cs new file mode 100644 index 0000000..69de5f8 --- /dev/null +++ b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Infrastructure/Migrations/20251010094225_UpdateAutoTestConfigEntity.Designer.cs @@ -0,0 +1,291 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Modules.Backup.Infrastructure.DbContexts; + +#nullable disable + +namespace Modules.Backup.Infrastructure.Migrations +{ + [DbContext(typeof(BackupsDbContext))] + [Migration("20251010094225_UpdateAutoTestConfigEntity")] + partial class UpdateAutoTestConfigEntity + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.8"); + + modelBuilder.Entity("Modules.Backup.Core.Entities.DbContext.AutomaticBackupTestConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("IsEnabled") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("AutomaticBackupTestConfigs"); + }); + + modelBuilder.Entity("Modules.Backup.Core.Entities.DbContext.BackupSchedule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ConfigurationJson") + .HasColumnType("TEXT"); + + b.Property("DbConnectionId") + .HasColumnType("TEXT"); + + b.Property("IsEnabled") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("NextBackupDate") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Schedules"); + }); + + modelBuilder.Entity("Modules.Backup.Core.Entities.DbContext.BackupTest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("BackupId") + .HasColumnType("TEXT"); + + b.Property("ErrorMessage") + .HasColumnType("TEXT"); + + b.Property("IsSuccess") + .HasColumnType("INTEGER"); + + b.Property("TestedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("BackupsTests"); + }); + + modelBuilder.Entity("Modules.Backup.Core.Entities.DbContext.DbServerConnection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("AutoTestBackupsConfigId") + .HasColumnType("TEXT"); + + b.Property("BackupEncryptionKeyHas") + .HasColumnType("TEXT"); + + b.Property("ConnectionName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DbName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DbPasswd") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DbType") + .HasColumnType("INTEGER"); + + b.Property("DbUser") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IsDisabled") + .HasColumnType("INTEGER"); + + b.Property("IsTunnelRequired") + .HasColumnType("INTEGER"); + + b.Property("ServerHost") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ServerPort") + .HasColumnType("INTEGER"); + + b.Property("TunnelId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("DbConnections"); + }); + + modelBuilder.Entity("Modules.Backup.Core.Entities.DbContext.DbServerTunnel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("LocalPort") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PrivateKeyContent") + .HasColumnType("TEXT"); + + b.Property("PrivateKeyPassphrase") + .HasColumnType("TEXT"); + + b.Property("RemoteHost") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("RemotePort") + .HasColumnType("INTEGER"); + + b.Property("ServerHost") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SshPort") + .HasColumnType("INTEGER"); + + b.Property("UsePasswordAuth") + .HasColumnType("INTEGER"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("DbServerTunnels"); + }); + + modelBuilder.Entity("Modules.Backup.Core.Entities.DbContext.PerformedBackup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("FilePath") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ServerConnectionId") + .HasColumnType("TEXT"); + + b.Property("TestId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Backups"); + }); + + modelBuilder.Entity("Modules.Backup.Core.Entities.DbContext.ServerBackupsConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("TEXT"); + + b.Property("TimeInDaysToHoldBackups") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Configurations"); + }); + + modelBuilder.Entity("Modules.Backup.Core.Entities.DbContext.ServersUsers", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("UsersServers"); + }); + + modelBuilder.Entity("Modules.Backup.Core.Entities.DbContext.UserNotificationsSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("IsEnabled") + .HasColumnType("INTEGER"); + + b.Property("NotifyOnChanges") + .HasColumnType("INTEGER"); + + b.Property("NotifyOnErrors") + .HasColumnType("INTEGER"); + + b.Property("NotifyOnFailedBackups") + .HasColumnType("INTEGER"); + + b.Property("NotifyOnFailedTests") + .HasColumnType("INTEGER"); + + b.Property("NotifyOnSuccessfulBackup") + .HasColumnType("INTEGER"); + + b.Property("NotifyOnUpdates") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("UsersNotificationsSettings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Infrastructure/Migrations/20251010094225_UpdateAutoTestConfigEntity.cs b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Infrastructure/Migrations/20251010094225_UpdateAutoTestConfigEntity.cs new file mode 100644 index 0000000..296d3ab --- /dev/null +++ b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Infrastructure/Migrations/20251010094225_UpdateAutoTestConfigEntity.cs @@ -0,0 +1,50 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Modules.Backup.Infrastructure.Migrations +{ + /// + public partial class UpdateAutoTestConfigEntity : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ShouldTestEveryBackup", + table: "AutomaticBackupTestConfigs"); + + migrationBuilder.DropColumn( + name: "TestFrequency", + table: "AutomaticBackupTestConfigs"); + + migrationBuilder.RenameColumn( + name: "Name", + table: "AutomaticBackupTestConfigs", + newName: "ServerId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "ServerId", + table: "AutomaticBackupTestConfigs", + newName: "Name"); + + migrationBuilder.AddColumn( + name: "ShouldTestEveryBackup", + table: "AutomaticBackupTestConfigs", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "TestFrequency", + table: "AutomaticBackupTestConfigs", + type: "INTEGER", + nullable: false, + defaultValue: (short)0); + } + } +} diff --git a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Shared/Dtos/AutoTestBackupConfigDto.cs b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Shared/Dtos/AutoTestBackupConfigDto.cs new file mode 100644 index 0000000..efdb9fe --- /dev/null +++ b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Shared/Dtos/AutoTestBackupConfigDto.cs @@ -0,0 +1,7 @@ +namespace Modules.Backup.Shared.Dtos; + +public sealed class AutoTestBackupConfigDto +{ + public Guid Id { get; set; } = Guid.CreateVersion7(); + public bool IsEnabled { get; set; } = true; +} \ No newline at end of file diff --git a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Shared/Dtos/ServerConnectionDto.cs b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Shared/Dtos/ServerConnectionDto.cs index 0bdbb1f..10a682d 100644 --- a/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Shared/Dtos/ServerConnectionDto.cs +++ b/DbBackupService/Src/Modules/BackupModule/Modules.Backup.Shared/Dtos/ServerConnectionDto.cs @@ -16,5 +16,5 @@ public record ServerConnectionDto public bool IsTunnelRequired { get; set; } public ServerTunnelDto? Tunnel { get; set; } - //public Guid AutoTestBackupsConfigId { get; set; } + public Guid AutoTestBackupsConfigId { get; set; } } \ No newline at end of file