From ffe60a7c15e95749a4dca197092c82c829bca056 Mon Sep 17 00:00:00 2001 From: Robert Sirre Date: Thu, 1 Dec 2022 01:21:58 +0100 Subject: [PATCH] Converted to .Net standard Replaced JsonConverter, separated parsing into predictable envelope and dynamic payload. Update --- DuoApi.Examples/DuoApi.Examples.csproj | 12 + {examples => DuoApi.Examples}/Program.cs | 20 +- {test => DuoApi.Tests}/ApiCallTest.cs | 18 +- DuoApi.Tests/DuoApi.Tests.csproj | 26 +++ {test => DuoApi.Tests}/QueryParamsTest.cs | 2 +- {test => DuoApi.Tests}/SigningTest.cs | 2 +- DuoApi/DataEnvelope.cs | 43 ++++ {duo_api_csharp => DuoApi}/Duo.cs | 254 +++++++++++----------- DuoApi/DuoApi.csproj | 14 ++ DuoApi/DuoApiResponseStatus.cs | 7 + DuoApi/PagingInfo.cs | 12 + duo_api_csharp.sln | 34 +-- duo_api_csharp/duo_api_csharp.csproj | 54 ----- examples/App.config | 6 - examples/Examples.csproj | 59 ----- examples/Properties/AssemblyInfo.cs | 36 --- test/DuoApiTest.csproj | 124 ----------- test/Makefile | 10 - test/Properties/AssemblyInfo.cs | 36 --- test/app.config | 11 - test/packages.config | 20 -- 21 files changed, 276 insertions(+), 524 deletions(-) create mode 100644 DuoApi.Examples/DuoApi.Examples.csproj rename {examples => DuoApi.Examples}/Program.cs (76%) rename {test => DuoApi.Tests}/ApiCallTest.cs (96%) create mode 100644 DuoApi.Tests/DuoApi.Tests.csproj rename {test => DuoApi.Tests}/QueryParamsTest.cs (99%) rename {test => DuoApi.Tests}/SigningTest.cs (99%) create mode 100644 DuoApi/DataEnvelope.cs rename {duo_api_csharp => DuoApi}/Duo.cs (79%) create mode 100644 DuoApi/DuoApi.csproj create mode 100644 DuoApi/DuoApiResponseStatus.cs create mode 100644 DuoApi/PagingInfo.cs delete mode 100644 duo_api_csharp/duo_api_csharp.csproj delete mode 100644 examples/App.config delete mode 100644 examples/Examples.csproj delete mode 100644 examples/Properties/AssemblyInfo.cs delete mode 100644 test/DuoApiTest.csproj delete mode 100644 test/Makefile delete mode 100644 test/Properties/AssemblyInfo.cs delete mode 100644 test/app.config delete mode 100644 test/packages.config diff --git a/DuoApi.Examples/DuoApi.Examples.csproj b/DuoApi.Examples/DuoApi.Examples.csproj new file mode 100644 index 0000000..8b31ff7 --- /dev/null +++ b/DuoApi.Examples/DuoApi.Examples.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + diff --git a/examples/Program.cs b/DuoApi.Examples/Program.cs similarity index 76% rename from examples/Program.cs rename to DuoApi.Examples/Program.cs index 110606b..ef6c6ce 100644 --- a/examples/Program.cs +++ b/DuoApi.Examples/Program.cs @@ -23,8 +23,7 @@ static int Main(string[] args) var r = client.JSONApiCall>( "GET", "/admin/v1/info/authentication_attempts", parameters); var attempts = r["authentication_attempts"] as Dictionary; - foreach (KeyValuePair info in attempts) - { + foreach (KeyValuePair info in attempts) { var s = String.Format("{0} authentication(s) ended with {1}.", info.Value, info.Key); @@ -35,28 +34,23 @@ static int Main(string[] args) var users = client.JSONApiCall( "GET", "/admin/v1/users", parameters); System.Console.WriteLine(String.Format("{0} users.", users.Count)); - foreach (Dictionary user in users) - { + foreach (Dictionary user in users) { System.Console.WriteLine( "\t" + "Username: " + (user["username"] as string)); } // paging call int? offset = 0; - while (offset != null) - { - var jsonResponse = client.JSONPagingApiCall("GET", "/admin/v1/users", parameters, (int)offset, 10); - var pagedUsers = jsonResponse["response"] as System.Collections.ArrayList; + while (offset != null) { + var pagedUsers = client.JSONPagingApiCall("GET", "/admin/v1/users", parameters, (int)offset, 10, out var metadata); System.Console.WriteLine(String.Format("{0} users at offset {1}", pagedUsers.Count, offset)); - foreach (Dictionary user in pagedUsers) - { + foreach (Dictionary user in pagedUsers) { System.Console.WriteLine( "\t" + "Username: " + (user["username"] as string)); } - var metadata = jsonResponse["metadata"] as Dictionary; - if (metadata.ContainsKey("next_offset")) + if (metadata.next_offset.HasValue) { - offset = metadata["next_offset"] as int?; + offset = metadata.next_offset.Value; } else { diff --git a/test/ApiCallTest.cs b/DuoApi.Tests/ApiCallTest.cs similarity index 96% rename from test/ApiCallTest.cs rename to DuoApi.Tests/ApiCallTest.cs index 23d67f6..8773251 100644 --- a/test/ApiCallTest.cs +++ b/DuoApi.Tests/ApiCallTest.cs @@ -386,10 +386,10 @@ public void TestValidJsonPagingResponseNoParameters() return "{\"stat\": \"OK\", \"response\": \"hello, world!\", \"metadata\": {\"next_offset\":10}}"; }; var parameters = new Dictionary(); - var jsonResponse = api.JSONPagingApiCall("GET", "/json_ok", parameters, 0, 10); - Assert.Equal("hello, world!", jsonResponse["response"]); - var metadata = jsonResponse["metadata"] as Dictionary; - Assert.Equal(10, metadata["next_offset"]); + var jsonResponse = api.JSONPagingApiCall("GET", "/json_ok", parameters, 0, 10, out var metadata); + Assert.Equal("hello, world!", jsonResponse); + + Assert.Equal(10, metadata.next_offset); // make sure parameters was not changed as a side-effect Assert.Empty(parameters); } @@ -406,10 +406,10 @@ public void TestValidJsonPagingResponseExistingParameters() {"offset", "0"}, {"limit", "10"} }; - var jsonResponse = api.JSONPagingApiCall("GET", "/json_ok", parameters, 10, 20); - Assert.Equal("hello, world!", jsonResponse["response"]); - var metadata = jsonResponse["metadata"] as Dictionary; - Assert.False(metadata.ContainsKey("next_offset")); + var jsonResponse = api.JSONPagingApiCall("GET", "/json_ok", parameters, 10, 20, out var metadata); + Assert.Equal("hello, world!", jsonResponse); + + Assert.NotNull(metadata); // make sure parameters was not changed as a side-effect Assert.Equal(2, parameters.Count); Assert.Equal("0", parameters["offset"]); @@ -456,7 +456,7 @@ public void TestJsonResponseMissingField() }); Assert.NotNull(ex); - var e = Assert.IsType(ex); + var e = Assert.IsType(ex); Assert.Equal(400, e.HttpStatus); diff --git a/DuoApi.Tests/DuoApi.Tests.csproj b/DuoApi.Tests/DuoApi.Tests.csproj new file mode 100644 index 0000000..e39f0bd --- /dev/null +++ b/DuoApi.Tests/DuoApi.Tests.csproj @@ -0,0 +1,26 @@ + + + + netcoreapp3.1 + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/test/QueryParamsTest.cs b/DuoApi.Tests/QueryParamsTest.cs similarity index 99% rename from test/QueryParamsTest.cs rename to DuoApi.Tests/QueryParamsTest.cs index 70956bb..76613bf 100644 --- a/test/QueryParamsTest.cs +++ b/DuoApi.Tests/QueryParamsTest.cs @@ -106,4 +106,4 @@ public void NextOffsetTest() var expected = "foo=1&next_offset=fjaewoifjew&next_offset=473891274832917498"; Assert.Equal(expected, DuoApi.CanonicalizeParams(parameters)); } -} +} \ No newline at end of file diff --git a/test/SigningTest.cs b/DuoApi.Tests/SigningTest.cs similarity index 99% rename from test/SigningTest.cs rename to DuoApi.Tests/SigningTest.cs index 4c5d933..c078157 100644 --- a/test/SigningTest.cs +++ b/DuoApi.Tests/SigningTest.cs @@ -31,4 +31,4 @@ public void HmacSha512() var expected = "Basic dGVzdF9pa2V5OjA1MDgwNjUwMzVhMDNiMmExZGUyZjQ1M2U2MjllNzkxZDE4MDMyOWUxNTdmNjVkZjZiM2UwZjA4Mjk5ZDQzMjFlMWM1YzdhN2M3ZWU2YjllNWZjODBkMWZiNmZiZjNhZDVlYjdjNDRkZDNiMzk4NWEwMmMzN2FjYTUzZWMzNjk4"; Assert.Equal(expected, actual); } -} +} \ No newline at end of file diff --git a/DuoApi/DataEnvelope.cs b/DuoApi/DataEnvelope.cs new file mode 100644 index 0000000..25694a6 --- /dev/null +++ b/DuoApi/DataEnvelope.cs @@ -0,0 +1,43 @@ +using System.ComponentModel.DataAnnotations; + +namespace Duo +{ + + /// + /// + /// + /// + public class DataEnvelope + { + /// + /// + /// + [Required] + public DuoApiResponseStatus stat { get; set; } + + /// + /// + /// + public int? code { get; set; } + + /// + /// + /// + public T response { get; set; } + + /// + /// Upon error, basic error information + /// + public string message { get; set; } + + /// + /// Upon error, detailed error information + /// + public string message_detail { get; set; } + + /// + /// + /// + public PagingInfo metadata { get; set; } + } +} diff --git a/duo_api_csharp/Duo.cs b/DuoApi/Duo.cs similarity index 79% rename from duo_api_csharp/Duo.cs rename to DuoApi/Duo.cs index d809085..f2b247d 100644 --- a/duo_api_csharp/Duo.cs +++ b/DuoApi/Duo.cs @@ -10,12 +10,12 @@ using System.Security.Cryptography; using System.Text.RegularExpressions; using System.Text; -using System.Web.Script.Serialization; using System.Web; using System.Globalization; using System.Linq; using System.Runtime.InteropServices; - +using System.Text.Json; +using System.Text.Json.Serialization; namespace Duo { @@ -249,9 +249,12 @@ private HttpWebRequest PrepareHttpRequest(String method, String url, String auth request.Headers.Add("Authorization", auth); request.Headers.Add("X-Duo-Date", date); request.UserAgent = this.user_agent; + + //todo: Understand, handle and test proxy config + // If no proxy, check for and use WinHTTP proxy as autoconfig won't pick this up when run from a service - if (!HasProxyServer(request)) - request.Proxy = GetWinhttpProxy(); + //if (!HasProxyServer(request)) + //request.Proxy = GetWinhttpProxy(); if (method.Equals("POST") || method.Equals("PUT")) { @@ -313,45 +316,41 @@ private HttpWebResponse AttemptRetriableHttpRequest( /// calls (particularly in the Auth APIs) will not /// return a complete JSON response. /// raises if JSON response indicates an error - private Dictionary BaseJSONApiCall(string method, + private T BaseJSONApiCall(string method, string path, Dictionary parameters, int timeout, - DateTime date) + DateTime date, + out PagingInfo metaData) { HttpStatusCode statusCode; string res = this.ApiCall(method, path, parameters, timeout, date, out statusCode); - var jss = new JavaScriptSerializer(); try { - var dict = jss.Deserialize>(res); - if (dict["stat"] as string == "OK") + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }; + + options.Converters.Add(new JsonStringEnumConverter()); + + var dict = JsonSerializer.Deserialize>(res, options); + if (dict.stat == DuoApiResponseStatus.Ok) { - return dict; + metaData = dict.metadata; + return dict.response; } else { - int? check = dict["code"] as int?; - int code; - if (check.HasValue) - { - code = check.Value; - } - else - { - code = 0; - } - String message_detail = ""; - if (dict.ContainsKey("message_detail")) - { - message_detail = dict["message_detail"] as string; - } + + int code = dict.code.GetValueOrDefault(); + throw new ApiException(code, (int)statusCode, - dict["message"] as string, - message_detail); + dict.message, + dict.message_detail); } } catch (ApiException) @@ -406,17 +405,17 @@ public T JSONApiCall(string method, DateTime date) where T : class { - var dict = BaseJSONApiCall(method, path, parameters, timeout, date); - return dict["response"] as T; + return BaseJSONApiCall(method, path, parameters, timeout, date, out _); } - public Dictionary JSONPagingApiCall(string method, + public T JSONPagingApiCall(string method, string path, Dictionary parameters, int offset, - int limit) + int limit, + out PagingInfo metaData) { - return JSONPagingApiCall(method, path, parameters, offset, limit, 0, DateTime.UtcNow); + return JSONPagingApiCall(method, path, parameters, offset, limit, 0, DateTime.UtcNow, out metaData); } /// The current date and time, used to authenticate @@ -439,20 +438,21 @@ public Dictionary JSONPagingApiCall(string method, /// return a JSON dictionary with top level keys: stat, response, metadata. /// The actual requested data is in 'response'. 'metadata' contains a /// 'next_offset' key which should be used to fetch the next page. - public Dictionary JSONPagingApiCall(string method, + public T JSONPagingApiCall(string method, string path, Dictionary parameters, int offset, int limit, int timeout, - DateTime date) + DateTime date, + out PagingInfo metaData) { // copy parameters so we don't cause any side-effects parameters = new Dictionary(parameters); parameters["offset"] = offset.ToString(); // overrides caller value parameters["limit"] = limit.ToString(); - return this.BaseJSONApiCall(method, path, parameters, timeout, date); + return this.BaseJSONApiCall(method, path, parameters, timeout, date, out metaData); } @@ -509,98 +509,98 @@ private static string DateToRFC822(DateTime date) return date_string; } - /// - /// Gets the WinHTTP proxy. - /// - /// - /// Normally, C# picks up these proxy settings by default, but when run under the SYSTEM account, it does not. - /// - /// - private static System.Net.WebProxy GetWinhttpProxy() - { - string[] proxyServerNames = null; - string primaryProxyServer = null; - string[] bypassHostnames = null; - bool enableLocalBypass = false; - System.Net.WebProxy winhttpProxy = null; - - // Has a proxy been configured? - // No. Is a WinHTTP proxy set? - int internetHandle = WinHttpOpen("DuoTest", WinHttp_Access_Type.WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, null, null, 0); - if (internetHandle != 0) - { - // Yes, use it. This is normal when run under the SYSTEM account and a WinHTTP proxy is configured. When run as a normal user, - // the Proxy property will already be configured correctly. To resolve this for SYSTEM, manually read proxy settings and configure. - var proxyInfo = new WINHTTP_PROXY_INFO(); - WinHttpGetDefaultProxyConfiguration(proxyInfo); - if (proxyInfo.lpszProxy != null) - { - if (proxyInfo.lpszProxy != null) - { - proxyServerNames = proxyInfo.lpszProxy.Split(new char[] { ' ', '\t', ';' }); - if ((proxyServerNames == null) || (proxyServerNames.Length == 0)) - primaryProxyServer = proxyInfo.lpszProxy; - else - primaryProxyServer = proxyServerNames[0]; - } - if (proxyInfo.lpszProxyBypass != null) - { - bypassHostnames = proxyInfo.lpszProxyBypass.Split(new char[] { ' ', '\t', ';' }); - if ((bypassHostnames == null) || (bypassHostnames.Length == 0)) - bypassHostnames = new string[] { proxyInfo.lpszProxyBypass }; - if (bypassHostnames != null) - enableLocalBypass = bypassHostnames.Contains("local", StringComparer.InvariantCultureIgnoreCase); - } - if (primaryProxyServer != null) - winhttpProxy = new System.Net.WebProxy(proxyServerNames[0], enableLocalBypass, bypassHostnames); - } - WinHttpCloseHandle(internetHandle); - internetHandle = 0; - } - else - { - throw new Exception(String.Format("WinHttp init failed {0}", System.Runtime.InteropServices.Marshal.GetLastWin32Error())); - } - - return winhttpProxy; - } - - /// - /// Determines if the specified web request is using a proxy server. - /// - /// - /// If no proxy is set, the Proxy member is typically non-null and set to an object type that includes but hides IWebProxy with no address, - /// so it cannot be inspected. Resolving this requires reflection to extract the hidden webProxy object and check it's Address member. - /// - /// Request to check - /// TRUE if a proxy is in use, else FALSE - public static bool HasProxyServer(HttpWebRequest requestObject) - { - WebProxy actualProxy = null; - bool hasProxyServer = false; - - if (requestObject.Proxy != null) - { - // WebProxy is described as the base class for IWebProxy, so we should always see this type as the field is initialized by the framework. - if (!(requestObject.Proxy is WebProxy)) - { - var webProxyField = requestObject.Proxy.GetType().GetField("webProxy", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public); - if (webProxyField != null) - actualProxy = webProxyField.GetValue(requestObject.Proxy) as WebProxy; - } - else - { - actualProxy = requestObject.Proxy as WebProxy; - } - hasProxyServer = (actualProxy.Address != null); - } - else - { - hasProxyServer = false; - } - - return hasProxyServer; - } + ///// + ///// Gets the WinHTTP proxy. + ///// + ///// + ///// Normally, C# picks up these proxy settings by default, but when run under the SYSTEM account, it does not. + ///// + ///// + //private static System.Net.WebProxy GetWinhttpProxy() + //{ + // string[] proxyServerNames = null; + // string primaryProxyServer = null; + // string[] bypassHostnames = null; + // bool enableLocalBypass = false; + // System.Net.WebProxy winhttpProxy = null; + + // // Has a proxy been configured? + // // No. Is a WinHTTP proxy set? + // int internetHandle = WinHttpOpen("DuoTest", WinHttp_Access_Type.WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, null, null, 0); + // if (internetHandle != 0) + // { + // // Yes, use it. This is normal when run under the SYSTEM account and a WinHTTP proxy is configured. When run as a normal user, + // // the Proxy property will already be configured correctly. To resolve this for SYSTEM, manually read proxy settings and configure. + // var proxyInfo = new WINHTTP_PROXY_INFO(); + // WinHttpGetDefaultProxyConfiguration(proxyInfo); + // if (proxyInfo.lpszProxy != null) + // { + // if (proxyInfo.lpszProxy != null) + // { + // proxyServerNames = proxyInfo.lpszProxy.Split(new char[] { ' ', '\t', ';' }); + // if ((proxyServerNames == null) || (proxyServerNames.Length == 0)) + // primaryProxyServer = proxyInfo.lpszProxy; + // else + // primaryProxyServer = proxyServerNames[0]; + // } + // if (proxyInfo.lpszProxyBypass != null) + // { + // bypassHostnames = proxyInfo.lpszProxyBypass.Split(new char[] { ' ', '\t', ';' }); + // if ((bypassHostnames == null) || (bypassHostnames.Length == 0)) + // bypassHostnames = new string[] { proxyInfo.lpszProxyBypass }; + // if (bypassHostnames != null) + // enableLocalBypass = bypassHostnames.Contains("local", StringComparer.InvariantCultureIgnoreCase); + // } + // if (primaryProxyServer != null) + // winhttpProxy = new System.Net.WebProxy(proxyServerNames[0], enableLocalBypass, bypassHostnames); + // } + // WinHttpCloseHandle(internetHandle); + // internetHandle = 0; + // } + // else + // { + // throw new Exception(String.Format("WinHttp init failed {0}", System.Runtime.InteropServices.Marshal.GetLastWin32Error())); + // } + + // return winhttpProxy; + //} + + ///// + ///// Determines if the specified web request is using a proxy server. + ///// + ///// + ///// If no proxy is set, the Proxy member is typically non-null and set to an object type that includes but hides IWebProxy with no address, + ///// so it cannot be inspected. Resolving this requires reflection to extract the hidden webProxy object and check it's Address member. + ///// + ///// Request to check + ///// TRUE if a proxy is in use, else FALSE + //public static bool HasProxyServer(HttpWebRequest requestObject) + //{ + // WebProxy actualProxy = null; + // bool hasProxyServer = false; + + // if (requestObject.Proxy != null) + // { + // // WebProxy is described as the base class for IWebProxy, so we should always see this type as the field is initialized by the framework. + // if (!(requestObject.Proxy is WebProxy)) + // { + // var webProxyField = requestObject.Proxy.GetType().GetField("webProxy", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public); + // if (webProxyField != null) + // actualProxy = webProxyField.GetValue(requestObject.Proxy) as WebProxy; + // } + // else + // { + // actualProxy = requestObject.Proxy as WebProxy; + // } + // hasProxyServer = (actualProxy.Address != null); + // } + // else + // { + // hasProxyServer = false; + // } + + // return hasProxyServer; + //} #endregion Private Methods #region Private DllImport diff --git a/DuoApi/DuoApi.csproj b/DuoApi/DuoApi.csproj new file mode 100644 index 0000000..39f292e --- /dev/null +++ b/DuoApi/DuoApi.csproj @@ -0,0 +1,14 @@ + + + + netstandard2.1 + enable + True + + + + + + + + diff --git a/DuoApi/DuoApiResponseStatus.cs b/DuoApi/DuoApiResponseStatus.cs new file mode 100644 index 0000000..d1bd0d8 --- /dev/null +++ b/DuoApi/DuoApiResponseStatus.cs @@ -0,0 +1,7 @@ +namespace Duo +{ + public enum DuoApiResponseStatus { + Fail = 0, + Ok = 1 + } +} diff --git a/DuoApi/PagingInfo.cs b/DuoApi/PagingInfo.cs new file mode 100644 index 0000000..bb07c75 --- /dev/null +++ b/DuoApi/PagingInfo.cs @@ -0,0 +1,12 @@ +namespace Duo +{ + /// + /// Information of dataset paging + /// + public struct PagingInfo + { + public int total_objects { get; set; } + public int? next_offset { get; set; } + public int prev_offset { get; set; } + } +} diff --git a/duo_api_csharp.sln b/duo_api_csharp.sln index 743ca5f..596cdaf 100644 --- a/duo_api_csharp.sln +++ b/duo_api_csharp.sln @@ -2,17 +2,17 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.32126.317 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "duo_api_csharp", "duo_api_csharp\duo_api_csharp.csproj", "{6E96C9D9-0825-4D26-83C7-8A62180F8FB9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DuoApiTest", "test\DuoApiTest.csproj", "{6B97B9FB-E553-494C-BD50-4BF7DB5C2184}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E739E3FE-D923-480A-9B01-3B2A623067E3}" ProjectSection(SolutionItems) = preProject LICENSE = LICENSE README.md = README.md EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples", "Examples\Examples.csproj", "{C089A10B-646D-407E-A2B8-848C6C522B13}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DuoApi", "DuoApi\DuoApi.csproj", "{83919561-1430-4928-B231-02A77D8B9AD3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DuoApi.Tests", "DuoApi.Tests\DuoApi.Tests.csproj", "{A0508DF1-F0F6-4A5E-B1F8-015D8C37E165}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DuoApi.Examples", "DuoApi.Examples\DuoApi.Examples.csproj", "{834D5CD4-19F2-4434-A35C-9D6C3FBCED1B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -20,18 +20,18 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6E96C9D9-0825-4D26-83C7-8A62180F8FB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6E96C9D9-0825-4D26-83C7-8A62180F8FB9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6E96C9D9-0825-4D26-83C7-8A62180F8FB9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6E96C9D9-0825-4D26-83C7-8A62180F8FB9}.Release|Any CPU.Build.0 = Release|Any CPU - {6B97B9FB-E553-494C-BD50-4BF7DB5C2184}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6B97B9FB-E553-494C-BD50-4BF7DB5C2184}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6B97B9FB-E553-494C-BD50-4BF7DB5C2184}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6B97B9FB-E553-494C-BD50-4BF7DB5C2184}.Release|Any CPU.Build.0 = Release|Any CPU - {C089A10B-646D-407E-A2B8-848C6C522B13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C089A10B-646D-407E-A2B8-848C6C522B13}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C089A10B-646D-407E-A2B8-848C6C522B13}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C089A10B-646D-407E-A2B8-848C6C522B13}.Release|Any CPU.Build.0 = Release|Any CPU + {83919561-1430-4928-B231-02A77D8B9AD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {83919561-1430-4928-B231-02A77D8B9AD3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {83919561-1430-4928-B231-02A77D8B9AD3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {83919561-1430-4928-B231-02A77D8B9AD3}.Release|Any CPU.Build.0 = Release|Any CPU + {A0508DF1-F0F6-4A5E-B1F8-015D8C37E165}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0508DF1-F0F6-4A5E-B1F8-015D8C37E165}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0508DF1-F0F6-4A5E-B1F8-015D8C37E165}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0508DF1-F0F6-4A5E-B1F8-015D8C37E165}.Release|Any CPU.Build.0 = Release|Any CPU + {834D5CD4-19F2-4434-A35C-9D6C3FBCED1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {834D5CD4-19F2-4434-A35C-9D6C3FBCED1B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {834D5CD4-19F2-4434-A35C-9D6C3FBCED1B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {834D5CD4-19F2-4434-A35C-9D6C3FBCED1B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/duo_api_csharp/duo_api_csharp.csproj b/duo_api_csharp/duo_api_csharp.csproj deleted file mode 100644 index 88a1660..0000000 --- a/duo_api_csharp/duo_api_csharp.csproj +++ /dev/null @@ -1,54 +0,0 @@ - - - Debug - AnyCPU - {6E96C9D9-0825-4D26-83C7-8A62180F8FB9} - Library - false - ClassLibrary - v4.8 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - duo_api_csharp - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/App.config b/examples/App.config deleted file mode 100644 index 193aecc..0000000 --- a/examples/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/examples/Examples.csproj b/examples/Examples.csproj deleted file mode 100644 index 35bc283..0000000 --- a/examples/Examples.csproj +++ /dev/null @@ -1,59 +0,0 @@ - - - - - Debug - AnyCPU - {C089A10B-646D-407E-A2B8-848C6C522B13} - Exe - Examples - Examples - v4.8 - 512 - true - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - {6e96c9d9-0825-4d26-83c7-8a62180f8fb9} - duo_api_csharp - - - - \ No newline at end of file diff --git a/examples/Properties/AssemblyInfo.cs b/examples/Properties/AssemblyInfo.cs deleted file mode 100644 index 6a556c3..0000000 --- a/examples/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Examples")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Examples")] -[assembly: AssemblyCopyright("Copyright © 2022")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("c089a10b-646d-407e-a2b8-848c6c522b13")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/test/DuoApiTest.csproj b/test/DuoApiTest.csproj deleted file mode 100644 index 96608cc..0000000 --- a/test/DuoApiTest.csproj +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - Debug - AnyCPU - {6B97B9FB-E553-494C-BD50-4BF7DB5C2184} - Library - Properties - test - test - v4.8 - 512 - - - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - ..\packages\Microsoft.Bcl.AsyncInterfaces.6.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll - - - - ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll - - - ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll - - - - ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll - - - ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll - - - ..\packages\System.Text.Encodings.Web.6.0.0\lib\net461\System.Text.Encodings.Web.dll - - - ..\packages\System.Text.Json.6.0.2\lib\net461\System.Text.Json.dll - - - ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll - - - ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll - - - - - - - ..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll - - - ..\packages\xunit.assert.2.4.1\lib\netstandard1.1\xunit.assert.dll - - - ..\packages\xunit.extensibility.core.2.4.1\lib\net452\xunit.core.dll - - - ..\packages\xunit.extensibility.execution.2.4.1\lib\net452\xunit.execution.desktop.dll - - - - - - - - - - - - - - - - - - {6e96c9d9-0825-4d26-83c7-8a62180f8fb9} - duo_api_csharp - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - \ No newline at end of file diff --git a/test/Makefile b/test/Makefile deleted file mode 100644 index 4d6e7b5..0000000 --- a/test/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -DLLS := SigningTest.dll QueryParamsTest.dll - -test: $(DLLS) - nunit-console $^ - -%.dll: %.cs ../Duo.cs - dmcs /target:library -r:System.Web.Services -r:System.Web.Extensions -r:System.Web -r:nunit.framework.dll $< ../Duo.cs -out:$@ - -clean: - rm -f $(DLLS) *~ TestResult.xml diff --git a/test/Properties/AssemblyInfo.cs b/test/Properties/AssemblyInfo.cs deleted file mode 100644 index 80f68e1..0000000 --- a/test/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("DuoApiTest")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Cisco Systems")] -[assembly: AssemblyProduct("DuoApiTest")] -[assembly: AssemblyCopyright("Copyright © 2022")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("ee1b0852-a526-4b1f-bbda-178c88e8e2fa")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/test/app.config b/test/app.config deleted file mode 100644 index 1696df6..0000000 --- a/test/app.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/test/packages.config b/test/packages.config deleted file mode 100644 index 9462602..0000000 --- a/test/packages.config +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file