From 87a73ff24be7341c5fd94680ee4585aaefa40fbd Mon Sep 17 00:00:00 2001 From: Matthew Burke Date: Thu, 24 Aug 2023 12:45:56 -0400 Subject: [PATCH] Refactor to api connections. Update Checker. --- PWAPPv2/Config/PracticeConfig.xml | 10 ++ PWAPPv2/Config/UniversalConfig.txt | 5 + PWAPPv2/MainWindow.xaml.cs | 64 ++++++++--- PWAPPv2/PWAPPv2.csproj | 2 + PWAPPv2/Source/API/APIConfig.cs | 22 +++- PWAPPv2/Source/API/APIConnection.cs | 101 ++++++++++++------ PWAPPv2/Source/API/PWApiConnection.cs | 50 +++++++++ PWAPPv2/Source/Config/Configuration.cs | 54 ++++++++++ PWAPPv2/Source/DataObjects/APICredentials.cs | 8 ++ PWAPPv2/Source/Database/DatabaseConnection.cs | 9 ++ UnitTests/ConfigTest.cs | 21 ++++ UnitTests/PWConnectionTest.cs | 22 ++++ UnitTests/UnitTest1.cs | 30 ++++++ UnitTests/UnitTests.csproj | 2 + 14 files changed, 355 insertions(+), 45 deletions(-) create mode 100644 PWAPPv2/Config/PracticeConfig.xml create mode 100644 PWAPPv2/Config/UniversalConfig.txt create mode 100644 PWAPPv2/Source/API/PWApiConnection.cs create mode 100644 PWAPPv2/Source/Config/Configuration.cs create mode 100644 UnitTests/ConfigTest.cs create mode 100644 UnitTests/PWConnectionTest.cs diff --git a/PWAPPv2/Config/PracticeConfig.xml b/PWAPPv2/Config/PracticeConfig.xml new file mode 100644 index 0000000..2296f93 --- /dev/null +++ b/PWAPPv2/Config/PracticeConfig.xml @@ -0,0 +1,10 @@ + + + 10.0.1.107 + root + + testdoctor + testdoctor + 210 + 12345678 + \ No newline at end of file diff --git a/PWAPPv2/Config/UniversalConfig.txt b/PWAPPv2/Config/UniversalConfig.txt new file mode 100644 index 0000000..78fa985 --- /dev/null +++ b/PWAPPv2/Config/UniversalConfig.txt @@ -0,0 +1,5 @@ + + + http://apipatientweb.azurewebsites.net/ + https://localhost:44354/api/PWAppVersion + \ No newline at end of file diff --git a/PWAPPv2/MainWindow.xaml.cs b/PWAPPv2/MainWindow.xaml.cs index 3242c7b..efbe229 100644 --- a/PWAPPv2/MainWindow.xaml.cs +++ b/PWAPPv2/MainWindow.xaml.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; +using System.Windows.Forms; using System.Windows.Media; /** @@ -17,16 +18,22 @@ namespace PWAPPv2 /// public partial class MainWindow : Window { - static Source.APIConfig apiconfig = new Source.APIConfig(); + static Source.APIConfig apiconfig;// = new Source.APIConfig(); static Source.Database.DatabaseConfig DataConfig; static Source.API.APIConnection apiConnection; Source.DataObjects.APICredentials apiCreds; + Source.API.PWApiConnection pwapiConnection; + Source.DataObjects.ComboBoxData TypeBox; Source.DataObjects.ComboBoxData ToBox; Source.DataObjects.ComboBoxData FromBox; + Source.Config.Configuration practiceConfig; + Source.Config.Configuration universalConfig; + + string[] args; Source.Patient patient; @@ -43,18 +50,49 @@ namespace PWAPPv2 } catch (Exception) { } + + try + { + practiceConfig = new Source.Config.Configuration(".\\Config\\PracticeConfig.xml"); + universalConfig = new Source.Config.Configuration(".\\Config\\UniversalConfig.xml"); + } + catch + (Exception) + { + System.Windows.MessageBox.Show("An error has occured in the configurations files."); + } + + pwapiConnection = new Source.API.PWApiConnection(practiceConfig, universalConfig); + + try + { + if(pwapiConnection.CheckForUpdate() == true) + { + string message = "An update is available! Would you like to install it?"; + string title = "Update available!"; + MessageBoxButtons buttons = MessageBoxButtons.YesNo; + DialogResult result = System.Windows.Forms.MessageBox.Show(message, title, buttons); + if(result == System.Windows.Forms.DialogResult.Yes) + { + System.Windows.MessageBox.Show("HAHA NO UPDATE FOR YOU!"); + } + } + } + catch (Exception) + { + System.Windows.MessageBox.Show("An error has occured while checking for updates"); + } + try { images = new List(); - apiconfig.LoadConfig(ConfigPath); - DataConfig = new Source.Database.DatabaseConfig(ConfigPath); - Source.Database.DatabaseConnection dbcon = new Source.Database.DatabaseConnection(DataConfig); + Source.Database.DatabaseConnection dbcon = new Source.Database.DatabaseConnection(practiceConfig); + + apiconfig = new Source.APIConfig(practiceConfig, universalConfig); apiCreds = new Source.DataObjects.APICredentials(apiconfig); - - apiConnection = new Source.API.APIConnection("http://apipatientweb.azurewebsites.net/", - apiCreds); + apiConnection = new Source.API.APIConnection(universalConfig.Get("PWBaseURI"), apiCreds); InitializeComponent(); @@ -72,7 +110,7 @@ namespace PWAPPv2 } catch(Exception e) { - MessageBox.Show(e.Message); + System.Windows.MessageBox.Show(e.Message); } } @@ -176,11 +214,11 @@ namespace PWAPPv2 string json = att.ToJsonString(); apiConnection.SendPostRequestAsync("api/PWAttachment", json); } - MessageBox.Show("Referral added successfully!"); + System.Windows.MessageBox.Show("Referral added successfully!"); } else { - MessageBox.Show(result); + System.Windows.MessageBox.Show(result); } this.Close(); } @@ -193,12 +231,12 @@ namespace PWAPPv2 //AddImage Button private void Button_Click_2(object sender, RoutedEventArgs e) { - OpenFileDialog openFileDialog = new OpenFileDialog(); + System.Windows.Forms.OpenFileDialog openFileDialog = new System.Windows.Forms.OpenFileDialog(); openFileDialog.Multiselect = true; openFileDialog.Filter = "Image files (*.jpg,*.jpeg)|*.jpg;*.jpeg"; openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); - if (openFileDialog.ShowDialog() == true) + if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { foreach (string filename in openFileDialog.FileNames) { @@ -252,7 +290,7 @@ namespace PWAPPv2 { Grid imageGrid = new Grid(); imageGrid.Width = 477; - imageGrid.HorizontalAlignment = HorizontalAlignment.Left; + imageGrid.HorizontalAlignment = System.Windows.HorizontalAlignment.Left; imageGrid.VerticalAlignment = VerticalAlignment.Top; imageGrid.ShowGridLines = true; diff --git a/PWAPPv2/PWAPPv2.csproj b/PWAPPv2/PWAPPv2.csproj index c100bc5..c797ca4 100644 --- a/PWAPPv2/PWAPPv2.csproj +++ b/PWAPPv2/PWAPPv2.csproj @@ -213,6 +213,8 @@ + + diff --git a/PWAPPv2/Source/API/APIConfig.cs b/PWAPPv2/Source/API/APIConfig.cs index 3a88069..4d99093 100644 --- a/PWAPPv2/Source/API/APIConfig.cs +++ b/PWAPPv2/Source/API/APIConfig.cs @@ -1,4 +1,5 @@ -using System; +using PWAPPv2.Source.Config; +using System; using System.Xml; namespace PWAPPv2.Source @@ -10,6 +11,25 @@ namespace PWAPPv2.Source public string PWPracticeID; public string PWApiID; + public string PWBaseURI; + public string PWUpdateURI; + public string PWAppVersion; + + public APIConfig() { } + + public APIConfig(Config.Configuration practiceConfig, Config.Configuration universalConfig) + { + PWUserID = practiceConfig.Get("pwuserid"); + PWPassword = practiceConfig.Get("pwpassword"); + PWPracticeID = practiceConfig.Get("pwpracticeid"); + PWApiID = practiceConfig.Get("pwapiid"); + + PWBaseURI = universalConfig.Get("PWBaseURI"); + PWUpdateURI = universalConfig.Get("PWUpdateURI"); + PWAppVersion = universalConfig.Get("PWAppVersion"); + + } + public void LoadConfig(string path) { XmlDocument cfgDoc = new XmlDocument(); diff --git a/PWAPPv2/Source/API/APIConnection.cs b/PWAPPv2/Source/API/APIConnection.cs index 6847714..ba72ecc 100644 --- a/PWAPPv2/Source/API/APIConnection.cs +++ b/PWAPPv2/Source/API/APIConnection.cs @@ -1,4 +1,6 @@ -using System; +using Microsoft.Identity.Client.Platforms.Features.DesktopOs.Kerberos; +using System; +using System.Diagnostics; using System.IO; using System.Net; using System.Net.Http; @@ -13,34 +15,28 @@ namespace PWAPPv2.Source.API public DataObjects.APICredentials Credentials; - private static bool ResponseReady = false; - private static string Response = ""; + + HttpClient Client; public APIConnection(string baseUrl, DataObjects.APICredentials credentials) { Credentials = credentials; BaseURL = baseUrl; + + Client = new HttpClient(); + Client.BaseAddress = new Uri(BaseURL); + Client.DefaultRequestHeaders.Accept.Add( + new MediaTypeWithQualityHeaderValue("application/json")); + } - public string GetResponse() - { - while (!ResponseReady) ; - return Response; - } + /// + /// Dont use. Doesn't work, sillyhead. + /// + /// public static async void APIGet(string Call) { - //WebRequest request = WebRequest.Create(BaseURL + Call); - //request.Method = "GET"; - //request.ContentType = "application/json; charset=utf-8"; - //var response = (HttpWebResponse)request.GetResponse(); - //string text; - //using (var sr = new StreamReader(response.GetResponseStream())) - //{ - // text = sr.ReadToEnd(); - //} - //return text; - using (var client = new HttpClient()) { client.BaseAddress = new Uri(BaseURL); @@ -52,16 +48,16 @@ namespace PWAPPv2.Source.API } } + /// + /// Send a post requst without data. Essentially an advanced get since I was a retard when I wrote the original API. + /// + /// + /// public string SendPostRequestAsync(string apiUri) { - HttpClient client = new HttpClient(); - client.BaseAddress = new Uri(BaseURL); - client.DefaultRequestHeaders.Accept.Add( - new MediaTypeWithQualityHeaderValue("application/json")); - StringContent contetnt = new StringContent(Credentials.ToJsonString(), Encoding.UTF8, "application/json"); - var response = client.PostAsync(apiUri, contetnt).Result; + var response = Client.PostAsync(apiUri, contetnt).Result; if (response.IsSuccessStatusCode) { @@ -69,16 +65,18 @@ namespace PWAPPv2.Source.API } return ""; } + + /// + /// Send a post request with data + /// + /// + /// + /// public string SendPostRequestAsync(string apiUri, string PostData) { - HttpClient client = new HttpClient(); - client.BaseAddress = new Uri(BaseURL); - client.DefaultRequestHeaders.Accept.Add( - new MediaTypeWithQualityHeaderValue("application/json")); - StringContent contetnt = new StringContent(PostData, Encoding.UTF8, "application/json"); - var response = client.PostAsync(apiUri, contetnt).Result; + var response = Client.PostAsync(apiUri, contetnt).Result; if (response.IsSuccessStatusCode) { @@ -87,5 +85,46 @@ namespace PWAPPv2.Source.API return ""; } + /// + /// Send a post request with the API credengials in the header of the request. + /// + /// + /// + /// + /// + public string SendPostWithCredsInHeader(string apiUri, string PostData) + { + Client.DefaultRequestHeaders.Add("UserID", Credentials.UserID); + Client.DefaultRequestHeaders.Add("Password", Credentials.Password); + Client.DefaultRequestHeaders.Add("PracticeID", Credentials.PracticeId); + Client.DefaultRequestHeaders.Add("ApiID", Credentials.APIid); + + StringContent content = new StringContent(PostData, Encoding.UTF8, "application/json"); + + var response = Client.PostAsync(apiUri, content).Result; + + Client.DefaultRequestHeaders.Remove("UserID"); + Client.DefaultRequestHeaders.Remove("Password"); + Client.DefaultRequestHeaders.Remove("PraticeID"); + Client.DefaultRequestHeaders.Remove("ApiID"); + + if (response.IsSuccessStatusCode) + { + + return response.Content.ReadAsStringAsync().Result; + } + throw new RequestFailedExcpetion(response.StatusCode.ToString()); + + } + + } + + public class RequestFailedExcpetion : Exception + { + public string RequestError; + public RequestFailedExcpetion(string errorCode) + { + RequestError = "Server responded with error code: " + errorCode; + } } } diff --git a/PWAPPv2/Source/API/PWApiConnection.cs b/PWAPPv2/Source/API/PWApiConnection.cs new file mode 100644 index 0000000..c188642 --- /dev/null +++ b/PWAPPv2/Source/API/PWApiConnection.cs @@ -0,0 +1,50 @@ +using PWAPPv2.Source.DataObjects; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PWAPPv2.Source.API +{ + public class PWApiConnection + { + private APIConnection BaseConnection; + private APIConnection UpdateConnection; + + private APICredentials Credentials; + private string AppVersion; + + public PWApiConnection(Source.Config.Configuration practiceConfig, Source.Config.Configuration universalConfig) + { + Credentials = new APICredentials(practiceConfig); + BaseConnection = new APIConnection(universalConfig.Get("PWBaseURI"), Credentials); + UpdateConnection = new APIConnection(universalConfig.Get("PWUpdateURI"), Credentials); + + AppVersion = universalConfig.Get("PWAppVersion"); + + } + + public string PostToApi(string uri, string data) + { + return BaseConnection.SendPostRequestAsync(uri, data); + } + + public string GetFromApi(string uri) + { + return BaseConnection.SendPostRequestAsync(uri); + } + + public bool CheckForUpdate() + { + string currentVersion = UpdateConnection.SendPostWithCredsInHeader("", ""); + currentVersion = currentVersion.Replace("\"", ""); + if(currentVersion != AppVersion) + { + return true; + } + return false; + } + + } +} diff --git a/PWAPPv2/Source/Config/Configuration.cs b/PWAPPv2/Source/Config/Configuration.cs new file mode 100644 index 0000000..a81d2ee --- /dev/null +++ b/PWAPPv2/Source/Config/Configuration.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using System.IO; + +namespace PWAPPv2.Source.Config +{ + public class Configuration + { + private Dictionary values; + + public Configuration(string file) + { + values = new Dictionary(); + if(!File.Exists(file)) + { + throw new ConfigFileNotFoundException(); + } + + string f = File.ReadAllText(file); + + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.LoadXml(f); + + XmlNodeList xmlNodeList = xmlDoc.DocumentElement.ChildNodes; + foreach (XmlNode xmlNode in xmlNodeList) + { + values.Add(xmlNode.Name, xmlNode.InnerText); + } + + } + + public string Get(string key) + { + try + { + return values[key]; + } + catch + { + throw new ConfigValueNotFoundException(); + } + } + + + } + + public class ConfigFileNotFoundException : Exception { } + + public class ConfigValueNotFoundException: Exception { } +} diff --git a/PWAPPv2/Source/DataObjects/APICredentials.cs b/PWAPPv2/Source/DataObjects/APICredentials.cs index 77e513c..c870733 100644 --- a/PWAPPv2/Source/DataObjects/APICredentials.cs +++ b/PWAPPv2/Source/DataObjects/APICredentials.cs @@ -20,6 +20,14 @@ APIid = config.PWApiID; } + public APICredentials(Source.Config.Configuration practiceConfig) + { + UserID = practiceConfig.Get("pwuserid"); + Password = practiceConfig.Get("pwpassword"); + PracticeId = practiceConfig.Get("pwpracticeid"); + APIid = practiceConfig.Get("pwapiid"); + } + public string BuildJsonBodyContents() { return "'UserID':'" + UserID + "'," + diff --git a/PWAPPv2/Source/Database/DatabaseConnection.cs b/PWAPPv2/Source/Database/DatabaseConnection.cs index c644ca7..33efa00 100644 --- a/PWAPPv2/Source/Database/DatabaseConnection.cs +++ b/PWAPPv2/Source/Database/DatabaseConnection.cs @@ -4,6 +4,9 @@ using System.Collections.Generic; namespace PWAPPv2.Source.Database { + /// + /// Class DatabaseConnection creates and maintains a connection to and OpenDental MySqlDatabase. + /// class DatabaseConnection { @@ -18,6 +21,12 @@ namespace PWAPPv2.Source.Database Connection = new MySqlConnection(SqlString); } + public DatabaseConnection(Config.Configuration config) + { + SqlString = "server=" + config.Get("ODhost") + ";Uid=" + config.Get("ODuser") + ";database=" + config.Get("ODdatabase") + ";Pwd=" + config.Get("ODpassword"); + Connection = new MySqlConnection(SqlString); + } + public void Connect() { try diff --git a/UnitTests/ConfigTest.cs b/UnitTests/ConfigTest.cs new file mode 100644 index 0000000..0510881 --- /dev/null +++ b/UnitTests/ConfigTest.cs @@ -0,0 +1,21 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using PWAPPv2.Source; + +namespace UnitTests +{ + [TestClass] + public class ConfigTest + { + [TestMethod] + public void TestGetPracticeConfigs() + { + PWAPPv2.Source.Config.Configuration configuration = new PWAPPv2.Source.Config.Configuration(".\\Config\\PracticeConfig.xml"); + Assert.IsNotNull(configuration); + + string apiKey = configuration.Get("pwapiid"); + Assert.IsNotNull(apiKey); + + } + } +} diff --git a/UnitTests/PWConnectionTest.cs b/UnitTests/PWConnectionTest.cs new file mode 100644 index 0000000..1194a09 --- /dev/null +++ b/UnitTests/PWConnectionTest.cs @@ -0,0 +1,22 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; + +namespace UnitTests +{ + [TestClass] + public class PWConnectionTest + { + [TestMethod] + public void TestCheckUpdate() + { + PWAPPv2.Source.Config.Configuration practiceConfig = new PWAPPv2.Source.Config.Configuration(".\\Config\\PracticeConfig.xml"); + PWAPPv2.Source.Config.Configuration universalConfig = new PWAPPv2.Source.Config.Configuration(".\\Config\\UniversalConfig.xml"); + + PWAPPv2.Source.API.PWApiConnection pwApiConnection = new PWAPPv2.Source.API.PWApiConnection(practiceConfig, universalConfig); + Assert.IsNotNull(pwApiConnection); + + + Assert.IsFalse(pwApiConnection.CheckForUpdate()); + } + } +} diff --git a/UnitTests/UnitTest1.cs b/UnitTests/UnitTest1.cs index 3de928a..f6a0f58 100644 --- a/UnitTests/UnitTest1.cs +++ b/UnitTests/UnitTest1.cs @@ -25,5 +25,35 @@ namespace UnitTests Assert.AreEqual("\"1|Endo|2|Implant|3|Oral Surgery|4|Ortho|5|Pedo|6|Perio|7|Restore|8|Other \\n\"", res); } + + [TestMethod] + public void TestV2Get() + { + APICredentials creds = new APICredentials(); + creds.UserID = "testdoctor"; + creds.Password = "testdoctor"; + creds.PracticeId = "210"; + creds.APIid = "12345678"; + + APIConnection conn = new APIConnection("https://localhost:44354/", creds); + string res = conn.SendPostWithCredsInHeader("api/PWAppVersion", ""); + + } + + [TestMethod] + [ExpectedException(typeof(RequestFailedExcpetion))] + public void TestInvalidCredentialsV2() + { + APICredentials creds = new APICredentials(); + creds.UserID = "testdoctor"; + creds.Password = "badPassword"; + creds.PracticeId = "210"; + creds.APIid = "12345678"; + + APIConnection conn = new APIConnection("https://localhost:44354/", creds); + string res = conn.SendPostWithCredsInHeader("api/PWAppVersion", ""); + + } + } } diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj index 720bce6..6f705ec 100644 --- a/UnitTests/UnitTests.csproj +++ b/UnitTests/UnitTests.csproj @@ -51,6 +51,8 @@ + +