From 0714ec64324a58e51743473f6cb3b550382033dd Mon Sep 17 00:00:00 2001 From: "DESKTOP-GENO133\\IvanPlex" Date: Wed, 17 Jan 2024 11:02:40 -0700 Subject: [PATCH] Create and Restore Backups. --- Controllers/FilesController.cs | 17 +++- Helper/FileHelper.cs | 122 ++++++++++++++++++++++++- Views/Home/_Settings.cshtml | 53 ++++++++++- Views/Vehicle/_CostMakeUpReport.cshtml | 2 +- wwwroot/js/supplyrecord.js | 2 +- 5 files changed, 184 insertions(+), 12 deletions(-) diff --git a/Controllers/FilesController.cs b/Controllers/FilesController.cs index bcf6ea8..176373e 100644 --- a/Controllers/FilesController.cs +++ b/Controllers/FilesController.cs @@ -46,12 +46,25 @@ namespace CarCareTracker.Controllers } [HttpPost] - public ActionResult DeleteFiles(string fileLocation) + public IActionResult DeleteFiles(string fileLocation) { var result = _fileHelper.DeleteFile(fileLocation); return Json(result); } - + [Authorize(Roles = nameof(UserData.IsRootUser))] + [HttpGet] + public IActionResult MakeBackup() + { + var result = _fileHelper.MakeBackup(); + return Json(result); + } + [Authorize(Roles = nameof(UserData.IsRootUser))] + [HttpPost] + public IActionResult RestoreBackup(string fileName) + { + var result = _fileHelper.RestoreBackup(fileName); + return Json(result); + } private string UploadFile(IFormFile fileToUpload) { string uploadDirectory = "temp/"; diff --git a/Helper/FileHelper.cs b/Helper/FileHelper.cs index 136e9de..82989f0 100644 --- a/Helper/FileHelper.cs +++ b/Helper/FileHelper.cs @@ -1,12 +1,16 @@ -namespace CarCareTracker.Helper +using System.IO.Compression; + +namespace CarCareTracker.Helper { public interface IFileHelper { string GetFullFilePath(string currentFilePath, bool mustExist = true); string MoveFileFromTemp(string currentFilePath, string newFolder); bool DeleteFile(string currentFilePath); + string MakeBackup(); + bool RestoreBackup(string fileName); } - public class FileHelper: IFileHelper + public class FileHelper : IFileHelper { private readonly IWebHostEnvironment _webEnv; public FileHelper(IWebHostEnvironment webEnv) @@ -23,7 +27,8 @@ if (File.Exists(oldFilePath)) { return oldFilePath; - } else if (!mustExist) + } + else if (!mustExist) { return oldFilePath; } @@ -31,6 +36,111 @@ return string.Empty; } } + public bool RestoreBackup(string fileName) + { + var fullFilePath = GetFullFilePath(fileName); + if (string.IsNullOrWhiteSpace(fullFilePath)) + { + return false; + } + try + { + var tempPath = Path.Combine(_webEnv.WebRootPath, $"temp/{Guid.NewGuid()}"); + if (!Directory.Exists(tempPath)) + Directory.CreateDirectory(tempPath); + //extract zip file + ZipFile.ExtractToDirectory(fullFilePath, tempPath); + //copy over images and documents. + var imagePath = Path.Combine(tempPath, "images"); + var documentPath = Path.Combine(tempPath, "documents"); + var dataPath = Path.Combine(tempPath, StaticHelper.DbName); + var configPath = Path.Combine(tempPath, StaticHelper.UserConfigPath); + if (Directory.Exists(imagePath)) + { + var existingPath = Path.Combine(_webEnv.WebRootPath, "images"); + if (Directory.Exists(existingPath)) + { + Directory.Delete(existingPath, true); + } + Directory.Move(imagePath, existingPath); + } + if (Directory.Exists(documentPath)) + { + var existingPath = Path.Combine(_webEnv.WebRootPath, "documents"); + if (Directory.Exists(existingPath)) + { + Directory.Delete(existingPath, true); + } + Directory.Move(documentPath, existingPath); + } + if (File.Exists(dataPath)) + { + //data path will always exist as it is created on startup if not. + File.Move(dataPath, StaticHelper.DbName, true); + } + if (File.Exists(configPath)) + { + //check if config folder exists. + if (!Directory.Exists("config/")) + { + Directory.CreateDirectory("config/"); + } + File.Move(configPath, StaticHelper.UserConfigPath, true); + } + return true; + } catch (Exception ex) + { + return false; + } + } + public string MakeBackup() + { + var folderName = $"db_backup_{DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")}"; + var tempPath = Path.Combine(_webEnv.WebRootPath, $"temp/{folderName}"); + var imagePath = Path.Combine(_webEnv.WebRootPath, "images"); + var documentPath = Path.Combine(_webEnv.WebRootPath, "documents"); + var dataPath = StaticHelper.DbName; + var configPath = StaticHelper.UserConfigPath; + if (!Directory.Exists(tempPath)) + Directory.CreateDirectory(tempPath); + if (Directory.Exists(imagePath)) + { + var files = Directory.GetFiles(imagePath); + foreach (var file in files) + { + var newPath = Path.Combine(tempPath, "images"); + Directory.CreateDirectory(newPath); + File.Copy(file, $"{newPath}/{Path.GetFileName(file)}"); + } + } + if (Directory.Exists(documentPath)) + { + var files = Directory.GetFiles(documentPath); + foreach (var file in files) + { + var newPath = Path.Combine(tempPath, "documents"); + Directory.CreateDirectory(newPath); + File.Copy(file, $"{newPath}/{Path.GetFileName(file)}"); + } + } + if (File.Exists(dataPath)) + { + var newPath = Path.Combine(tempPath, "data"); + Directory.CreateDirectory(newPath); + File.Copy(dataPath, $"{newPath}/{Path.GetFileName(dataPath)}"); + } + if (File.Exists(configPath)) + { + var newPath = Path.Combine(tempPath, "config"); + Directory.CreateDirectory(newPath); + File.Copy(configPath, $"{newPath}/{Path.GetFileName(configPath)}"); + } + var destFilePath = $"{tempPath}.zip"; + ZipFile.CreateFromDirectory(tempPath, destFilePath); + //delete temp directory + Directory.Delete(tempPath, true); + return $"/temp/{folderName}.zip"; + } public string MoveFileFromTemp(string currentFilePath, string newFolder) { string tempPath = "temp/"; @@ -38,7 +148,8 @@ { return currentFilePath; } - if (currentFilePath.StartsWith("/")) { + if (currentFilePath.StartsWith("/")) + { currentFilePath = currentFilePath.Substring(1); } string uploadPath = Path.Combine(_webEnv.WebRootPath, newFolder); @@ -67,7 +178,8 @@ if (!File.Exists(filePath)) //verify file no longer exists. { return true; - } else + } + else { return false; } diff --git a/Views/Home/_Settings.cshtml b/Views/Home/_Settings.cshtml index 32dfc4f..ff1297e 100644 --- a/Views/Home/_Settings.cshtml +++ b/Views/Home/_Settings.cshtml @@ -94,10 +94,8 @@
-
- Default Tab -
+ Default Tab
+ @if (User.IsInRole(nameof(UserData.IsRootUser))) + { +
+ Backups +
+
+ +
+
+ + +
+
+
+ }
@@ -187,6 +200,40 @@ } }) } + function makeBackup() { + $.get('/Files/MakeBackup', function (data) { + window.location.href = data; + }); + } + function openRestoreBackup(){ + $("#inputBackup").click(); + } + function restoreBackup(event) { + let formData = new FormData(); + formData.append("file", event.files[0]); + sloader.show(); + $.ajax({ + url: "/Files/HandleFileUpload", + data: formData, + cache: false, + processData: false, + contentType: false, + type: 'POST', + success: function (response) { + if (response.trim() != '') { + $.post('/Files/RestoreBackup', { fileName : response}, function (data) { + sloader.hide(); + if (data){ + successToast("Backup Restored"); + setTimeout(function () { window.location.href = '/Home/Index' }, 500); + } else { + errorToast("An error occurred, please try again later."); + } + }); + } + } + }); + } function enableAuthCheckChanged(){ var enableAuth = $("#enableAuth").is(":checked"); if (enableAuth) { diff --git a/Views/Vehicle/_CostMakeUpReport.cshtml b/Views/Vehicle/_CostMakeUpReport.cshtml index 2b92678..4f89530 100644 --- a/Views/Vehicle/_CostMakeUpReport.cshtml +++ b/Views/Vehicle/_CostMakeUpReport.cshtml @@ -9,7 +9,7 @@ new Chart($("#pie-chart"), { type: 'pie', data: { - labels: ["Planned Maintenance(Service Records)", "Unplanned Maintenance(Repairs)", "Upgrades", "Tax", "Fuel"], + labels: ["Service Records", "Repairs", "Upgrades", "Tax", "Fuel"], datasets: [ { label: "Expenses by Category", diff --git a/wwwroot/js/supplyrecord.js b/wwwroot/js/supplyrecord.js index 3f47e92..82a1131 100644 --- a/wwwroot/js/supplyrecord.js +++ b/wwwroot/js/supplyrecord.js @@ -93,7 +93,7 @@ function getAndValidateSupplyRecordValues() { } else { $("#supplyRecordDescription").removeClass("is-invalid"); } - if (supplyQuantity.trim() == '' || !isValidMoney(supplyQuantity)) { + if (supplyQuantity.trim() == '' || !isValidMoney(supplyQuantity) || parseFloat(supplyQuantity) < 0) { hasError = true; $("#supplyRecordQuantity").addClass("is-invalid"); } else {