Implementing systemd file modification and various fixes
This commit is contained in:
		| @@ -14,11 +14,9 @@ | |||||||
| 	</div> | 	</div> | ||||||
|  |  | ||||||
| 	<div class="fileTitle"> | 	<div class="fileTitle"> | ||||||
| 		@if (IsAnyFileSelected) | 		<div class="field is-grouped @(IsAnyFileSelected ? null : "is-hidden")"> | ||||||
| 		{ |  | ||||||
| 			<div class="field is-grouped"> |  | ||||||
| 			<div class="control is-expanded borderRBig neomorphXSmall has-icons-left has-text-centered"> | 			<div class="control is-expanded borderRBig neomorphXSmall has-icons-left has-text-centered"> | ||||||
| 					<span>@SelectedFile.Name</span> | 				<span>@SelectedFile?.Name</span> | ||||||
| 			</div> | 			</div> | ||||||
| 			<p class="control @(IsDraftMode ? "is-hidden" : null)"> | 			<p class="control @(IsDraftMode ? "is-hidden" : null)"> | ||||||
| 				<button class="button is-small is-rounded neoBtnSmall" @onclick="OnFileRenameClick" title="Rename configuration"> | 				<button class="button is-small is-rounded neoBtnSmall" @onclick="OnFileRenameClick" title="Rename configuration"> | ||||||
| @@ -35,13 +33,10 @@ | |||||||
| 				</button> | 				</button> | ||||||
| 			</p> | 			</p> | ||||||
| 		</div> | 		</div> | ||||||
| 		} |  | ||||||
| 		else | 		<div class="field @(IsAnyFileSelected ? "is-hidden" : null)"> | ||||||
| 		{ |  | ||||||
| 			<div class="field"> |  | ||||||
| 			<div class="control is-expanded borderRBig neomorphXSmall has-text-centered"><span>···</span></div> | 			<div class="control is-expanded borderRBig neomorphXSmall has-text-centered"><span>···</span></div> | ||||||
| 		</div> | 		</div> | ||||||
| 		} |  | ||||||
| 	</div> | 	</div> | ||||||
|  |  | ||||||
| 	<div class="files neomorphInsetXSmall borderR"> | 	<div class="files neomorphInsetXSmall borderR"> | ||||||
| @@ -81,9 +76,7 @@ | |||||||
| 	</div> | 	</div> | ||||||
|  |  | ||||||
| 	<div class="editorActions"> | 	<div class="editorActions"> | ||||||
| 		@if (IsAnyFileSelected) | 		<div class="level @(IsAnyFileSelected ? null : "is-hidden")"> | ||||||
| 		{ |  | ||||||
| 			<div class="level"> |  | ||||||
| 			<div class="level-left"> | 			<div class="level-left"> | ||||||
| 				<div class="level-item"> | 				<div class="level-item"> | ||||||
| 					<div class="button is-rounded is-small noStyle isNoFinger"> | 					<div class="button is-rounded is-small noStyle isNoFinger"> | ||||||
| @@ -99,17 +92,14 @@ | |||||||
| 					<div class="buttons"> | 					<div class="buttons"> | ||||||
| 						<button @onclick="OnUndoChanges" class="button is-rounded neoBtnSmall is-small has-icon-left noBottomMargin"><span class="icon is-left has-text-dark"><i class="mdi mdi-undo-variant"></i></span> <span>Undo changes</span></button> | 						<button @onclick="OnUndoChanges" class="button is-rounded neoBtnSmall is-small has-icon-left noBottomMargin"><span class="icon is-left has-text-dark"><i class="mdi mdi-undo-variant"></i></span> <span>Undo changes</span></button> | ||||||
| 						<button @onclick="OnTest" class="button is-rounded neoBtnSmall is-small has-icon-left noBottomMargin @(HasTesting && !IsDraftMode ? null : "is-hidden")"><span class="icon is-left has-text-danger"><i class="mdi mdi-alert"></i></span> <span>Test</span></button> | 						<button @onclick="OnTest" class="button is-rounded neoBtnSmall is-small has-icon-left noBottomMargin @(HasTesting && !IsDraftMode ? null : "is-hidden")"><span class="icon is-left has-text-danger"><i class="mdi mdi-alert"></i></span> <span>Test</span></button> | ||||||
| 							<button @onclick="OnSaveDraft" class="button is-rounded neoBtnSmall is-small has-icon-left noBottomMargin @(IsDraftMode ? null : "is-hidden")"><span class="icon is-left has-text-light"><i class="mdi mdi-content-save"></i></span> <span>@(string.IsNullOrEmpty(SelectedFile.DraftBody) ? "Create" : "Save") draft</span></button> | 						<button @onclick="OnSaveDraft" class="button is-rounded neoBtnSmall is-small has-icon-left noBottomMargin @(IsDraftMode ? null : "is-hidden")"><span class="icon is-left has-text-light"><i class="mdi mdi-content-save"></i></span> <span>@(string.IsNullOrEmpty(SelectedFile?.DraftBody) ? "Create" : "Save") draft</span></button> | ||||||
| 						<button @onclick="OnSave" class="button is-rounded neoBtnSmall is-small has-icon-left noBottomMargin @(IsDraftMode ? "is-hidden"  : null)"><span class="icon is-left has-text-success"><i class="mdi mdi-content-save-all"></i></span> <span>Save</span></button> | 						<button @onclick="OnSave" class="button is-rounded neoBtnSmall is-small has-icon-left noBottomMargin @(IsDraftMode ? "is-hidden"  : null)"><span class="icon is-left has-text-success"><i class="mdi mdi-content-save-all"></i></span> <span>Save</span></button> | ||||||
| 					</div> | 					</div> | ||||||
| 				</div> | 				</div> | ||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
| 		} |  | ||||||
| 		else | 		<span class="@(IsAnyFileSelected ? "is-hidden" : null)"></span> | ||||||
| 		{ |  | ||||||
| 			<span></span> |  | ||||||
| 		} |  | ||||||
| 	</div> | 	</div> | ||||||
|  |  | ||||||
| </div> | </div> | ||||||
|   | |||||||
| @@ -101,6 +101,7 @@ namespace Seenginx.Pages | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			SelectedFile.Name = result.Data.ToString(); | 			SelectedFile.Name = result.Data.ToString(); | ||||||
|  | 			SelectedFile.FullPath = renameResult.Data.FullPath; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		public async Task SaveFileAsync() | 		public async Task SaveFileAsync() | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| @page "/systemd" | @inherits SystemdBase | ||||||
|  | @page "/systemd" | ||||||
| <h3>SystemD</h3> | <FilesWithEditor CFile="ConfigFile" Files="ConfigFiles" SelectedFile="SelectedFile" SelectedFileChanged="SelectedFileChanged" | ||||||
|  | 								 TestConfiguration="() => { }" DeleteFileCallback="DeleteFile" ShowAddFileModal="AddFileModal" | ||||||
| @code { | 								 RenameFileCallback="RenameFileModal" | ||||||
|  | 								 HasTesting="false" SaveFileCallback="SaveFileAsync" SaveDraftFileCallback="SaveDraftFileAsync"> | ||||||
| } | </FilesWithEditor> | ||||||
							
								
								
									
										166
									
								
								Seenginx/Pages/Systemd.razor.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								Seenginx/Pages/Systemd.razor.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,166 @@ | |||||||
|  | using Blazored.Modal; | ||||||
|  | using Blazored.Modal.Services; | ||||||
|  | using Microsoft.AspNetCore.Components; | ||||||
|  | using Seenginx.Models; | ||||||
|  | using Seenginx.Services; | ||||||
|  | using Seenginx.Shared; | ||||||
|  | using Seenginx.Utility; | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
|  | namespace Seenginx.Pages | ||||||
|  | { | ||||||
|  | 	public class SystemdBase : ComponentBase | ||||||
|  | 	{ | ||||||
|  | 		[Inject] public ISystemDService SystemDService { get; set; } | ||||||
|  | 		[CascadingParameter] public IModalService Modal { get; set; } | ||||||
|  |  | ||||||
|  | 		public string InputSearch { get; set; } | ||||||
|  |  | ||||||
|  | 		public List<ConfigFile> ConfigFiles { get; set; } = new List<ConfigFile>(); | ||||||
|  | 		public ConfigFile SelectedFile { get; set; } | ||||||
|  | 		public List<int> FilteredOutFiles { get; set; } = new List<int>(); | ||||||
|  | 		public NotificationSettings GeneralNotificationSettings { get; set; } = null; | ||||||
|  | 		public List<Template> Templates { get; set; } = new List<Template>(); | ||||||
|  |  | ||||||
|  | 		protected override async Task OnParametersSetAsync() | ||||||
|  | 		{ | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				ConfigFiles.AddRange(await SystemDService.GetFilesAsync()); | ||||||
|  | 				Templates.AddRange(await SystemDService.GetTemplates()); | ||||||
|  | 			} | ||||||
|  | 			catch (Exception ex) | ||||||
|  | 			{ | ||||||
|  | 				throw ex; | ||||||
|  | 			} | ||||||
|  | 			await base.OnParametersSetAsync(); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		public void SelectedFileChanged(ConfigFile configFile) | ||||||
|  | 		{ | ||||||
|  | 			SelectedFile = configFile; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		public async Task AddFileModal() | ||||||
|  | 		{ | ||||||
|  | 			var parameters = new ModalParameters(); | ||||||
|  | 			parameters.Add(nameof(Templates), Templates); | ||||||
|  |  | ||||||
|  | 			var resultAwait = Modal.Show<SystemdConfigForm>(string.Empty, parameters); | ||||||
|  | 			var result = await resultAwait.Result; | ||||||
|  | 			if (result.Cancelled) return; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 			var validationResult = await SystemDService.ValidateForAddFileAsync((NewFileForm)result.Data); | ||||||
|  |  | ||||||
|  | 			if (!validationResult.AllOk) | ||||||
|  | 			{ | ||||||
|  | 				var validationPopupParameters = new ModalParameters().Setup(PopupType.Ok, validationResult.ErrorMessage); | ||||||
|  | 				var validationPopup = Modal.Show<GenericPopup>(string.Empty, validationPopupParameters); | ||||||
|  | 				await validationPopup.Result; | ||||||
|  | 				validationPopup.Close(); | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			var addFileResult = await SystemDService.AddFileAsync((NewFileForm)result.Data); | ||||||
|  | 			if (SelectedFile != null) | ||||||
|  | 				SelectedFile.Deselect(); | ||||||
|  | 			ConfigFiles.Add(addFileResult.Data); | ||||||
|  | 			ConfigFiles = ConfigFiles.OrderBy(cf => cf.Name).ToList(); | ||||||
|  | 			SelectedFile = ConfigFiles.Find(cf => cf.Name == addFileResult.Data.Name); | ||||||
|  | 			SelectedFile.Select(); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		public async Task RenameFileModal() | ||||||
|  | 		{ | ||||||
|  | 			var parameters = new ModalParameters(); | ||||||
|  | 			parameters.Add(nameof(RenameForm.Name), SelectedFile.Name); | ||||||
|  |  | ||||||
|  | 			var resultAwait = Modal.Show<RenameForm>(string.Empty, parameters); | ||||||
|  | 			var result = await resultAwait.Result; | ||||||
|  | 			if (result.Cancelled) return; | ||||||
|  |  | ||||||
|  | 			var validationResult = await SystemDService.ValidateForRenameFileAsync(ConfigFiles, SelectedFile, result.Data.ToString()); | ||||||
|  | 			if (!validationResult.AllOk) | ||||||
|  | 			{ | ||||||
|  | 				var popupAwait = Modal.Show<GenericPopup>(string.Empty, new ModalParameters().Setup(PopupType.Ok, validationResult.ErrorMessage)); | ||||||
|  | 				await popupAwait.Result; | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			var renameResult = await SystemDService.RenameFileAsync(SelectedFile, $"{result.Data}.service"); | ||||||
|  | 			if (!renameResult.AllOk) | ||||||
|  | 			{ | ||||||
|  | 				var popupAwait = Modal.Show<GenericPopup>(string.Empty, new ModalParameters().Setup(PopupType.Ok, renameResult.ErrorMessage)); | ||||||
|  | 				await popupAwait.Result; | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			SelectedFile.Name = result.Data.ToString(); | ||||||
|  | 			SelectedFile.FullPath = renameResult.Data.FullPath; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		public async Task SaveFileAsync() | ||||||
|  | 		{ | ||||||
|  | 			var validationResult = await SystemDService.ValidateForSaveFileAsync(SelectedFile); | ||||||
|  |  | ||||||
|  | 			if (!validationResult.AllOk) | ||||||
|  | 			{ | ||||||
|  | 				await Modal.Show<GenericPopup>(string.Empty, new ModalParameters().Setup(PopupType.Ok, validationResult.ErrorMessage)).Result; | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			var saveResult = await SystemDService.SaveFileAsync(SelectedFile); | ||||||
|  |  | ||||||
|  | 			if (!saveResult.AllOk) | ||||||
|  | 			{ | ||||||
|  | 				await Modal.Show<GenericPopup>(string.Empty, new ModalParameters().Setup(PopupType.Ok, saveResult.ErrorMessage)).Result; | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		public async Task SaveDraftFileAsync() | ||||||
|  | 		{ | ||||||
|  | 			//var validationResult = await NginxService.ValidateForSaveDraftFileAsync(SelectedFile); | ||||||
|  |  | ||||||
|  | 			//if (!validationResult.AllOk) | ||||||
|  | 			//{ | ||||||
|  | 			//	await Modal.Show<GenericPopup>(string.Empty, new ModalParameters().Setup(PopupType.Ok, validationResult.ErrorMessage)).Result; | ||||||
|  | 			//	return; | ||||||
|  | 			//} | ||||||
|  |  | ||||||
|  | 			var saveDraftResult = await SystemDService.SaveDraftFileAsync(SelectedFile); | ||||||
|  |  | ||||||
|  | 			if (!saveDraftResult.AllOk) | ||||||
|  | 			{ | ||||||
|  | 				await Modal.Show<GenericPopup>(string.Empty, new ModalParameters().Setup(PopupType.Ok, saveDraftResult.ErrorMessage)).Result; | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		public async Task DeleteFile() | ||||||
|  | 		{ | ||||||
|  | 			var parameters = new ModalParameters().Setup(PopupType.YesNo, $"Are you sure you want to delete '{SelectedFile.Name}'?"); | ||||||
|  |  | ||||||
|  | 			var resultAwait = Modal.Show<GenericPopup>(string.Empty, parameters); | ||||||
|  | 			var result = await resultAwait.Result; | ||||||
|  | 			if ((PopupAnswer)result.Data == PopupAnswer.No) return; | ||||||
|  |  | ||||||
|  | 			var deleteFileResult = await SystemDService.DeleteFileAsync(SelectedFile); | ||||||
|  |  | ||||||
|  | 			if (!deleteFileResult.AllOk) | ||||||
|  | 			{ | ||||||
|  | 				var errorParameters = new ModalParameters().Setup(PopupType.Ok, $"Something went wrong, here's the error message: '{deleteFileResult.ErrorMessage}'?"); | ||||||
|  | 				var errorReportModalAwait = Modal.Show<GenericPopup>(string.Empty, errorParameters); | ||||||
|  | 				await errorReportModalAwait.Result; | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			ConfigFiles.Remove(SelectedFile); | ||||||
|  | 			SelectedFile = null; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -6,6 +6,7 @@ | |||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Content Remove="compilerconfig.json" /> |     <Content Remove="compilerconfig.json" /> | ||||||
|  |     <Content Remove="Settings\settings.json" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
| @@ -15,6 +16,7 @@ | |||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <None Include="compilerconfig.json" /> |     <None Include="compilerconfig.json" /> | ||||||
|  |     <None Include="Settings\settings.json" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ namespace Seenginx.Services | |||||||
| 		Task<Result<ConfigFile>> SaveDraftFileAsync(ConfigFile configFile); | 		Task<Result<ConfigFile>> SaveDraftFileAsync(ConfigFile configFile); | ||||||
|  |  | ||||||
| 		Task<Result> ValidateForRenameFileAsync(List<ConfigFile> configFiles, ConfigFile configFile, string newName); | 		Task<Result> ValidateForRenameFileAsync(List<ConfigFile> configFiles, ConfigFile configFile, string newName); | ||||||
| 		Task<Result> RenameFileAsync(ConfigFile configFile, string newName); | 		Task<Result<ConfigFile>> RenameFileAsync(ConfigFile configFile, string newName); | ||||||
|  |  | ||||||
| 		Task<Result> ValidateForDeleteFileAsync(ConfigFile configFile); | 		Task<Result> ValidateForDeleteFileAsync(ConfigFile configFile); | ||||||
| 		Task<Result> DeleteFileAsync(ConfigFile configFile); | 		Task<Result> DeleteFileAsync(ConfigFile configFile); | ||||||
|   | |||||||
| @@ -6,7 +6,23 @@ namespace Seenginx.Services | |||||||
| { | { | ||||||
| 	public interface ISystemDService | 	public interface ISystemDService | ||||||
| 	{ | 	{ | ||||||
| 		Task<IEnumerable<ConfigFile>> GetFiles(SystemDFilter filter = null); | 		Task<IEnumerable<ConfigFile>> GetFilesAsync(); | ||||||
| 		Task<IEnumerable<string>> GetLogMessages(SystemDLogsFilter filter = null); | 		Task<IEnumerable<Template>> GetTemplates(); | ||||||
|  |  | ||||||
|  | 		Task<Result> ValidateForAddFileAsync(NewFileForm newFileForm); | ||||||
|  | 		Task<Result<ConfigFile>> AddFileAsync(NewFileForm newFileForm); | ||||||
|  |  | ||||||
|  | 		Task<Result> ValidateForSaveFileAsync(ConfigFile configFile); | ||||||
|  | 		Task<Result<ConfigFile>> SaveFileAsync(ConfigFile configFile); | ||||||
|  |  | ||||||
|  | 		Task<Result> ValidateForSaveDraftFileAsync(ConfigFile configFile); | ||||||
|  | 		Task<Result<ConfigFile>> SaveDraftFileAsync(ConfigFile configFile); | ||||||
|  |  | ||||||
|  | 		Task<Result> ValidateForRenameFileAsync(List<ConfigFile> configFiles, ConfigFile configFile, string newName); | ||||||
|  | 		Task<Result<ConfigFile>> RenameFileAsync(ConfigFile configFile, string newName); | ||||||
|  |  | ||||||
|  | 		Task<Result> ValidateForDeleteFileAsync(ConfigFile configFile); | ||||||
|  | 		Task<Result> DeleteFileAsync(ConfigFile configFile); | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -1,13 +0,0 @@ | |||||||
| using System; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.Linq; |  | ||||||
| using System.Threading.Tasks; |  | ||||||
|  |  | ||||||
| namespace Seenginx.Services.Models |  | ||||||
| { |  | ||||||
| 	public class ConfigPaths |  | ||||||
| 	{ |  | ||||||
| 		public string NginxPath { get; set; } |  | ||||||
| 		public string SystemDPath { get; set; } |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
							
								
								
									
										23
									
								
								Seenginx/Services/Models/SeenginxSettings.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								Seenginx/Services/Models/SeenginxSettings.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
|  | namespace Seenginx.Services.Models | ||||||
|  | { | ||||||
|  | 	public class SeenginxSettings | ||||||
|  | 	{ | ||||||
|  | 		public NginxSettings nginx { get; set; } | ||||||
|  | 		public SystemdSettings systemd { get; set; } | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public class NginxSettings | ||||||
|  | 	{ | ||||||
|  | 		public string rootPath { get; set; } | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public class SystemdSettings | ||||||
|  | 	{ | ||||||
|  | 		public string rootPath { get; set; } | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -14,27 +14,26 @@ namespace Seenginx.Services | |||||||
| { | { | ||||||
| 	public class NginxService : INginxService | 	public class NginxService : INginxService | ||||||
| 	{ | 	{ | ||||||
| 		private readonly ConfigPaths ConfigPaths; | 		private readonly SeenginxSettings Settings; | ||||||
|  |  | ||||||
| 		private readonly CommandService CommandService; | 		private readonly CommandService CommandService; | ||||||
|  |  | ||||||
| 		public NginxService(ConfigPaths configPaths, CommandService commandService) | 		public NginxService(SeenginxSettings configPaths, CommandService commandService) | ||||||
| 		{ | 		{ | ||||||
| 			ConfigPaths = configPaths; | 			Settings = configPaths; | ||||||
| 			CommandService = commandService; | 			CommandService = commandService; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		public async Task<IEnumerable<ConfigFile>> GetFilesAsync() | 		public async Task<IEnumerable<ConfigFile>> GetFilesAsync() | ||||||
| 		{ | 		{ | ||||||
| 			await Task.Run(() => { }); | 			await Task.Run(() => { }); | ||||||
| 			var rootConfigs = Directory.GetFiles(ConfigPaths.NginxPath, "*.conf"); | 			var rootConfigs = Directory.GetFiles(Settings.nginx.rootPath, "*.conf"); | ||||||
| 			var rootDraftConfigs = Directory.GetFiles(ConfigPaths.NginxPath, "*.conf.draft"); | 			var rootDraftConfigs = Directory.GetFiles(Settings.nginx.rootPath, "*.conf.draft"); | ||||||
|  |  | ||||||
| 			var confdConfigs = Directory.GetFiles(Path.Combine(ConfigPaths.NginxPath, "conf.d"), "*.conf"); | 			var confdConfigs = Directory.GetFiles(Path.Combine(Settings.nginx.rootPath, "conf.d"), "*.conf"); | ||||||
| 			var confDraftConfigs = Directory.GetFiles(Path.Combine(ConfigPaths.NginxPath, "conf.d"), "*.conf.draft"); | 			var confDraftConfigs = Directory.GetFiles(Path.Combine(Settings.nginx.rootPath, "conf.d"), "*.conf.draft"); | ||||||
|  |  | ||||||
| 			var sitesAvailableConfigs = Directory.GetFiles(Path.Combine(ConfigPaths.NginxPath, "sites-available"), "*.conf"); | 			var sitesAvailableConfigs = Directory.GetFiles(Path.Combine(Settings.nginx.rootPath, "sites-available"), "*.conf"); | ||||||
| 			var sitesAvailableDraftConfigs = Directory.GetFiles(Path.Combine(ConfigPaths.NginxPath, "sites-available"), "*.conf.draft"); | 			var sitesAvailableDraftConfigs = Directory.GetFiles(Path.Combine(Settings.nginx.rootPath, "sites-available"), "*.conf.draft"); | ||||||
|  |  | ||||||
| 			var rootConfigFiles = rootConfigs.Select(fp => | 			var rootConfigFiles = rootConfigs.Select(fp => | ||||||
| 			{ | 			{ | ||||||
| @@ -44,7 +43,7 @@ namespace Seenginx.Services | |||||||
| 				configFile.Folder = string.Empty; | 				configFile.Folder = string.Empty; | ||||||
| 				configFile.LastUpdated = File.GetLastWriteTime(fp); | 				configFile.LastUpdated = File.GetLastWriteTime(fp); | ||||||
| 				configFile.Name = name; | 				configFile.Name = name; | ||||||
| 				configFile.FullPath = Path.Combine(ConfigPaths.NginxPath, $"{configFile.Name}.conf"); | 				configFile.FullPath = Path.Combine(Settings.nginx.rootPath, $"{configFile.Name}.conf"); | ||||||
| 				configFile.Body = File.ReadAllText(fp); | 				configFile.Body = File.ReadAllText(fp); | ||||||
| 				if (rootDraftConfigs.Any(cfp => cfp.Contains(name))) | 				if (rootDraftConfigs.Any(cfp => cfp.Contains(name))) | ||||||
| 					configFile.DraftBody = File.ReadAllText(rootDraftConfigs.First(cfp => cfp.Contains(name))); | 					configFile.DraftBody = File.ReadAllText(rootDraftConfigs.First(cfp => cfp.Contains(name))); | ||||||
| @@ -59,7 +58,7 @@ namespace Seenginx.Services | |||||||
| 				configFile.Folder = "conf.d"; | 				configFile.Folder = "conf.d"; | ||||||
| 				configFile.LastUpdated = File.GetLastWriteTime(fp); | 				configFile.LastUpdated = File.GetLastWriteTime(fp); | ||||||
| 				configFile.Name = fileName; | 				configFile.Name = fileName; | ||||||
| 				configFile.FullPath = Path.Combine(ConfigPaths.NginxPath, configFile.Folder, $"{configFile.Name}.conf"); | 				configFile.FullPath = Path.Combine(Settings.nginx.rootPath, configFile.Folder, $"{configFile.Name}.conf"); | ||||||
| 				configFile.Body = File.ReadAllText(fp); | 				configFile.Body = File.ReadAllText(fp); | ||||||
| 				if (confDraftConfigs.Any(cfp => cfp.Contains(fileName))) | 				if (confDraftConfigs.Any(cfp => cfp.Contains(fileName))) | ||||||
| 					configFile.DraftBody = File.ReadAllText(confDraftConfigs.First(cfp => cfp.Contains(fileName))); | 					configFile.DraftBody = File.ReadAllText(confDraftConfigs.First(cfp => cfp.Contains(fileName))); | ||||||
| @@ -74,37 +73,18 @@ namespace Seenginx.Services | |||||||
| 				configFile.Folder = "sites-available"; | 				configFile.Folder = "sites-available"; | ||||||
| 				configFile.LastUpdated = File.GetLastWriteTime(fp); | 				configFile.LastUpdated = File.GetLastWriteTime(fp); | ||||||
| 				configFile.Name = fileName; | 				configFile.Name = fileName; | ||||||
| 				configFile.FullPath = Path.Combine(ConfigPaths.NginxPath, configFile.Folder, $"{configFile.Name}.conf"); | 				configFile.FullPath = Path.Combine(Settings.nginx.rootPath, configFile.Folder, $"{configFile.Name}.conf"); | ||||||
| 				configFile.Body = File.ReadAllText(fp); | 				configFile.Body = File.ReadAllText(fp); | ||||||
| 				if (sitesAvailableDraftConfigs.Any(cfp => cfp.Contains(fileName))) | 				if (sitesAvailableDraftConfigs.Any(cfp => cfp.Contains(fileName))) | ||||||
| 					configFile.DraftBody = File.ReadAllText(sitesAvailableDraftConfigs.First(cfp => cfp.Contains(fileName))); | 					configFile.DraftBody = File.ReadAllText(sitesAvailableDraftConfigs.First(cfp => cfp.Contains(fileName))); | ||||||
|  |  | ||||||
| 				return configFile; | 				return configFile; | ||||||
| 			}); | 			}); | ||||||
| 			//var sitesEnabledConfigFiles = sitesEnabledConfigs.Select(fp => |  | ||||||
| 			//{ |  | ||||||
| 			//	var fileName = Path.GetFileName(fp); |  | ||||||
| 			//	var configFile = new ConfigFile(); |  | ||||||
| 			//	configFile.CanBeDeleted = true; |  | ||||||
| 			//	configFile.Folder = "/sites-enabled"; |  | ||||||
| 			//	configFile.LastUpdated = File.GetLastWriteTime(fp); |  | ||||||
| 			//	configFile.Name = fileName; |  | ||||||
| 			//	configFile.FullPath = Path.Combine(ConfigPaths.NginxPath, configFile.Folder.Replace("/", string.Empty), configFile.Name); |  | ||||||
| 			//	configFile.Body = File.ReadAllText(fp); |  | ||||||
| 			//	configFile.DraftName = fileName; |  | ||||||
| 			//	configFile.DraftBody = configFile.Body; |  | ||||||
| 			//	if (confDraftConfigs.Any(cfp => cfp.Contains(fileName))) |  | ||||||
| 			//	{ |  | ||||||
| 			//		configFile.DraftName = Path.GetFileName(confDraftConfigs.First(cfp => cfp.Contains(fileName))); |  | ||||||
| 			//		configFile.DraftBody = File.ReadAllText(confDraftConfigs.First(cfp => cfp.Contains(fileName))); |  | ||||||
| 			//	} |  | ||||||
| 			//	return configFile; |  | ||||||
| 			//}); |  | ||||||
| 			var finalList = new List<ConfigFile>(); | 			var finalList = new List<ConfigFile>(); | ||||||
| 			finalList.AddRange(rootConfigFiles); | 			finalList.AddRange(rootConfigFiles); | ||||||
| 			finalList.AddRange(confdConfigFiles); | 			finalList.AddRange(confdConfigFiles); | ||||||
| 			finalList.AddRange(sitesAvailableConfigFiles); | 			finalList.AddRange(sitesAvailableConfigFiles); | ||||||
| 			//finalList.AddRange(sitesEnabledConfigFiles); |  | ||||||
|  |  | ||||||
| 			finalList = finalList.OrderBy(cf => cf.Name).ToList(); | 			finalList = finalList.OrderBy(cf => cf.Name).ToList(); | ||||||
|  |  | ||||||
| @@ -142,7 +122,7 @@ namespace Seenginx.Services | |||||||
| 			var validationResult = new Result(); | 			var validationResult = new Result(); | ||||||
| 			try | 			try | ||||||
| 			{ | 			{ | ||||||
| 				var filePath = Path.Combine(ConfigPaths.NginxPath, "conf.d", $"{newFileForm.Name}.conf"); | 				var filePath = Path.Combine(Settings.nginx.rootPath, "conf.d", $"{newFileForm.Name}.conf"); | ||||||
|  |  | ||||||
| 				if (File.Exists(filePath)) | 				if (File.Exists(filePath)) | ||||||
| 					return validationResult.Invalidate($"There's already a file with the '{newFileForm.Name}.conf' name."); | 					return validationResult.Invalidate($"There's already a file with the '{newFileForm.Name}.conf' name."); | ||||||
| @@ -161,9 +141,9 @@ namespace Seenginx.Services | |||||||
| 			try | 			try | ||||||
| 			{ | 			{ | ||||||
| 				var newFile = new ConfigFile(); | 				var newFile = new ConfigFile(); | ||||||
| 				newFile.Name = $"{newFileForm.Name}.conf"; | 				newFile.Name = newFileForm.Name; | ||||||
| 				newFile.Folder = "conf.d"; | 				newFile.Folder = "conf.d"; | ||||||
| 				newFile.FullPath = Path.Combine(ConfigPaths.NginxPath, newFile.Folder, newFile.Name); | 				newFile.FullPath = Path.Combine(Settings.nginx.rootPath, newFile.Folder, $"{newFileForm.Name}.conf"); | ||||||
| 				newFile.Body = newFileForm.SelectedTemplate == 0.ToString() ? string.Empty : (await GetTemplates()).SingleOrDefault(t => t.Name == newFileForm.SelectedTemplate)?.Code; | 				newFile.Body = newFileForm.SelectedTemplate == 0.ToString() ? string.Empty : (await GetTemplates()).SingleOrDefault(t => t.Name == newFileForm.SelectedTemplate)?.Code; | ||||||
| 				newFile.LastUpdated = DateTime.UtcNow; | 				newFile.LastUpdated = DateTime.UtcNow; | ||||||
|  |  | ||||||
| @@ -205,6 +185,8 @@ namespace Seenginx.Services | |||||||
| 					return result.Invalidate($"File '{configFile.FullPath}' not found."); | 					return result.Invalidate($"File '{configFile.FullPath}' not found."); | ||||||
|  |  | ||||||
| 				File.Delete(configFile.FullPath); | 				File.Delete(configFile.FullPath); | ||||||
|  | 				if (configFile.DraftBody != null) | ||||||
|  | 					File.Delete($"{configFile.FullPath}.draft"); | ||||||
|  |  | ||||||
| 				return result; | 				return result; | ||||||
| 			} | 			} | ||||||
| @@ -236,7 +218,7 @@ namespace Seenginx.Services | |||||||
| 			var saveResult = new Result<ConfigFile>(); | 			var saveResult = new Result<ConfigFile>(); | ||||||
| 			try | 			try | ||||||
| 			{ | 			{ | ||||||
| 				await File.WriteAllTextAsync(Path.Combine(ConfigPaths.NginxPath, configFile.Folder, $"{configFile.Name}.conf"), configFile.Body, Encoding.UTF8); | 				await File.WriteAllTextAsync(Path.Combine(Settings.nginx.rootPath, configFile.Folder, $"{configFile.Name}.conf"), configFile.Body, Encoding.UTF8); | ||||||
|  |  | ||||||
| 				return saveResult; | 				return saveResult; | ||||||
| 			} | 			} | ||||||
| @@ -270,7 +252,7 @@ namespace Seenginx.Services | |||||||
| 			var saveDraftResult = new Result<ConfigFile>(); | 			var saveDraftResult = new Result<ConfigFile>(); | ||||||
| 			try | 			try | ||||||
| 			{ | 			{ | ||||||
| 				await File.WriteAllTextAsync(Path.Combine(ConfigPaths.NginxPath, configFile.Folder, $"{configFile.Name}.conf.draft"), configFile.DraftBody, Encoding.UTF8); | 				await File.WriteAllTextAsync(Path.Combine(Settings.nginx.rootPath, configFile.Folder, $"{configFile.Name}.conf.draft"), configFile.DraftBody, Encoding.UTF8); | ||||||
|  |  | ||||||
| 				return saveDraftResult; | 				return saveDraftResult; | ||||||
| 			} | 			} | ||||||
| @@ -288,7 +270,7 @@ namespace Seenginx.Services | |||||||
| 			{ | 			{ | ||||||
|  |  | ||||||
|  |  | ||||||
| 				if(configFiles.Count(cf => cf.Name == newName) > 0) | 				if (configFiles.Count(cf => cf.Name == newName) > 0) | ||||||
| 					return renameResult.Invalidate($"File '{selectedConfigFile.FullPath}' already exists."); | 					return renameResult.Invalidate($"File '{selectedConfigFile.FullPath}' already exists."); | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -297,7 +279,7 @@ namespace Seenginx.Services | |||||||
| 				if (!File.Exists(selectedConfigFile.FullPath)) | 				if (!File.Exists(selectedConfigFile.FullPath)) | ||||||
| 					return renameResult.Invalidate($"Original file '{selectedConfigFile.FullPath}' not found."); | 					return renameResult.Invalidate($"Original file '{selectedConfigFile.FullPath}' not found."); | ||||||
|  |  | ||||||
| 				var newPathName = Path.Combine(ConfigPaths.NginxPath, selectedConfigFile.Folder, $"{newName}.conf"); | 				var newPathName = Path.Combine(Settings.nginx.rootPath, selectedConfigFile.Folder, $"{newName}.conf"); | ||||||
| 				if (File.Exists(newPathName)) | 				if (File.Exists(newPathName)) | ||||||
| 					return renameResult.Invalidate($"The file '{newPathName}' already exists."); | 					return renameResult.Invalidate($"The file '{newPathName}' already exists."); | ||||||
|  |  | ||||||
| @@ -309,15 +291,20 @@ namespace Seenginx.Services | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		public async Task<Result> RenameFileAsync(ConfigFile configFile, string newName) | 		public async Task<Result<ConfigFile>> RenameFileAsync(ConfigFile configFile, string newName) | ||||||
| 		{ | 		{ | ||||||
| 			var renameResult = new Result(); | 			var renameResult = new Result<ConfigFile>(); | ||||||
| 			try | 			try | ||||||
| 			{ | 			{ | ||||||
| 				var originalPathName = Path.Combine(ConfigPaths.NginxPath, configFile.Folder, $"{configFile.Name}.conf"); | 				var originalPathName = Path.Combine(Settings.nginx.rootPath, configFile.Folder, $"{configFile.Name}.conf"); | ||||||
| 				var newPathName = Path.Combine(ConfigPaths.NginxPath, configFile.Folder, newName); | 				var newPathName = Path.Combine(Settings.nginx.rootPath, configFile.Folder, newName); | ||||||
|  |  | ||||||
| 				File.Move(originalPathName, newPathName, overwrite: false); | 				File.Move(originalPathName, newPathName, overwrite: false); | ||||||
|  | 				if (configFile.DraftBody != null) | ||||||
|  | 					File.Move($"{originalPathName}.draft", $"{newPathName}.draft", overwrite: false); | ||||||
|  |  | ||||||
|  | 				configFile.FullPath = newPathName; | ||||||
|  | 				renameResult.SetData(configFile); | ||||||
|  |  | ||||||
| 				return renameResult; | 				return renameResult; | ||||||
| 			} | 			} | ||||||
| @@ -334,7 +321,7 @@ namespace Seenginx.Services | |||||||
| 			var command1 = string.Empty; | 			var command1 = string.Empty; | ||||||
| 			var command2 = string.Empty; | 			var command2 = string.Empty; | ||||||
| 			var runResult = new Result<string>(); | 			var runResult = new Result<string>(); | ||||||
| 			var originalPathName = Path.Combine(ConfigPaths.NginxPath, configFile.Folder, $"{configFile.Name}.conf"); | 			var originalPathName = Path.Combine(Settings.nginx.rootPath, configFile.Folder, $"{configFile.Name}.conf"); | ||||||
| 			switch (Environment.OSVersion.Platform) | 			switch (Environment.OSVersion.Platform) | ||||||
| 			{ | 			{ | ||||||
| 				case PlatformID.Win32S: | 				case PlatformID.Win32S: | ||||||
| @@ -357,17 +344,5 @@ namespace Seenginx.Services | |||||||
| 			return runResult; | 			return runResult; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		//public async Task<Result> DeleteFileAsync(ConfigFile configFile) |  | ||||||
| 		//{ |  | ||||||
| 		//	var result = new Result(true); |  | ||||||
| 		//	try |  | ||||||
| 		//	{ |  | ||||||
| 		//		return result; |  | ||||||
| 		//	} |  | ||||||
| 		//	catch (Exception ex) |  | ||||||
| 		//	{ |  | ||||||
| 		//		return result.Invalidate(ex.Message, ex); |  | ||||||
| 		//	} |  | ||||||
| 		//} |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,23 +1,279 @@ | |||||||
| using Seenginx.Models; | using Seenginx.Models; | ||||||
|  | using Seenginx.Services; | ||||||
|  | using Seenginx.Services.Models; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
|  | using System.IO; | ||||||
| using System.Linq; | using System.Linq; | ||||||
|  | using System.Text; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
|  |  | ||||||
| namespace Seenginx.Services | namespace Seenginx.Services | ||||||
| { | { | ||||||
| 	public class SystemDService : ISystemDService | 	public class SystemDService : ISystemDService | ||||||
| 	{ | 	{ | ||||||
| 		public async Task<IEnumerable<ConfigFile>> GetFiles(SystemDFilter filter = null) |  | ||||||
|  | 		private readonly SeenginxSettings Settings; | ||||||
|  |  | ||||||
|  | 		private readonly CommandService CommandService; | ||||||
|  |  | ||||||
|  | 		public SystemDService(SeenginxSettings configPaths, CommandService commandService) | ||||||
| 		{ | 		{ | ||||||
| 			await Task.Run(() => { }); | 			Settings = configPaths; | ||||||
| 			return new List<ConfigFile>(); | 			CommandService = commandService; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		public async Task<IEnumerable<string>> GetLogMessages(SystemDLogsFilter filter = null) | 		public async Task<IEnumerable<ConfigFile>> GetFilesAsync() | ||||||
| 		{ | 		{ | ||||||
| 			await Task.Run(() => { }); | 			await Task.Run(() => { }); | ||||||
| 			return new List<string>(); | 			var rootConfigs = Directory.GetFiles(Settings.systemd.rootPath, "*.service"); | ||||||
|  | 			var rootDraftConfigs = Directory.GetFiles(Settings.systemd.rootPath, "*.service.draft"); | ||||||
|  |  | ||||||
|  | 			var rootConfigFiles = rootConfigs.Select(fp => | ||||||
|  | 			{ | ||||||
|  | 				var name = Path.GetFileNameWithoutExtension(fp); | ||||||
|  | 				var configFile = new ConfigFile(); | ||||||
|  | 				configFile.CanBeDeleted = true; | ||||||
|  | 				configFile.Folder = string.Empty; | ||||||
|  | 				configFile.LastUpdated = File.GetLastWriteTime(fp); | ||||||
|  | 				configFile.Name = name; | ||||||
|  | 				configFile.FullPath = Path.Combine(Settings.systemd.rootPath, $"{configFile.Name}.service"); | ||||||
|  | 				configFile.Body = File.ReadAllText(fp); | ||||||
|  | 				if (rootDraftConfigs.Any(cfp => cfp.Contains(name))) | ||||||
|  | 					configFile.DraftBody = File.ReadAllText(rootDraftConfigs.First(cfp => cfp.Contains(name))); | ||||||
|  |  | ||||||
|  | 				return configFile; | ||||||
|  | 			}); | ||||||
|  | 			 | ||||||
|  | 			var finalList = new List<ConfigFile>(); | ||||||
|  | 			finalList.AddRange(rootConfigFiles); | ||||||
|  |  | ||||||
|  | 			finalList = finalList.OrderBy(cf => cf.Name).ToList(); | ||||||
|  |  | ||||||
|  | 			return finalList; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		public async Task<IEnumerable<Template>> GetTemplates() | ||||||
|  | 		{ | ||||||
|  | 			var templates = new List<Template>(); | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				var systemdTemplateDirectory = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "templates", "systemd"); | ||||||
|  | 				var systemdTemplateFiles = Directory.GetFiles(systemdTemplateDirectory, "*.template"); | ||||||
|  |  | ||||||
|  | 				foreach (var templateFilePath in systemdTemplateFiles) | ||||||
|  | 				{ | ||||||
|  | 					var template = new Template(); | ||||||
|  | 					var templateFileLines = await File.ReadAllLinesAsync(templateFilePath); | ||||||
|  | 					template.Name = templateFileLines.FirstOrDefault(); | ||||||
|  | 					template.Code = string.Join(Environment.NewLine, templateFileLines.Skip(2)); | ||||||
|  | 					templates.Add(template); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				return templates; | ||||||
|  | 			} | ||||||
|  | 			catch (Exception ex) | ||||||
|  | 			{ | ||||||
|  | 				throw ex; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 		public async Task<Result> ValidateForAddFileAsync(NewFileForm newFileForm) | ||||||
|  | 		{ | ||||||
|  | 			var validationResult = new Result(); | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				var filePath = Path.Combine(Settings.systemd.rootPath, $"{newFileForm.Name}.service"); | ||||||
|  |  | ||||||
|  | 				if (File.Exists(filePath)) | ||||||
|  | 					return validationResult.Invalidate($"There's already a file with the '{newFileForm.Name}.service' name."); | ||||||
|  |  | ||||||
|  | 				return validationResult; | ||||||
|  | 			} | ||||||
|  | 			catch (Exception ex) | ||||||
|  | 			{ | ||||||
|  | 				return validationResult.Invalidate($"Exception at {nameof(ValidateForAddFileAsync)}()", ex); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		public async Task<Result<ConfigFile>> AddFileAsync(NewFileForm newFileForm) | ||||||
|  | 		{ | ||||||
|  | 			var addResult = new Result<ConfigFile>(); | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				var newFile = new ConfigFile(); | ||||||
|  | 				newFile.Name = newFileForm.Name; | ||||||
|  | 				newFile.Folder = string.Empty; | ||||||
|  | 				newFile.FullPath = Path.Combine(Settings.systemd.rootPath, newFile.Folder, $"{newFileForm.Name}.service"); | ||||||
|  | 				newFile.Body = newFileForm.SelectedTemplate == 0.ToString() ? string.Empty : (await GetTemplates()).SingleOrDefault(t => t.Name == newFileForm.SelectedTemplate)?.Code; | ||||||
|  | 				newFile.LastUpdated = DateTime.UtcNow; | ||||||
|  |  | ||||||
|  | 				await File.WriteAllTextAsync(newFile.FullPath, newFile.Body, Encoding.UTF8); | ||||||
|  |  | ||||||
|  | 				addResult.SetData(newFile); | ||||||
|  |  | ||||||
|  | 				return addResult; | ||||||
|  | 			} | ||||||
|  | 			catch (Exception ex) | ||||||
|  | 			{ | ||||||
|  | 				return addResult.Invalidate(ex.Message, ex); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 		public async Task<Result> ValidateForDeleteFileAsync(ConfigFile configFile) | ||||||
|  | 		{ | ||||||
|  | 			var validationResult = new Result(); | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				if (File.Exists(configFile.FullPath)) | ||||||
|  | 					return validationResult.Invalidate($"File '{configFile.FullPath}' not found."); | ||||||
|  |  | ||||||
|  | 				return validationResult; | ||||||
|  | 			} | ||||||
|  | 			catch (Exception ex) | ||||||
|  | 			{ | ||||||
|  | 				return validationResult.Invalidate(ex.Message, ex); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		public async Task<Result> DeleteFileAsync(ConfigFile configFile) | ||||||
|  | 		{ | ||||||
|  | 			var result = new Result(); | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				if (!File.Exists(configFile.FullPath)) | ||||||
|  | 					return result.Invalidate($"File '{configFile.FullPath}' not found."); | ||||||
|  |  | ||||||
|  | 				File.Delete(configFile.FullPath); | ||||||
|  |  | ||||||
|  | 				return result; | ||||||
|  | 			} | ||||||
|  | 			catch (Exception ex) | ||||||
|  | 			{ | ||||||
|  | 				return result.Invalidate(ex.Message, ex); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 		public async Task<Result> ValidateForSaveFileAsync(ConfigFile configFile) | ||||||
|  | 		{ | ||||||
|  | 			var validationResult = new Result(); | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				if (File.Exists(configFile.FullPath)) | ||||||
|  | 					return validationResult.Invalidate($"File '{configFile.FullPath}' not found."); | ||||||
|  |  | ||||||
|  | 				return validationResult; | ||||||
|  | 			} | ||||||
|  | 			catch (Exception ex) | ||||||
|  | 			{ | ||||||
|  | 				return validationResult.Invalidate(ex.Message, ex); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		public async Task<Result<ConfigFile>> SaveFileAsync(ConfigFile configFile) | ||||||
|  | 		{ | ||||||
|  | 			var saveResult = new Result<ConfigFile>(); | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				await File.WriteAllTextAsync(Path.Combine(Settings.systemd.rootPath, $"{configFile.Name}.service"), configFile.Body, Encoding.UTF8); | ||||||
|  |  | ||||||
|  | 				return saveResult; | ||||||
|  | 			} | ||||||
|  | 			catch (Exception ex) | ||||||
|  | 			{ | ||||||
|  | 				return saveResult.Invalidate(ex.Message, ex); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 		public async Task<Result> ValidateForSaveDraftFileAsync(ConfigFile configFile) | ||||||
|  | 		{ | ||||||
|  | 			var validationResult = new Result(); | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				var draftPathName = $"{configFile.FullPath}.draft"; | ||||||
|  |  | ||||||
|  | 				if (!File.Exists(draftPathName)) | ||||||
|  | 					return validationResult.Invalidate($"File '{draftPathName}' not found."); | ||||||
|  |  | ||||||
|  | 				return validationResult; | ||||||
|  | 			} | ||||||
|  | 			catch (Exception ex) | ||||||
|  | 			{ | ||||||
|  | 				return validationResult.Invalidate(ex.Message, ex); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		public async Task<Result<ConfigFile>> SaveDraftFileAsync(ConfigFile configFile) | ||||||
|  | 		{ | ||||||
|  | 			var saveDraftResult = new Result<ConfigFile>(); | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				await File.WriteAllTextAsync(Path.Combine(Settings.systemd.rootPath, $"{configFile.Name}.service.draft"), configFile.DraftBody, Encoding.UTF8); | ||||||
|  |  | ||||||
|  | 				return saveDraftResult; | ||||||
|  | 			} | ||||||
|  | 			catch (Exception ex) | ||||||
|  | 			{ | ||||||
|  | 				return saveDraftResult.Invalidate(ex.Message, ex); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 		public async Task<Result> ValidateForRenameFileAsync(List<ConfigFile> configFiles, ConfigFile selectedConfigFile, string newName) | ||||||
|  | 		{ | ||||||
|  | 			var renameResult = new Result(); | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 				if (configFiles.Count(cf => cf.Name == newName) > 0) | ||||||
|  | 					return renameResult.Invalidate($"File '{selectedConfigFile.FullPath}' already exists."); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 				if (!File.Exists(selectedConfigFile.FullPath)) | ||||||
|  | 					return renameResult.Invalidate($"Original file '{selectedConfigFile.FullPath}' not found."); | ||||||
|  |  | ||||||
|  | 				var newPathName = Path.Combine(Settings.systemd.rootPath, $"{newName}.service"); | ||||||
|  | 				if (File.Exists(newPathName)) | ||||||
|  | 					return renameResult.Invalidate($"The file '{newPathName}' already exists."); | ||||||
|  |  | ||||||
|  | 				return renameResult; | ||||||
|  | 			} | ||||||
|  | 			catch (Exception ex) | ||||||
|  | 			{ | ||||||
|  | 				return renameResult.Invalidate(ex.Message, ex); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		public async Task<Result<ConfigFile>> RenameFileAsync(ConfigFile configFile, string newName) | ||||||
|  | 		{ | ||||||
|  | 			var renameResult = new Result<ConfigFile>(); | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				var originalPathName = Path.Combine(Settings.systemd.rootPath, $"{configFile.Name}.service"); | ||||||
|  | 				var newPathName = Path.Combine(Settings.systemd.rootPath, newName); | ||||||
|  |  | ||||||
|  | 				File.Move(originalPathName, newPathName, overwrite: false); | ||||||
|  | 				if(configFile.DraftBody != null) | ||||||
|  | 					File.Move(originalPathName, newPathName, overwrite: false); | ||||||
|  |  | ||||||
|  | 				configFile.FullPath = newPathName; | ||||||
|  | 				renameResult.SetData(configFile); | ||||||
|  |  | ||||||
|  | 				return renameResult; | ||||||
|  | 			} | ||||||
|  | 			catch (Exception ex) | ||||||
|  | 			{ | ||||||
|  | 				return renameResult.Invalidate(ex.Message, ex); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								Seenginx/Settings/settings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Seenginx/Settings/settings.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | { | ||||||
|  | 	"nginx": { | ||||||
|  | 		"rootPath": "C:\\nginx\\" | ||||||
|  | 	}, | ||||||
|  | 	"systemd": { | ||||||
|  | 		"rootPath": "C:\\systemd\\system\\" | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										5
									
								
								Seenginx/Shared/SystemdConfigForm.razor
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								Seenginx/Shared/SystemdConfigForm.razor
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | <h3>SystemdConfigForm</h3> | ||||||
|  |  | ||||||
|  | @code { | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -1,10 +1,7 @@ | |||||||
| using System; | using System.IO; | ||||||
| using System.Collections.Generic; | using System.Text.Json; | ||||||
| using System.Linq; |  | ||||||
| using System.Threading.Tasks; |  | ||||||
| using Blazored.Modal; | using Blazored.Modal; | ||||||
| using Microsoft.AspNetCore.Builder; | using Microsoft.AspNetCore.Builder; | ||||||
| using Microsoft.AspNetCore.Components; |  | ||||||
| using Microsoft.AspNetCore.Hosting; | using Microsoft.AspNetCore.Hosting; | ||||||
| using Microsoft.Extensions.Configuration; | using Microsoft.Extensions.Configuration; | ||||||
| using Microsoft.Extensions.DependencyInjection; | using Microsoft.Extensions.DependencyInjection; | ||||||
| @@ -33,11 +30,10 @@ namespace Seenginx | |||||||
| 			services.AddServerSideBlazor(); | 			services.AddServerSideBlazor(); | ||||||
| 			services.AddBlazoredModal(); | 			services.AddBlazoredModal(); | ||||||
|  |  | ||||||
| 			var configPaths = new ConfigPaths(); | 			var settingsJson = File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "Settings", "settings.json")); | ||||||
| 			configPaths.NginxPath = @"C:\nginx\"; | 			var settings = JsonSerializer.Deserialize<SeenginxSettings>(settingsJson); | ||||||
| 			configPaths.SystemDPath = @"C:\systemd\system\"; |  | ||||||
|  |  | ||||||
| 			services.AddSingleton(configPaths); | 			services.AddSingleton(settings); | ||||||
| 			services.AddTransient<CommandService>(); | 			services.AddTransient<CommandService>(); | ||||||
| 			services.AddTransient<IDmesgService, DmesgService>(); | 			services.AddTransient<IDmesgService, DmesgService>(); | ||||||
| 			services.AddTransient<INginxService, NginxService>(); | 			services.AddTransient<INginxService, NginxService>(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user