From 238539899f439864e1593c217f25617ad57995c5 Mon Sep 17 00:00:00 2001 From: Hunter T Date: Tue, 19 Mar 2024 15:01:09 -0700 Subject: [PATCH 01/46] Rename class to more accurately represent purpose --- ActiveDirectoryQuerier/MainWindowViewModel.cs | 24 +++++++++---------- ActiveDirectoryQuerier/Queries/Query.cs | 14 ++++------- .../{CustomQueries.cs => QueryStackPanel.cs} | 2 +- 3 files changed, 18 insertions(+), 22 deletions(-) rename ActiveDirectoryQuerier/Queries/{CustomQueries.cs => QueryStackPanel.cs} (99%) diff --git a/ActiveDirectoryQuerier/MainWindowViewModel.cs b/ActiveDirectoryQuerier/MainWindowViewModel.cs index 34f21d4..40eb550 100644 --- a/ActiveDirectoryQuerier/MainWindowViewModel.cs +++ b/ActiveDirectoryQuerier/MainWindowViewModel.cs @@ -37,7 +37,7 @@ public sealed class MainWindowViewModel : INotifyPropertyChanged // [[ Other fields ]] ----------------------------------------------------------- // private readonly Query _currentQuery; - private readonly CustomQueries _customQuery; + private readonly QueryStackPanel _queryStackPanel; private readonly PSExecutor _psExecutor; private Query? _isEditing; private readonly ActiveDirectoryInfo _activeDirectoryInfo = new(); @@ -172,7 +172,7 @@ public MainWindowViewModel() _consoleOutputInQueryBuilder = new AppConsole(); _consoleOutputInActiveDirectoryInfo = new AppConsole(); _psExecutor = new PSExecutor(); - _customQuery = new CustomQueries(); + _queryStackPanel = new QueryStackPanel(); _currentQuery = new Query(); ADCommands = new ObservableCollection(); @@ -348,8 +348,8 @@ private void DeleteQueryFromQueryStackPanel(object queryButton) if (result == MessageBoxResult.Yes) { QueryButtonStackPanel.Remove(currentButton); - _customQuery.Queries.Remove((Query)currentButton.Tag); - _customQuery.SaveQueriesToJson(); + _queryStackPanel.Queries.Remove((Query)currentButton.Tag); + _queryStackPanel.SaveQueriesToJson(); } } @@ -362,7 +362,7 @@ private void CreateNewQueryFile(object _) { QueryButtonStackPanel.Clear(); //File.WriteAllText(saveFileDialog.FileName, string.Empty); - _customQuery.CustomQueryFileLocation = saveFileDialog.FileName; + _queryStackPanel.CustomQueryFileLocation = saveFileDialog.FileName; } } @@ -371,10 +371,10 @@ private void LoadSavedQueriesFromFile() try { // Load the custom queries from the file (Deserialize) - _customQuery.LoadData(); + _queryStackPanel.LoadData(); // Loop through the queries and create a button for each one. - foreach (var newButton in _customQuery.Queries.Select(CreateQueryButtonInStackPanel)) + foreach (var newButton in _queryStackPanel.Queries.Select(CreateQueryButtonInStackPanel)) { // Lastly add the button to the stack panel QueryButtonStackPanel.Add(newButton); @@ -399,7 +399,7 @@ private void ImportQueryFile(object _) if (result == true) { // Open document - _customQuery.CustomQueryFileLocation = dialog.FileName; + _queryStackPanel.CustomQueryFileLocation = dialog.FileName; QueryButtonStackPanel.Clear(); LoadSavedQueriesFromFile(); @@ -715,9 +715,9 @@ private void SaveQuery(object commandParameter) { // CustomQueries.query editingQuery = _customQuery.Queries.Find(item => item == isEditing); GetCurrentQuery(); - Trace.WriteLine(_customQuery.Queries.IndexOf(_isEditing)); - _customQuery.Queries[_customQuery.Queries.IndexOf(_isEditing)] = _currentQuery; - _customQuery.SaveQueriesToJson(); + Trace.WriteLine(_queryStackPanel.Queries.IndexOf(_isEditing)); + _queryStackPanel.Queries[_queryStackPanel.Queries.IndexOf(_isEditing)] = _currentQuery; + _queryStackPanel.SaveQueriesToJson(); _isEditing = null; QueryEditingEnabled = false; } @@ -728,7 +728,7 @@ private void SaveQuery(object commandParameter) { UpdateSelectedCommand(); - _customQuery.SerializeCommand(SelectedCommandFromComboBoxInQueryBuilder, QueryName, QueryDescription); + _queryStackPanel.SerializeCommand(SelectedCommandFromComboBoxInQueryBuilder, QueryName, QueryDescription); Button newButton = CreateQueryButtonInStackPanel(); diff --git a/ActiveDirectoryQuerier/Queries/Query.cs b/ActiveDirectoryQuerier/Queries/Query.cs index 43b965e..a523d99 100644 --- a/ActiveDirectoryQuerier/Queries/Query.cs +++ b/ActiveDirectoryQuerier/Queries/Query.cs @@ -14,16 +14,19 @@ public class Query /// /// Used for serializing the Command Name /// + // ReSharper disable once InconsistentNaming public string? PSCommandName { get; set; } /// /// Used for Serializing the Commands parameters /// + // ReSharper disable once InconsistentNaming public string[]? PSCommandParameters { get; set; } /// /// Used for Serializing the Commands parameters /// + // ReSharper disable once InconsistentNaming public string[]? PSCommandParameterValues { get; set; } /// @@ -35,19 +38,12 @@ public class Query /// Used for the Custom Queries Description /// public string? QueryDescription { get; set; } - - /// - /// Constructor for the query class - /// - /// Name of the Command EX. get-adusers + public Query(string psCommandName) { PSCommandName = psCommandName; } - - /// - /// Empty constructor for the query class - /// + public Query() { } } diff --git a/ActiveDirectoryQuerier/Queries/CustomQueries.cs b/ActiveDirectoryQuerier/Queries/QueryStackPanel.cs similarity index 99% rename from ActiveDirectoryQuerier/Queries/CustomQueries.cs rename to ActiveDirectoryQuerier/Queries/QueryStackPanel.cs index 8d5f04c..bfaa78e 100644 --- a/ActiveDirectoryQuerier/Queries/CustomQueries.cs +++ b/ActiveDirectoryQuerier/Queries/QueryStackPanel.cs @@ -11,7 +11,7 @@ namespace ActiveDirectoryQuerier.Queries; /// This class is used to save a json file named "CustomQueries.json" inside of /// \ActiveDirectoryQuerier\ActiveDirectoryQuerier\bin\Debug\net6.0-windows This /// -public class CustomQueries +public class QueryStackPanel { public List Queries { get; private set; } = new(); public string CustomQueryFileLocation { get; set; } = string.Empty; From 06134cb32284234a07beb89e9bbda7e2f7c16573 Mon Sep 17 00:00:00 2001 From: Hunter T Date: Tue, 19 Mar 2024 15:32:11 -0700 Subject: [PATCH 02/46] Improve class, method, and variable names --- ActiveDirectoryQuerier/MainWindowViewModel.cs | 24 +-- .../Queries/QueryManager.cs | 121 +++++++++++++++ .../Queries/QueryStackPanel.cs | 138 ------------------ 3 files changed, 133 insertions(+), 150 deletions(-) create mode 100644 ActiveDirectoryQuerier/Queries/QueryManager.cs delete mode 100644 ActiveDirectoryQuerier/Queries/QueryStackPanel.cs diff --git a/ActiveDirectoryQuerier/MainWindowViewModel.cs b/ActiveDirectoryQuerier/MainWindowViewModel.cs index 40eb550..e54648d 100644 --- a/ActiveDirectoryQuerier/MainWindowViewModel.cs +++ b/ActiveDirectoryQuerier/MainWindowViewModel.cs @@ -37,7 +37,7 @@ public sealed class MainWindowViewModel : INotifyPropertyChanged // [[ Other fields ]] ----------------------------------------------------------- // private readonly Query _currentQuery; - private readonly QueryStackPanel _queryStackPanel; + private readonly QueryManager _queryManager; private readonly PSExecutor _psExecutor; private Query? _isEditing; private readonly ActiveDirectoryInfo _activeDirectoryInfo = new(); @@ -172,7 +172,7 @@ public MainWindowViewModel() _consoleOutputInQueryBuilder = new AppConsole(); _consoleOutputInActiveDirectoryInfo = new AppConsole(); _psExecutor = new PSExecutor(); - _queryStackPanel = new QueryStackPanel(); + _queryManager = new QueryManager(); _currentQuery = new Query(); ADCommands = new ObservableCollection(); @@ -348,8 +348,8 @@ private void DeleteQueryFromQueryStackPanel(object queryButton) if (result == MessageBoxResult.Yes) { QueryButtonStackPanel.Remove(currentButton); - _queryStackPanel.Queries.Remove((Query)currentButton.Tag); - _queryStackPanel.SaveQueriesToJson(); + _queryManager.Queries.Remove((Query)currentButton.Tag); + _queryManager.SaveQueryToFile(); } } @@ -362,7 +362,7 @@ private void CreateNewQueryFile(object _) { QueryButtonStackPanel.Clear(); //File.WriteAllText(saveFileDialog.FileName, string.Empty); - _queryStackPanel.CustomQueryFileLocation = saveFileDialog.FileName; + _queryManager.QuerySaveLocation = saveFileDialog.FileName; } } @@ -371,10 +371,10 @@ private void LoadSavedQueriesFromFile() try { // Load the custom queries from the file (Deserialize) - _queryStackPanel.LoadData(); + _queryManager.LoadQueriesFromFile(); // Loop through the queries and create a button for each one. - foreach (var newButton in _queryStackPanel.Queries.Select(CreateQueryButtonInStackPanel)) + foreach (var newButton in _queryManager.Queries.Select(CreateQueryButtonInStackPanel)) { // Lastly add the button to the stack panel QueryButtonStackPanel.Add(newButton); @@ -399,7 +399,7 @@ private void ImportQueryFile(object _) if (result == true) { // Open document - _queryStackPanel.CustomQueryFileLocation = dialog.FileName; + _queryManager.QuerySaveLocation = dialog.FileName; QueryButtonStackPanel.Clear(); LoadSavedQueriesFromFile(); @@ -715,9 +715,9 @@ private void SaveQuery(object commandParameter) { // CustomQueries.query editingQuery = _customQuery.Queries.Find(item => item == isEditing); GetCurrentQuery(); - Trace.WriteLine(_queryStackPanel.Queries.IndexOf(_isEditing)); - _queryStackPanel.Queries[_queryStackPanel.Queries.IndexOf(_isEditing)] = _currentQuery; - _queryStackPanel.SaveQueriesToJson(); + Trace.WriteLine(_queryManager.Queries.IndexOf(_isEditing)); + _queryManager.Queries[_queryManager.Queries.IndexOf(_isEditing)] = _currentQuery; + _queryManager.SaveQueryToFile(); _isEditing = null; QueryEditingEnabled = false; } @@ -728,7 +728,7 @@ private void SaveQuery(object commandParameter) { UpdateSelectedCommand(); - _queryStackPanel.SerializeCommand(SelectedCommandFromComboBoxInQueryBuilder, QueryName, QueryDescription); + _queryManager.ConvertCommandToQueryAndSave(SelectedCommandFromComboBoxInQueryBuilder, QueryName, QueryDescription); Button newButton = CreateQueryButtonInStackPanel(); diff --git a/ActiveDirectoryQuerier/Queries/QueryManager.cs b/ActiveDirectoryQuerier/Queries/QueryManager.cs new file mode 100644 index 0000000..6db4020 --- /dev/null +++ b/ActiveDirectoryQuerier/Queries/QueryManager.cs @@ -0,0 +1,121 @@ +using System.IO; +using System.Management.Automation.Runspaces; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Windows; + +namespace ActiveDirectoryQuerier.Queries; + +/// +/// This class is for the collection of queries, it is used for serializing and deserializing the queries to a file. +/// +public class QueryManager +{ + private readonly JsonSerializerOptions _jsonSerializationOptions = new() { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + WriteIndented = true, + ReferenceHandler = ReferenceHandler.Preserve, + }; + + public List Queries { get; private set; } = new(); + public string QuerySaveLocation { get; set; } = string.Empty; + + public void SaveQueryToFile() + { + try + { + string serializedJsonQueries = JsonSerializer.Serialize(Queries, _jsonSerializationOptions); + File.WriteAllText(QuerySaveLocation == "" ? "CustomQueries.json" : QuerySaveLocation, + serializedJsonQueries); + } + catch (Exception exception) + { + MessageBox.Show(exception.Message); + } + } + + public void ConvertCommandToQueryAndSave(Command psCommand, string queryName, string queryDescription) + { + var commandParameters = new string[psCommand.Parameters.Count]; + var commandParameterValues = new string[psCommand.Parameters.Count]; + Query newQuery = new(psCommand.CommandText) { QueryName = queryName, QueryDescription = queryDescription }; + + // Loop through the parameters and add them to the new query. + for (int i = 0; i < psCommand.Parameters.Count; i++) + { + CommandParameter param = psCommand.Parameters[i]; + commandParameters[i] = param.Name; + commandParameterValues[i] = param.Value.ToString()!; + } + + // Set the new query's parameters. + newQuery.PSCommandParameters = commandParameters; + newQuery.PSCommandParameterValues = commandParameterValues; + + // Add the new query to the list of queries. + Queries.Add(newQuery); + SaveQueryToFile(); + + try + { + string serializedJsonQueries = JsonSerializer.Serialize(Queries, _jsonSerializationOptions); + File.WriteAllText(QuerySaveLocation == "" ? "CustomQueries.json" : QuerySaveLocation, + serializedJsonQueries); + } + // TODO: Improve exception handling. + catch (Exception exception) + { + MessageBox.Show(exception.Message); + } + } + + public void LoadQueriesFromFile() + { + try + { + string fileContents; + + // Opens file and reads it then adds the json to the Queries List + if (QuerySaveLocation == "") + { + if (File.Exists("CustomQueries.json")) + { + fileContents = File.ReadAllText("CustomQueries.json"); + } + else + { + return; + } + } + else + { + fileContents = File.ReadAllText(QuerySaveLocation); + } + + Queries = JsonSerializer.Deserialize>(fileContents, _jsonSerializationOptions)!; + + // Now we want to fill the command variable for each query + foreach (Query query in Queries) + { + Command psCommand = new(query.PSCommandName); + + // Check if there are parameters, and if there are add them to the list + if (query.PSCommandParameters != null) + { + for (int i = 0; i < query.PSCommandParameters.Length; i++) + { + psCommand.Parameters.Add(query.PSCommandParameters[i], query.PSCommandParameterValues![i]); + } + } + + // set the query command to the command + query.Command = psCommand; + } + } + // TODO: Improve exception handling. + catch (Exception exception) + { + MessageBox.Show(exception.Message); + } + } +} diff --git a/ActiveDirectoryQuerier/Queries/QueryStackPanel.cs b/ActiveDirectoryQuerier/Queries/QueryStackPanel.cs deleted file mode 100644 index bfaa78e..0000000 --- a/ActiveDirectoryQuerier/Queries/QueryStackPanel.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System.Diagnostics; -using System.IO; -using System.Management.Automation.Runspaces; -using System.Text.Json; -using System.Text.Json.Serialization; -using System.Windows; - -namespace ActiveDirectoryQuerier.Queries; - -/// -/// This class is used to save a json file named "CustomQueries.json" inside of -/// \ActiveDirectoryQuerier\ActiveDirectoryQuerier\bin\Debug\net6.0-windows This -/// -public class QueryStackPanel -{ - public List Queries { get; private set; } = new(); - public string CustomQueryFileLocation { get; set; } = string.Empty; - - /// - /// This a variable for feeding options to the Json serializer - /// - private static readonly JsonSerializerOptions _options = new() { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - WriteIndented = true, - ReferenceHandler = ReferenceHandler.Preserve, - }; - - /// - /// This takes the Queries List and serializes it to a file - /// - public void SaveQueriesToJson() - { - try - { - string serializedJsonQueries = JsonSerializer.Serialize(Queries, _options); - File.WriteAllText(CustomQueryFileLocation == "" ? "CustomQueries.json" : CustomQueryFileLocation, - serializedJsonQueries); - } - catch (Exception ex) - { - MessageBox.Show(ex.Message); - } - } - - /// - /// This method is for serializing a command type, so it converts the type to a query and then serializes it - /// - /// Command class that you want to serialize - /// Description field of the Query - /// Query Name - public void SerializeCommand(Command? psCommand, string queryName, string queryDescription) - { - string[] commandParameters = new string[psCommand!.Parameters.Count]; - string[] commandParameterValues = new string[psCommand.Parameters.Count]; - Query newQuery = new(psCommand.CommandText) { QueryName = queryName, QueryDescription = queryDescription }; - - // Iterate over the parameters and add them to the string - for (int i = 0; i < psCommand.Parameters.Count; i++) - { - CommandParameter param = psCommand.Parameters[i]; - - commandParameters[i] = param.Name; - commandParameterValues[i] = param.Value.ToString()!; - } - - newQuery.PSCommandParameters = commandParameters; - newQuery.PSCommandParameterValues = commandParameterValues; - - Queries.Add(newQuery); - SaveQueriesToJson(); - - try - { - string serializedJsonQueries = JsonSerializer.Serialize(Queries, _options); - if (CustomQueryFileLocation == "") - { - File.WriteAllText("CustomQueries.json", serializedJsonQueries); - } - else - { - File.WriteAllText(CustomQueryFileLocation, serializedJsonQueries); - } - } - catch (Exception ex) - { - MessageBox.Show(ex.Message); - } - } - /// - /// This method Loads the string from the saved file "CustomQueries.dat" then gives it to the Queries List - /// - public void LoadData() - { - try - { - // Opens file and reads it then adds the json to the Queries List - string json; - if (CustomQueryFileLocation == "") - { - if (File.Exists("CustomQueries.json")) - { - json = File.ReadAllText("CustomQueries.json"); - } - else - { - return; - } - } - else - { - json = File.ReadAllText(CustomQueryFileLocation); - } - Queries = JsonSerializer.Deserialize>(json, _options)!; - - // Now we want to fill the command variable for each query - foreach (Query query in Queries) - { - Command psCommand = new Command(query.PSCommandName); - - // Check if there are parameters, and if there are add them to the list - if (query.PSCommandParameters != null) - { - for (int i = 0; i < query.PSCommandParameters.Length; i++) - { - psCommand.Parameters.Add(query.PSCommandParameters[i], query.PSCommandParameterValues![i]); - } - } - - // set the query command to the command - query.Command = psCommand; - } - } - catch (Exception exception) - { - MessageBox.Show(exception.Message); - } - } -} From 8fda393a5e61e24bacb0e898cc6a25dba8256683 Mon Sep 17 00:00:00 2001 From: Hunter T Date: Tue, 19 Mar 2024 16:27:20 -0700 Subject: [PATCH 03/46] Refactoring --- .../ADCommandParametersTests.cs | 1 - .../ADCommandsFetcherTests.cs | 1 - .../ComboBoxParameterViewModelTests.cs | 1 - ActiveDirectoryQuerier/MainWindowViewModel.cs | 144 ++++++++---------- ActiveDirectoryQuerier/Queries/Query.cs | 4 +- .../Queries/QueryManager.cs | 16 +- 6 files changed, 71 insertions(+), 96 deletions(-) diff --git a/ActiveDirectoryQuerier.Tests/ADCommandParametersTests.cs b/ActiveDirectoryQuerier.Tests/ADCommandParametersTests.cs index bb2cadd..4b27723 100644 --- a/ActiveDirectoryQuerier.Tests/ADCommandParametersTests.cs +++ b/ActiveDirectoryQuerier.Tests/ADCommandParametersTests.cs @@ -1,6 +1,5 @@ using System.Management.Automation.Runspaces; using ActiveDirectoryQuerier.ActiveDirectory; -using ActiveDirectoryQuerier.PowerShell; namespace ActiveDirectoryQuerier.Tests; diff --git a/ActiveDirectoryQuerier.Tests/ADCommandsFetcherTests.cs b/ActiveDirectoryQuerier.Tests/ADCommandsFetcherTests.cs index a5afd55..309c4de 100644 --- a/ActiveDirectoryQuerier.Tests/ADCommandsFetcherTests.cs +++ b/ActiveDirectoryQuerier.Tests/ADCommandsFetcherTests.cs @@ -1,7 +1,6 @@ using System.Collections.ObjectModel; using System.Management.Automation.Runspaces; using ActiveDirectoryQuerier.ActiveDirectory; -using ActiveDirectoryQuerier.PowerShell; namespace ActiveDirectoryQuerier.Tests; diff --git a/ActiveDirectoryQuerier.Tests/ComboBoxParameterViewModelTests.cs b/ActiveDirectoryQuerier.Tests/ComboBoxParameterViewModelTests.cs index a98c571..61dd60b 100644 --- a/ActiveDirectoryQuerier.Tests/ComboBoxParameterViewModelTests.cs +++ b/ActiveDirectoryQuerier.Tests/ComboBoxParameterViewModelTests.cs @@ -1,7 +1,6 @@ using System.Collections.ObjectModel; using System.Management.Automation.Runspaces; using ActiveDirectoryQuerier.ActiveDirectory; -using ActiveDirectoryQuerier.PowerShell; using ActiveDirectoryQuerier.ViewModels; namespace ActiveDirectoryQuerier.Tests; diff --git a/ActiveDirectoryQuerier/MainWindowViewModel.cs b/ActiveDirectoryQuerier/MainWindowViewModel.cs index e54648d..cc9d1c8 100644 --- a/ActiveDirectoryQuerier/MainWindowViewModel.cs +++ b/ActiveDirectoryQuerier/MainWindowViewModel.cs @@ -11,7 +11,6 @@ using ActiveDirectoryQuerier.PowerShell; using ActiveDirectoryQuerier.Queries; using ActiveDirectoryQuerier.ViewModels; -using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.Win32; namespace ActiveDirectoryQuerier; @@ -25,7 +24,7 @@ public sealed class MainWindowViewModel : INotifyPropertyChanged // [[ Backing fields for properties ]] ------------------------------------------ // - private bool _queryEditingEnabled; + private bool _isQueryEditingEnabled; private string _queryName; private string _queryDescription; private AppConsole _consoleOutputInQueryBuilder; @@ -39,21 +38,14 @@ public sealed class MainWindowViewModel : INotifyPropertyChanged private readonly Query _currentQuery; private readonly QueryManager _queryManager; private readonly PSExecutor _psExecutor; - private Query? _isEditing; + private Query? _queryBeingEdited; private readonly ActiveDirectoryInfo _activeDirectoryInfo = new(); // [ Properties ] --------------------------------------------------------------- // // [[ Properties for backing fields ]] ------------------------------------------ // - - public bool QueryEditingEnabled - { - get => _queryEditingEnabled; - set { - _queryEditingEnabled = value; - OnPropertyChanged(nameof(QueryEditingEnabled)); - } - } - + + public ObservableCollection