Move Saxonite’s projects into a dedicated `Workspace` folder and align the solution with .NET 10 and the current Common workspace. Update encryption integration, test project structure and coverage, and repository guidance and upgrade notes. - Relocate application and library projects while retaining Git rename history. - Split tests into Admin, Online, and Shared projects; add representative behavioral and serialization tests. - Update Common integration, application version, and repository documentation. Application version: 1.3.0 Reviewed-on: #1 Co-authored-by: andy <andy@sarand.com>
240 lines
10 KiB
C#
240 lines
10 KiB
C#
using NPOI.SS.Formula.Functions;
|
|
using Sarand.Net.Standard.Base.App;
|
|
using Sarand.Net.Standard.Base.Bus;
|
|
using Sarand.Net.Standard.Base.Core;
|
|
using Sarand.Net.Standard.Base.Dbas;
|
|
using Sarand.Net.Standard.Base.Helpers;
|
|
using Sarand.Net.Standard.Base.IO;
|
|
using Sarand.Net.Standard.Base.Net;
|
|
using Sarand.Net.Standard.Base.Utils;
|
|
using Saxonite.Net.Core.Web.Base.App;
|
|
using Saxonite.Net.Core.Web.Base.Helpers;
|
|
using Saxonite.Net.Core.Web.Base.Procs;
|
|
using Saxonite.Net.Standard.Base.App;
|
|
using Saxonite.Net.Standard.Base.Bus.Reference;
|
|
using Saxonite.Net.Standard.Base.Consoles;
|
|
using Saxonite.Net.Standard.Base.Helpers;
|
|
using Saxonite.Web.Api.Consoles;
|
|
using System.Net;
|
|
using System.Net.Security;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
using System.Text.RegularExpressions;
|
|
using static Saxonite.Net.Core.Web.Base.App.SaxAppConfig;
|
|
|
|
namespace Saxonite.Web.Api.App
|
|
{
|
|
//=======================================================================
|
|
public class SaxApplication_Api : SaxApplication_Web
|
|
{
|
|
//-------------------------------------------------------------------
|
|
// Data members.
|
|
private Dictionary<String, SaxAppConfig> appConfigs = new Dictionary<string, SaxAppConfig>();
|
|
private Dictionary<String, SaxEmailConfig> emailConfigs = new Dictionary<string, SaxEmailConfig>();
|
|
// Session contexts.
|
|
private class SessionContextData_Api : SessionContextData_Web
|
|
{
|
|
public SessionContextData_Api(SaxSessionContext_Web sessionContext) : base(sessionContext) { }
|
|
}
|
|
private readonly Dictionary<int, SessionContextData_Api> sessionContexts = new Dictionary<int, SessionContextData_Api>();
|
|
|
|
//-------------------------------------------------------------------
|
|
// Construction.
|
|
public SaxApplication_Api(WebApplication app) : base(Sax.Application.Api)
|
|
{
|
|
InitialiseTemporaryLoggingFolder();
|
|
try
|
|
{
|
|
AppInstance = this;
|
|
ConsoleHelper_Api = new SaxConsoleHelper_Api(this);
|
|
|
|
// Application configuration.
|
|
InitEnvironment(app.Environment, "Sax-Web-Api");
|
|
LoadConfiguration();
|
|
|
|
// Test API calls.
|
|
Timer? timer = null;
|
|
timer =
|
|
new Timer((obj) =>
|
|
{
|
|
new Thread(new ThreadStart(() => { TestApi(); })).Start();
|
|
if (timer != null) timer.Dispose();
|
|
},
|
|
null, 1000, Timeout.Infinite);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
SaLogger.Error($"GetType().Name.CTR {ExceptionUtil.GetErrorStateMessage(exc)}");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Properties.
|
|
public static SaxApplication_Api? AppInstance { get; private set; }
|
|
public override SaxConsoleHelper ConsoleHelper { get { return ConsoleHelper_Api; } }
|
|
public SaxConsoleHelper_Api ConsoleHelper_Api { get; private set; }
|
|
// Database.
|
|
public override ISacsDatabase? GetDatabase(SaxSessionContext sessionContext, Sax.Database databaseType)
|
|
{
|
|
return sessionContexts.GetValue(sessionContext.Index, null)?.Databases.GetValue(databaseType, null);
|
|
}
|
|
// Configuration.
|
|
public override SaxAppConfig AppConfig { get { return appConfigs.Values.ToList().getConfigForApplication(); } }
|
|
public override SaxEmailConfig EmailConfig { get { return emailConfigs.Values.ToList().getConfigForSession(AppConfig); } }
|
|
public override String SessionCookieName { get { return Sax.Config.Api.Session.Cookie.Name; } }
|
|
// Startup messages - for debugging. See Admin.Views._Layout.
|
|
public List<String> Messages { get; } = new List<String>();
|
|
|
|
//-------------------------------------------------------------------
|
|
// Initialisation.
|
|
|
|
private void LoadConfiguration()
|
|
{
|
|
try
|
|
{
|
|
// Application configuration.
|
|
appConfigs = SaxAppConfigHelper.ExtractAppConfigs(SaxConfiguration.GetSection("AppConfigs"));
|
|
emailConfigs = SaxEmailConfigHelper.ExtractEmailConfigs(SaxConfiguration.GetSection("EmailConfigs"));
|
|
|
|
// Ensure root log folder ends with 'Api' folder.
|
|
LoggingRootFolder = AppConfig.Logging.RootFolder;
|
|
if (!StringUtil.IsBlank(LoggingRootFolder) && !Regex.IsMatch(LoggingRootFolder, "[\\\\/]Api$", RegexOptions.IgnoreCase))
|
|
LoggingRootFolder = StringUtil.CombineFilePath(LoggingRootFolder, "Api");
|
|
|
|
// Application instance.
|
|
if (AppConfig.Instance.EqualsCI("Dev")) instanceType = Sax.InstanceType.Dev;
|
|
else if (AppConfig.Instance.ContainsCI("Q")) instanceType = Sax.InstanceType.QC;
|
|
else if (AppConfig.Instance.ContainsCI("UAT")) instanceType = Sax.InstanceType.UAT;
|
|
else if (AppConfig.Instance.EqualsCI("PreProd")) instanceType = Sax.InstanceType.UAT;
|
|
|
|
// Initialise hard-coded logging path.
|
|
if (StringUtil.IsBlank(LoggingRootFolder))
|
|
{
|
|
if (SaxSystem.ComputerName.EqualsCI("WIN-BPCLM1QUOMT"))
|
|
LoggingRootFolder = @"D:\Saxonite\Logs\" + (Development ? "Dev" : "Test");
|
|
}
|
|
if (DirectoryUtil.DirectoryExists(LoggingRootFolder))
|
|
SaLogger.LogFolder = LoggingRootFolder;
|
|
LogApplicationStart(SysUtil.Fn);
|
|
|
|
// Session context - only one context available/necessary (for now).
|
|
SessionContextData_Api sessionContextData = new SessionContextData_Api(new SaxSessionContext_Web(100, ApplicationType));
|
|
ConfigureDatabaseConnection(sessionContextData, Sax.Database.Core);
|
|
ConfigureDatabaseConnection(sessionContextData, Sax.Database.Reference);
|
|
ConfigureDatabaseConnection(sessionContextData, Sax.Database.Support);
|
|
sessionContexts.Add(sessionContextData.SessionContext.Index, sessionContextData);
|
|
SessionContext = sessionContextData.SessionContext;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
SaLogger.Warn(SysUtil.Fn + " " + ExceptionUtil.GetLogMessage(exc, "loading application configuration", 8));
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
private void TestApi()
|
|
{
|
|
#pragma warning disable CS0162
|
|
// Allows you to bypass "AuthenticationException: The remote certificate is invalid according to the validation procedure." error. Don't to do this in production code...
|
|
//ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };
|
|
|
|
if (false)
|
|
{
|
|
CancellationToken cancelToken = new CancellationToken();
|
|
SacsHttpClientHelper.RequestData request = new SacsHttpClientHelper.RequestData(cancelToken);
|
|
request.UriBuilder.ConfigureSslUriBuilder("api.sportierre.com", "System/Version");
|
|
request.ContentHeaders.Add(SacsHttpClientHelper.HeaderName_ContentType, "application/json");
|
|
request.PostData = "{}";
|
|
//request.ForcePost = true;
|
|
request.Debug = true;
|
|
SacsHttpClientHelper.ResponseData response = SacsHttpClientHelper.DoRequest(request).Result;
|
|
String responseData = response.Data;
|
|
}
|
|
|
|
if (false)
|
|
{
|
|
CancellationToken cancelToken = new CancellationToken();
|
|
SacsHttpRequestData request = new SacsHttpRequestData(cancelToken);
|
|
request.Url = "https://api.sportierre.com/System/Version";
|
|
request.PostData = "{}";
|
|
request.ContentHeaders.Add(SacsHttpClient.HeaderName_ContentType, "application/json");
|
|
//request.ForcePost = true;
|
|
request.Debug = true;
|
|
SacsHttpResponseData response = SacsHttpClient.DoRequest(request).Result;
|
|
String data = response.Data;
|
|
}
|
|
|
|
DbUpdateInfo dbUpdateInfo = new DbUpdateInfo(new SysId(), "ApiApp", SacsSystem.ComputerName);
|
|
|
|
if (false)
|
|
{
|
|
// Cleanse USGA Courses and Markers.
|
|
SaxGolfUsgaDataLookup.Config courseLookupConfig = new SaxGolfUsgaDataLookup.Config(SessionContext, dbUpdateInfo);
|
|
courseLookupConfig.Tasks.Add(SaxGolfUsgaDataLookup.Task.CleanseCourses);
|
|
courseLookupConfig.Tasks.Add(SaxGolfUsgaDataLookup.Task.CleanseMarkers);
|
|
SaxGolfUsgaDataLookup courseLookup = new SaxGolfUsgaDataLookup(courseLookupConfig);
|
|
courseLookup.RunAsync();
|
|
}
|
|
|
|
if (false)
|
|
{
|
|
// USGA Countries.
|
|
SaxGolfUsgaDataLookup.Config courseLookupConfig = new SaxGolfUsgaDataLookup.Config(SessionContext, dbUpdateInfo);
|
|
SaxGolfUsgaDataLookup courseLookup = new SaxGolfUsgaDataLookup(courseLookupConfig);
|
|
List<SaxGolfUsgaDataLookup.CountryData> countries = courseLookup.LookupUsgaCountries();
|
|
SaLogger.Warn($"{SysUtil.Fn} Country lookup - found: {countries.Count}");
|
|
if (courseLookup.HasErrorMessage())
|
|
SaLogger.Warn($"{SysUtil.Fn} Country lookup error: {courseLookup.GetErrorMessage()}");
|
|
foreach (SaxGolfUsgaDataLookup.CountryData country in countries)
|
|
{
|
|
}
|
|
}
|
|
|
|
if (false)
|
|
{
|
|
// USGA Provinces.
|
|
SaxGolfUsgaDataLookup.Config courseLookupConfig = new SaxGolfUsgaDataLookup.Config(SessionContext, dbUpdateInfo);
|
|
SaxGolfUsgaDataLookup courseLookup = new SaxGolfUsgaDataLookup(courseLookupConfig);
|
|
List<SaxGolfUsgaDataLookup.ProvinceData> provinces = courseLookup.LookupUsgaProvincesForCountry("AUS");
|
|
SaLogger.Warn($"{SysUtil.Fn} Province lookup - found: {provinces.Count}");
|
|
if (courseLookup.HasErrorMessage())
|
|
SaLogger.Warn($"{SysUtil.Fn} Province lookup error: {courseLookup.GetErrorMessage()}");
|
|
foreach (SaxGolfUsgaDataLookup.ProvinceData province in provinces)
|
|
{
|
|
}
|
|
}
|
|
|
|
if (false)
|
|
{
|
|
// USGA Courses.
|
|
SaxGolfUsgaDataLookup.Config courseLookupConfig = new SaxGolfUsgaDataLookup.Config(SessionContext, dbUpdateInfo);
|
|
SaxGolfUsgaDataLookup courseLookup = new SaxGolfUsgaDataLookup(courseLookupConfig);
|
|
List<SaxGolfUsgaDataLookup.CourseData> courses = courseLookup.LookupUsgaCoursesForCountryAndProvince("AUS", "AU-VIC");
|
|
SaLogger.Warn($"{SysUtil.Fn} Course lookup - found: {courses.Count}");
|
|
if (courseLookup.HasErrorMessage())
|
|
SaLogger.Warn($"{SysUtil.Fn} Course lookup error: {courseLookup.GetErrorMessage()}");
|
|
foreach (SaxGolfUsgaDataLookup.CourseData course in courses)
|
|
{
|
|
}
|
|
}
|
|
|
|
if (false)
|
|
{
|
|
// USGA Markers.
|
|
SaxGolfUsgaDataLookup.Config courseLookupConfig = new SaxGolfUsgaDataLookup.Config(SessionContext, dbUpdateInfo);
|
|
SaxGolfUsgaDataLookup courseLookup = new SaxGolfUsgaDataLookup(courseLookupConfig);
|
|
List<SaxGolfUsgaDataLookup.MarkerData> markers = courseLookup.LookupUsgaMarkersForCourse(new SysId(18226));
|
|
SaLogger.Warn($"{SysUtil.Fn} Marker lookup - found: {markers.Count}");
|
|
if (courseLookup.HasErrorMessage())
|
|
SaLogger.Warn($"{SysUtil.Fn} Marker lookup error: {courseLookup.GetErrorMessage()}");
|
|
foreach (SaxGolfUsgaDataLookup.MarkerData marker in markers)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
//=======================================================================
|
|
}
|