1.2.11.4
This commit is contained in:
@@ -31,7 +31,7 @@ namespace Saxonite.Net.Core.Web.Admin.App
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private bool generateDatabaseDefinitions = false;
|
||||
private bool generateDatabaseDefinitions = true;
|
||||
private bool populateRegions = false;
|
||||
private Dictionary<String, SaxAppConfig> appConfigs = new Dictionary<string, SaxAppConfig>();
|
||||
private Dictionary<String, SaxEmailConfig> emailConfigs = new Dictionary<string, SaxEmailConfig>();
|
||||
@@ -44,7 +44,7 @@ namespace Saxonite.Net.Core.Web.Admin.App
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxApplication_Admin(IConfiguration configuration)
|
||||
public SaxApplication_Admin(IConfiguration configuration) : base(Sax.Application.Admin)
|
||||
{
|
||||
InitialiseTemporaryLoggingFolder();
|
||||
try
|
||||
@@ -100,31 +100,16 @@ namespace Saxonite.Net.Core.Web.Admin.App
|
||||
/// <summary>Initialise environment - from internal (above) or unit tests.</summary>
|
||||
protected void InitEnvironment(IWebHostEnvironment env)
|
||||
{
|
||||
Development = env.IsDevelopment();
|
||||
environmentName = env.EnvironmentName;
|
||||
SaLogger.LogFilenamePrefix = "Sax-Web-Adm";
|
||||
SaLogger.IncludeHostInFileMessage = false;
|
||||
SaLogger.IncludeUserInFileMessage = false;
|
||||
base.InitEnvironment(env, "Sax-Web-Adm");
|
||||
|
||||
try
|
||||
{
|
||||
// Load server configuration.
|
||||
var builder = new ConfigurationBuilder()
|
||||
.SetBasePath(env.ContentRootPath)
|
||||
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
|
||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: false)
|
||||
.AddJsonFile($"appsettings.machine.{SaxSystem.ComputerName}.json", optional: false, reloadOnChange: false)
|
||||
.AddEnvironmentVariables();
|
||||
SaxConfiguration = builder.Build();
|
||||
|
||||
//Messages.Add($"Host: {SaxSystem.ComputerName}");
|
||||
//Messages.Add($"Config file: appsettings.machine.{SaxSystem.ComputerName}.json");
|
||||
|
||||
// Application configuration.
|
||||
appConfigs = SaxAppConfigHelper.ExtractAppConfigs(SaxConfiguration.GetSection("AppConfigs"));
|
||||
emailConfigs = SaxEmailConfigHelper.ExtractEmailConfigs(SaxConfiguration.GetSection("EmailConfigs"));
|
||||
|
||||
// Ensure root log folder ends with 'Admin' folder.
|
||||
LoggingRootFolder = AppConfig.Logging.RootFolder;
|
||||
// Ensure root log folder ends with Admin folder.
|
||||
if (!StringUtil.IsBlank(LoggingRootFolder) && !Regex.IsMatch(LoggingRootFolder, "[\\\\/]Admin$", RegexOptions.IgnoreCase))
|
||||
LoggingRootFolder = StringUtil.CombineFilePath(LoggingRootFolder, "Admin");
|
||||
|
||||
@@ -150,8 +135,9 @@ namespace Saxonite.Net.Core.Web.Admin.App
|
||||
//Messages.Add($"DbConnection: {coreDatabase.ConnectionString}");
|
||||
|
||||
// Session context - only one context available/necessary (for now).
|
||||
SessionContextData_Admin sessionContextData = new SessionContextData_Admin(new SaxSessionContext_Web(100, Sax.Application.Admin));
|
||||
SessionContextData_Admin sessionContextData = new SessionContextData_Admin(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;
|
||||
@@ -183,6 +169,11 @@ namespace Saxonite.Net.Core.Web.Admin.App
|
||||
//SaUpdateLogDbDfnGenerator.Generate(database.ConnectionString);
|
||||
}
|
||||
|
||||
// Reference database.
|
||||
ISacsDatabase referenceDatabase = GetDatabase(sessionContext, Sax.Database.Reference);
|
||||
if (referenceDatabase != null && !StringUtil.IsEmpty(referenceDatabase.ConnectionString))
|
||||
SaxDbDfnGenerator.Generate(Sax.Database.Reference, referenceDatabase.ConnectionString);
|
||||
|
||||
// Support database.
|
||||
ISacsDatabase supportDatabase = GetDatabase(sessionContext, Sax.Database.Support);
|
||||
if (supportDatabase != null && !StringUtil.IsEmpty(supportDatabase.ConnectionString))
|
||||
|
||||
@@ -59,6 +59,31 @@ namespace Saxonite.Net.Core.Web.Admin.App
|
||||
}
|
||||
public FilterData Filter { get; private set; } = new FilterData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// System.
|
||||
public class SystemData
|
||||
{
|
||||
// Databases.
|
||||
public class DatabaseData
|
||||
{
|
||||
}
|
||||
public DatabaseData Database { get; private set; } = new DatabaseData();
|
||||
|
||||
// Logs.
|
||||
public class LogsData
|
||||
{
|
||||
public class FilterData
|
||||
{
|
||||
public String Folder { get; set; }
|
||||
public String Year { get; set; }
|
||||
public String Month { get; set; }
|
||||
}
|
||||
public FilterData Filter { get; private set; } = new FilterData();
|
||||
}
|
||||
public LogsData Logs { get; private set; } = new LogsData();
|
||||
}
|
||||
public SystemData System { get; private set; } = new SystemData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Online application encryption IV value - for consistent encryption during session.
|
||||
public String Base64IV_AdminApp { get; private set; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(SaxController_Admin.Base64Key_AdminApp);
|
||||
|
||||
@@ -50,6 +50,9 @@ namespace Saxonite.Net.Core.Web.Admin.App
|
||||
options.CheckConsentNeeded = context => true;
|
||||
options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.None;
|
||||
});
|
||||
|
||||
// Hosted (schedule) services.
|
||||
services.AddHostedService<SaxHostedServiceConsole_Admin>();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
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.Tasks;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Net.Core.Web.Admin.App;
|
||||
using Saxonite.Net.Core.Web.Base.Consoles;
|
||||
using Saxonite.Net.Core.Web.Base.Procs;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Consoles
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxHostedServiceConsole_Admin : SaxHostedServiceConsole_Web
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
private enum ProcessType { Unknown = 0, GolfUsgaReferenceLookup }
|
||||
|
||||
/// <summary>
|
||||
/// Process tracking data to control when process is run.
|
||||
/// </summary>
|
||||
private class ProcessControlData
|
||||
{
|
||||
// Construction.
|
||||
public ProcessControlData(ProcessType processType, TimeSpan minTimeBetweenRuns)
|
||||
{
|
||||
this.ProcessType = processType;
|
||||
this.MinTimeBetweenRuns = minTimeBetweenRuns;
|
||||
ResetRunTime();
|
||||
}
|
||||
// Properties.
|
||||
public ProcessType ProcessType { get; }
|
||||
public TimeSpan MinTimeBetweenRuns { get; }
|
||||
public DateTime LastRunAt { get; private set; }
|
||||
// Utilities.
|
||||
public bool ReadyToRun()
|
||||
{
|
||||
//SaLogger.Info($"{SysUtil.Fn} Process: {ProcessType}. Secs since last run: {(DateTime.Now - LastRunAt).TotalSeconds}. Seconds between runs: {MinTimeBetweenRuns.TotalSeconds}.");
|
||||
return (DateTime.Now - LastRunAt) > MinTimeBetweenRuns;
|
||||
}
|
||||
public void ResetRunTime()
|
||||
{
|
||||
LastRunAt = DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private Dictionary<ProcessType, ProcessControlData> processes { get; } = new Dictionary<ProcessType, ProcessControlData>();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxHostedServiceConsole_Admin()
|
||||
{
|
||||
InitialiseProcesses();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Clean-up.
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Periodic processing to execute application processes as required.
|
||||
/// <para>- See parent class for timer logic.</para>
|
||||
/// </summary>
|
||||
protected override void DoWork(object state)
|
||||
{
|
||||
//SaLogger.Info($"{SysUtil.Fn} Timed Background Service is working. State: {state}");
|
||||
SaxSessionContext sessionContext = SaxApplication_Admin.AppInstance.SessionContext;
|
||||
DbUpdateInfo dbUpdateInfo = new DbUpdateInfo(new SysId(), "AdminScheduled", SacsSystem.ComputerName);
|
||||
|
||||
// Check for cancellation.
|
||||
var token = ProcessTaskData.CancellationToken;
|
||||
if (token.IsCancellationRequested) return;
|
||||
|
||||
// Identify processes that are ready to run.
|
||||
foreach (ProcessControlData process in processes.Where(item => item.Value.ReadyToRun()).Select(item => item.Value))
|
||||
{
|
||||
//SaLogger.Info($"{SysUtil.Fn} Executing process: {process.ProcessType}.");
|
||||
process.ResetRunTime();
|
||||
switch (process.ProcessType)
|
||||
{
|
||||
case ProcessType.GolfUsgaReferenceLookup:
|
||||
// Run on separate thread.
|
||||
Task task = new Task(() =>
|
||||
{
|
||||
SaxGolfUsgaDataLookup.ExecuteScheduledUsgaDataLookup(sessionContext, dbUpdateInfo, ProcessTaskData);
|
||||
}, ProcessTaskData.CancellationToken);
|
||||
task.Start();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Initialisation.
|
||||
|
||||
private void InitialiseProcesses()
|
||||
{
|
||||
if (Sax.Config.Admin.Processes.Scheduled.UsgaGolfDataLookup.Enabled)
|
||||
InitialiseProcess(ProcessType.GolfUsgaReferenceLookup, TimeSpan.FromMinutes(MathUtil.Constrain(Sax.Config.Admin.Processes.Scheduled.UsgaGolfDataLookup.MinsBetweenExecution, 2, 120)));
|
||||
}
|
||||
|
||||
private void InitialiseProcess(ProcessType processType, TimeSpan minTimeBetweenRuns)
|
||||
{
|
||||
if (!processes.ContainsKey(processType))
|
||||
processes[processType] = new ProcessControlData(processType, minTimeBetweenRuns);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -118,7 +118,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.process.in.progress"]));
|
||||
|
||||
// Create the upload process.
|
||||
SaxOrganisationUploader.Config processConfig = new SaxOrganisationUploader.Config(SessionContext, model.OrganisationDataFile[0]);
|
||||
SaxOrganisationUploader.Config processConfig = new SaxOrganisationUploader.Config(SessionContext, DbUpdateInfo, model.OrganisationDataFile[0]);
|
||||
processConfig.SheetNameOrNumber = model.SheetNameOrNumber;
|
||||
processConfig.HeaderRowPos = (uint)StringUtil.ToInt(model.HeaderRow);
|
||||
processConfig.FirstDataRowPos = (uint)StringUtil.ToInt(model.FirstDataRow);
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
return BadRequest();
|
||||
|
||||
// Export data.
|
||||
SaxOrganisationExporter.Config exporterConfig = new SaxOrganisationExporter.Config(SessionContext, GetOrganisationListFilter(model, AccountMgr));
|
||||
SaxOrganisationExporter.Config exporterConfig = new SaxOrganisationExporter.Config(SessionContext, DbUpdateInfo, GetOrganisationListFilter(model, AccountMgr));
|
||||
exporterConfig.Format = SaxOrganisationExporter.ExportFormat.Excel_Open;
|
||||
exporterConfig.IncludeId = StringUtil.ToBool(model.IncludeId);
|
||||
SaxOrganisationExporter exporter = new SaxOrganisationExporter(exporterConfig);
|
||||
|
||||
@@ -188,7 +188,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
String keepLoggedInCookieValue = GenerateKeepLoggedInCookieValue();
|
||||
int cookieExpiresDays = Math.Max(Sax.Config.Security.SignIn.KeepLoggedIn.CookieExpiresDays_Min, Math.Min(Sax.Config.Security.SignIn.KeepLoggedIn.CookieExpiresDays_Max, AppConfig.Security.SignIn.KeepLoggedIn.CookieExpiresDays));
|
||||
SetResponseCookie(KeepLoggedIn.CookieName, keepLoggedInCookieValue, DateTime.Now.AddDays(cookieExpiresDays), true);
|
||||
SaLogger.Info(this.GetType().Name + ".SetKeepLoggedInCookie 'Keep Logged In' cookie set. Value: " + keepLoggedInCookieValue);
|
||||
SaLogger.Debug(this.GetType().Name + ".SetKeepLoggedInCookie 'Keep Logged In' cookie set. Value: " + keepLoggedInCookieValue);
|
||||
}
|
||||
|
||||
/// <summary>Set the 'Keep Logged In' response cookie to expired with no data.</summary>
|
||||
|
||||
@@ -63,9 +63,9 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsDisposable> disposableItems = new DisposableCollection<SacsDisposable>())
|
||||
{
|
||||
|
||||
// Core Database connection.
|
||||
ISacsDatabase db = Internals.CoreDatabase;
|
||||
// Database connection.
|
||||
Sax.Database databaseInstance = EnumUtil.ParseEnum(StringUtil.EmptyOnNull(model.DatabaseFilter.Instance), Sax.Database.Core);
|
||||
ISacsDatabase db = App.GetDatabase(SessionContext, databaseInstance);
|
||||
|
||||
// Database table row counts.
|
||||
Dictionary<String, int> tableRowCounts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||
@@ -83,7 +83,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
// Core database tables.
|
||||
// Database tables.
|
||||
List<DbDfnTable> tableDfns = db.GetTableDfns();
|
||||
foreach (DbDfnTable tableDfn in tableDfns.OrderBy(item => item.Name))
|
||||
{
|
||||
@@ -149,15 +149,15 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
|
||||
// Database instance.
|
||||
Sax.Database databaseInstance = EnumUtil.ParseEnum(StringUtil.EmptyOnNull(model.DatabaseInstance), Sax.Database.Unknown);
|
||||
Sax.Database databaseInstance = EnumUtil.ParseEnum(StringUtil.EmptyOnNull(model.DatabaseFilter.Instance), Sax.Database.Unknown);
|
||||
if (databaseInstance <= 0)
|
||||
return Json(responseData.SetMessage(messageTitle, "Database instance must be specified"));
|
||||
responseData.Instance = databaseInstance.ToString();
|
||||
|
||||
// Core Database connection.
|
||||
// Database connection.
|
||||
ISacsDatabase db = App.GetDatabase(SessionContext, databaseInstance);
|
||||
if (db == null)
|
||||
return Json(responseData.SetMessage(messageTitle, "Unrecognised database instance specified: " + model.DatabaseInstance));
|
||||
return Json(responseData.SetMessage(messageTitle, "Unrecognised database instance specified: " + model.DatabaseFilter.Instance));
|
||||
|
||||
// Retrieve XML database schema definition.
|
||||
var assembly = typeof(SaxSystem_Dbas).GetTypeInfo().Assembly;
|
||||
@@ -347,8 +347,13 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
if (StringUtil.IsEmpty(model.DatabaseTable.Name))
|
||||
return Json(responseData.SetMessage(messageTitle, "Table name must be supplied."));
|
||||
|
||||
// Core Database connection.
|
||||
ISacsDatabase db = Internals.CoreDatabase;
|
||||
// Database instance.
|
||||
Sax.Database databaseInstance = EnumUtil.ParseEnum(StringUtil.EmptyOnNull(model.DatabaseTable.Instance), Sax.Database.Unknown);
|
||||
if (databaseInstance <= 0)
|
||||
return Json(responseData.SetMessage(messageTitle, "Database instance must be specified"));
|
||||
|
||||
// Database connection.
|
||||
ISacsDatabase db = App.GetDatabase(SessionContext, databaseInstance);
|
||||
|
||||
// Table definition.
|
||||
DbDfnTable tableDfn = db.GetTableDfn(model.DatabaseTable.Name, true);
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
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.Utils;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
@@ -20,24 +24,168 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Database data.
|
||||
private class LogFileData
|
||||
private class LogFolderData
|
||||
{
|
||||
public String Name { get; set; }
|
||||
}
|
||||
private class LogFileData
|
||||
{
|
||||
public String Name { get; set; }
|
||||
public long Size { get; set; }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Database Table List ajax request.
|
||||
// Get Log Folder List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_LogFolderList : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_LogFolderList(SaxModel_Admin model) : base(model) { }
|
||||
// Log file list.
|
||||
public List<LogFolderData> Folders { get; } = new List<LogFolderData>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Retrieve the list of folders under the root folder.
|
||||
/// <para>- These should correspond to applications (admin, api, online etc).</para>
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[Route("System/Ajax/Logs/GetFolderList")]
|
||||
[Route("System/Ajax/Logs/GetFolders")]
|
||||
public IActionResult Ajax_GetLogFolderList(Model_System model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetLogFolderList";
|
||||
String messageTitle = Localiser["system.caption.logs"];
|
||||
AjaxResponse_LogFolderList responseData = new AjaxResponse_LogFolderList(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Identify folders in root log folder.
|
||||
String rootLogFolder = model.LoggingRootFolder;
|
||||
foreach (String folder in Directory.EnumerateDirectories(rootLogFolder))
|
||||
{
|
||||
String folderName = Path.GetFileName(folder);
|
||||
if (folderName.IsMatch("^(Online|Admin|Api)$", RegexOptions.IgnoreCase))
|
||||
responseData.Folders.Add(new LogFolderData() { Name = folderName });
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Log Year Folder List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_LogYearList : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_LogYearList(SaxModel_Admin model) : base(model) { }
|
||||
// Log file list.
|
||||
public List<LogFolderData> Years { get; } = new List<LogFolderData>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Retrieve the list of year folders under the selected folder.
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[Route("System/Ajax/Logs/GetYearList")]
|
||||
[Route("System/Ajax/Logs/GetYears")]
|
||||
public IActionResult Ajax_GetLogYearList(Model_System model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetLogYearList";
|
||||
String messageTitle = Localiser["system.caption.logs"];
|
||||
AjaxResponse_LogYearList responseData = new AjaxResponse_LogYearList(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Store filter properties to session.
|
||||
SessionData_Admin.System.Logs.Filter.Folder = model.LogsFilter.Folder;
|
||||
SessionData_Admin.System.Logs.Filter.Year = "";
|
||||
SessionData_Admin.System.Logs.Filter.Month = "";
|
||||
|
||||
// Identify folders in selected log folder.
|
||||
String logFolder = Path.Combine(model.LoggingRootFolder, model.LogsFilter.Folder);
|
||||
foreach (String folder in Directory.EnumerateDirectories(logFolder))
|
||||
{
|
||||
String folderName = Path.GetFileName(folder);
|
||||
if (folderName.IsMatch("^\\d{4}$"))
|
||||
responseData.Years.Add(new LogFolderData() { Name = folderName });
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Log Month Folder List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_LogMonthList : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_LogMonthList(SaxModel_Admin model) : base(model) { }
|
||||
// Log file list.
|
||||
public List<LogFolderData> Months { get; } = new List<LogFolderData>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Retrieve the list of year folders under the selected folder.
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[Route("System/Ajax/Logs/GetMonthList")]
|
||||
[Route("System/Ajax/Logs/GetMonths")]
|
||||
public IActionResult Ajax_GetLogMonthList(Model_System model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetLogMonthList";
|
||||
String messageTitle = Localiser["system.caption.logs"];
|
||||
AjaxResponse_LogMonthList responseData = new AjaxResponse_LogMonthList(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Store filter properties to session.
|
||||
SessionData_Admin.System.Logs.Filter.Folder = model.LogsFilter.Folder;
|
||||
SessionData_Admin.System.Logs.Filter.Year = model.LogsFilter.Year;
|
||||
SessionData_Admin.System.Logs.Filter.Month = "";
|
||||
//SessionData_Admin.System.Logs.Filter.Month = model.LogsFilter.Month;
|
||||
|
||||
// Identify folders in selected year folder.
|
||||
String logFolder = Path.Combine(model.LoggingRootFolder, model.LogsFilter.Folder, model.LogsFilter.Year);
|
||||
foreach (String folder in Directory.EnumerateDirectories(logFolder))
|
||||
{
|
||||
String folderName = Path.GetFileName(folder);
|
||||
if (folderName.IsMatch("^\\d{6}$"))
|
||||
responseData.Months.Add(new LogFolderData() { Name = folderName });
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Log File List ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_LogFileList : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_LogFileList(SaxModel_Admin model) : base(model) { }
|
||||
// Log file list.
|
||||
public List<LogFileData> Tables { get; } = new List<LogFileData>();
|
||||
public List<LogFileData> Files { get; } = new List<LogFileData>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("System/Ajax/GetLogFileList")]
|
||||
[Route("System/Ajax/Logs/GetFileList")]
|
||||
[Route("System/Ajax/Logs/GetFiles")]
|
||||
public IActionResult Ajax_GetLogFileList(Model_System model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetLogFileList";
|
||||
@@ -48,6 +196,97 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Store filter properties to session.
|
||||
SessionData_Admin.System.Logs.Filter.Folder = model.LogsFilter.Folder;
|
||||
SessionData_Admin.System.Logs.Filter.Year = model.LogsFilter.Year;
|
||||
SessionData_Admin.System.Logs.Filter.Month = model.LogsFilter.Month;
|
||||
|
||||
// Identify folders in selected year folder.
|
||||
String logFolder = Path.Combine(model.LoggingRootFolder, model.LogsFilter.Folder, model.LogsFilter.Year, model.LogsFilter.Month);
|
||||
DirectoryInfo folder = new DirectoryInfo(logFolder);
|
||||
foreach (FileInfo file in folder.EnumerateFiles())
|
||||
{
|
||||
responseData.Files.Add(new LogFileData() { Name = file.Name, Size = file.Length });
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Log File ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_LogFile : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_LogFile(SaxModel_Admin model) : base(model) { }
|
||||
// Log file.
|
||||
public class LogFileData
|
||||
{
|
||||
public String Path { get; set; }
|
||||
public String Name { get; set; }
|
||||
public String Data { get; set; }
|
||||
public String Html { get; set; } = "";
|
||||
}
|
||||
public LogFileData File { get; } = new LogFileData();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("System/Ajax/Logs/GetFile")]
|
||||
[Route("System/Ajax/Logs/GetLogFile")]
|
||||
public IActionResult Ajax_GetLogFile(Model_System model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetLogFile";
|
||||
String messageTitle = Localiser["system.caption.logs"];
|
||||
AjaxResponse_LogFile responseData = new AjaxResponse_LogFile(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Store filter properties to session.
|
||||
SessionData_Admin.System.Logs.Filter.Folder = model.LogsFilter.Folder;
|
||||
SessionData_Admin.System.Logs.Filter.Year = model.LogsFilter.Year;
|
||||
SessionData_Admin.System.Logs.Filter.Month = model.LogsFilter.Month;
|
||||
|
||||
// Identify folders in selected year folder.
|
||||
responseData.File.Path = Path.Combine(model.LoggingRootFolder, model.LogsFilter.Folder, model.LogsFilter.Year, model.LogsFilter.Month, model.LogsFilter.Filename);
|
||||
responseData.File.Name = Path.GetFileName(responseData.File.Path);
|
||||
try
|
||||
{
|
||||
String[] fileLines = System.IO.File.ReadAllLines(responseData.File.Path);
|
||||
responseData.File.Data = String.Join("\n", fileLines);
|
||||
// Construct html data.
|
||||
foreach (var fileLine in fileLines)
|
||||
{
|
||||
String line = fileLine;
|
||||
List<String> classNames = new List<string>();
|
||||
if (fileLine.IsMatch("^\t{2}"))
|
||||
{
|
||||
line = Regex.Replace(fileLine, "^\t+", "");
|
||||
classNames.Add("tab2");
|
||||
}
|
||||
if (fileLine.IsMatch("^\t"))
|
||||
{
|
||||
line = Regex.Replace(fileLine, "^\t", "");
|
||||
classNames.Add("tab");
|
||||
}
|
||||
if (line.IsMatch("\\d{8}:\\d{6}\\s+(error|err)\\s+", RegexOptions.IgnoreCase))
|
||||
classNames.Add("err");
|
||||
else if (line.IsMatch("\\d{8}:\\d{6}\\s+(warn|wrn)\\s+", RegexOptions.IgnoreCase))
|
||||
classNames.Add("wrn");
|
||||
else if (line.IsMatch("\\d{8}:\\d{6}\\s+(info|inf)\\s+", RegexOptions.IgnoreCase))
|
||||
classNames.Add("inf");
|
||||
responseData.File.Html += $"<div class='{String.Join(" ", classNames)}'>" + line + "</div>";
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc, "reading log file", 0)}");
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
|
||||
@@ -68,6 +68,10 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
return RedirectToAction("", "");
|
||||
|
||||
model.AdditionalFiles_JS.Add("js/sax-sys-logs.js");
|
||||
model.LogsFilter.Folder = StringUtil.OnBlank(SessionData_Admin.System.Logs.Filter.Folder, "Admin");
|
||||
model.LogsFilter.Year = StringUtil.OnBlank(SessionData_Admin.System.Logs.Filter.Year, DateTime.Today.ToString("yyyy"));
|
||||
model.LogsFilter.Month = StringUtil.OnBlank(SessionData_Admin.System.Logs.Filter.Month, DateTime.Today.ToString("yyyyMM"));
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
@@ -19,25 +23,43 @@ namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public String DatabaseInstance { get; set; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Database page properties.
|
||||
public class DatabaseFilterData
|
||||
{
|
||||
public String Instance { get; set; }
|
||||
public String Search { get; set; }
|
||||
}
|
||||
public DatabaseFilterData DatabaseFilter { get; } = new DatabaseFilterData();
|
||||
public class DatabaseTableData
|
||||
{
|
||||
public String Instance { get; set; }
|
||||
public String Name { get; set; }
|
||||
}
|
||||
public DatabaseTableData DatabaseTable { get; } = new DatabaseTableData();
|
||||
|
||||
public IEnumerable<SelectListItem> GetDatabases()
|
||||
{
|
||||
List<CodeDesc> items = new List<CodeDesc>();
|
||||
if (SessionData?.ValidUserSession ?? false)
|
||||
{
|
||||
items.Add("Core", Localiser["label.core"]);
|
||||
items.Add("Reference", Localiser["label.reference"]);
|
||||
items.Add("Support", Localiser["label.support"]);
|
||||
}
|
||||
return new SelectList(items, "Code", "Desc");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Logs page properties.
|
||||
public String LoggingRootFolder { get; } = Regex.Replace(SaLogger.LogFolder, "[\\\\/]Admin$", "");
|
||||
// Log file filter.
|
||||
public class LogsFilterData
|
||||
{
|
||||
public String Folder { get; set; }
|
||||
public String Year { get; set; }
|
||||
public String Month { get; set; }
|
||||
public String Filename { get; set; }
|
||||
}
|
||||
public LogsFilterData LogsFilter { get; } = new LogsFilterData();
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Saxonite.Net.Core.Web.Admin.Procs
|
||||
// Process configuration.
|
||||
public new class Config : SaxProcess_Admin.Config
|
||||
{
|
||||
public Config(SaxSessionContext sessionContext, SaxOrganisation.Params prmOrganisation) : base(sessionContext)
|
||||
public Config(SaxSessionContext sessionContext, DbUpdateInfo dbUpdateInfo, SaxOrganisation.Params prmOrganisation) : base(sessionContext, dbUpdateInfo)
|
||||
{
|
||||
PrmOrganisation = prmOrganisation;
|
||||
}
|
||||
@@ -138,7 +138,7 @@ namespace Saxonite.Net.Core.Web.Admin.Procs
|
||||
control.Spreadsheet = new SaMsSpreadsheet_POI();
|
||||
control.Spreadsheet.CreateWorkbook();
|
||||
control.Spreadsheet.WorksheetName = "Organisations";
|
||||
control.Spreadsheet.ApplyDefaultStyle(GetExceldefaultWorkbookStyle());
|
||||
control.Spreadsheet.ApplyDefaultStyle(GetExcelDefaultWorkbookStyle());
|
||||
|
||||
// Columns.
|
||||
ColumnDfn colId = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Id);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Standard.Proc.Excel;
|
||||
@@ -28,7 +29,7 @@ namespace Saxonite.Net.Core.Web.Admin.Procs
|
||||
// Process configuration.
|
||||
public new class Config : SaxProcess_Admin.Config
|
||||
{
|
||||
public Config(SaxSessionContext sessionContext, IFormFile dataFile) : base(sessionContext)
|
||||
public Config(SaxSessionContext sessionContext, DbUpdateInfo dbUpdateInfo, IFormFile dataFile) : base(sessionContext, dbUpdateInfo)
|
||||
{
|
||||
this.DataFile = new UploadFileData(dataFile);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Sarand.Net.Standard.Proc.Excel;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Proc.Excel;
|
||||
using Sarand.Net.Standard.Proc.Procs;
|
||||
using Saxonite.Net.Core.Web.Base.Procs;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Procs;
|
||||
using System;
|
||||
@@ -9,13 +11,13 @@ using System.Text;
|
||||
namespace Saxonite.Net.Core.Web.Admin.Procs
|
||||
{
|
||||
//=======================================================================
|
||||
public abstract class SaxProcess_Admin : SaxProcess_Base
|
||||
public abstract class SaxProcess_Admin : SaxProcess_Web
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
public new class Config : SaxProcess_Base.Config
|
||||
public new class Config : SaxProcess_Web.Config
|
||||
{
|
||||
protected Config(SaxSessionContext sessionContext) : base(sessionContext)
|
||||
protected Config(SaxSessionContext sessionContext, DbUpdateInfo dbUpdateInfo) : base(sessionContext, dbUpdateInfo)
|
||||
{ }
|
||||
}
|
||||
|
||||
@@ -33,28 +35,15 @@ namespace Saxonite.Net.Core.Web.Admin.Procs
|
||||
//-------------------------------------------------------------------
|
||||
// Excel Spreadsheet utilities.
|
||||
//-------------------------------------------------------------------
|
||||
protected SaMsExcelColumnHeading_Config GetExcelColumnHeadingConfig()
|
||||
protected override SaMsExcelColumnHeading_Config GetExcelColumnHeadingConfig()
|
||||
{
|
||||
SaMsExcelColumnHeading_Config configHeading = new SaMsExcelColumnHeading_Config();
|
||||
configHeading.FontAttr.Name = "Arial";
|
||||
configHeading.FontAttr.HeightInPoints = 10;
|
||||
configHeading.FontAttr.ColourIndex = SaXlColourIndex.DarkBlue;
|
||||
configHeading.FontAttr.Bold = true;
|
||||
configHeading.HeadingTextWrap = true;
|
||||
configHeading.ForegroundColourIndex = SaXlColourIndex.LightYellow;
|
||||
configHeading.BorderWeight = SaXlBorderWeight.Medium;
|
||||
SaMsExcelColumnHeading_Config configHeading = base.GetExcelColumnHeadingConfig();
|
||||
return configHeading;
|
||||
}
|
||||
|
||||
protected SaMsExcelStyleAttr GetExceldefaultWorkbookStyle()
|
||||
protected override SaMsExcelStyleAttr GetExcelDefaultWorkbookStyle()
|
||||
{
|
||||
SaMsExcelStyleAttr styleAttr = new SaMsExcelStyleAttr();
|
||||
styleAttr.FontAttr.Name = "Arial";
|
||||
styleAttr.FontAttr.HeightInPoints = 9;
|
||||
styleAttr.FontAttr.ColourIndex = SaXlColourIndex.Black;
|
||||
styleAttr.HorizontalAlignment = (short)XlHAlign.xlHAlignLeft;
|
||||
styleAttr.VerticalAlignment = (short)XlVAlign.xlVAlignTop;
|
||||
styleAttr.WrapText = true;
|
||||
SaMsExcelStyleAttr styleAttr = base.GetExcelDefaultWorkbookStyle();
|
||||
return styleAttr;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user