Logging for Genesis toolbox

This commit is contained in:
Stoyan Zlatev
2023-06-05 11:33:01 +02:00
parent 33104bdca3
commit 559f01e549
14 changed files with 313 additions and 110 deletions
+1 -1
View File
@@ -155,7 +155,7 @@
</site> </site>
<site name="MeterProcessState" id="2"> <site name="MeterProcessState" id="2">
<application path="/" applicationPool="Clr4IntegratedAppPool"> <application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="D:\Projekte\SENSUS_GitLab\laa_production\Common\Service\MeterProcessState" /> <virtualDirectory path="/" physicalPath="C:\Users\SZLATEV\source\repos\laa_production\Common\Service\MeterProcessState" />
</application> </application>
<bindings> <bindings>
<binding protocol="http" bindingInformation="*:56011:localhost" /> <binding protocol="http" bindingInformation="*:56011:localhost" />
@@ -34,6 +34,7 @@
encoding: Encoding.UTF8, encoding: Encoding.UTF8,
content: JsonConvert.SerializeObject(new content: JsonConvert.SerializeObject(new
{ {
windowsUser = Environment.UserName,
software, software,
functions functions
})); }));
@@ -78,6 +79,7 @@
appId, appId,
username, username,
password, password,
windowsUser = Environment.UserName,
})); }));
using (var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage)) using (var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage))
@@ -101,5 +103,36 @@
.ConfigureAwait(true) .ConfigureAwait(true)
.GetAwaiter() .GetAwaiter()
.GetResult(); .GetResult();
internal static void LogAction(string buttonText, string buttonTag, string user, int appId)
=> Task
.Run(async () =>
{
try
{
using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Put, "api/software/functions"))
{
httpRequestMessage.Content = new StringContent(
mediaType: APPLICATION_JSON,
encoding: Encoding.UTF8,
content: JsonConvert.SerializeObject(new
{
WindowsUser = Environment.UserName,
Action = "ACCESS",
AppId = appId,
Message = $"User '{user}' accessed '{buttonText}' with Tag: {buttonTag}"
}));
_ = await httpClient.SendAsync(httpRequestMessage);
}
}
catch (Exception)
{
// TODO: Log the error message.
}
})
.ConfigureAwait(true)
.GetAwaiter()
.GetResult();
} }
} }
@@ -8,11 +8,12 @@
{ {
internal const string UNAVAILABLE = "Genesis Toolbox is currently not available."; internal const string UNAVAILABLE = "Genesis Toolbox is currently not available.";
private static IEnumerable<SoftwareFunctions> softwareFunctions; private static IEnumerable<SoftwareFunctions> softwareFunctions;
internal static int Id { get; private set; } internal static int Id { get; private set; }
internal static string User { get; private set; }
internal static bool IsAuthorized { get; private set; } internal static bool IsAuthorized { get; private set; }
internal static bool Initialized { get; private set; } internal static bool Initialized { get; private set; }
@@ -40,6 +41,7 @@
{ {
softwareFunctions = ApplicationHttp.GetSoftwareFunction<SoftwareFunctions>(Id, username, password); softwareFunctions = ApplicationHttp.GetSoftwareFunction<SoftwareFunctions>(Id, username, password);
IsAuthorized = softwareFunctions != null; IsAuthorized = softwareFunctions != null;
User = username;
if (!IsAuthorized) if (!IsAuthorized)
{ {
+2
View File
@@ -13,7 +13,9 @@
[STAThread] [STAThread]
internal static void Main() internal static void Main()
{ {
// Initializes application state for the hole application as static properties and methods.
ApplicationState.Initialize(); ApplicationState.Initialize();
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FrmMainForm()); Application.Run(new FrmMainForm());
+120 -89
View File
@@ -41,95 +41,6 @@ namespace Xylem.Common.Ui.GenesisToolBox
lblVersionNumber.Text = $@"Version: {version.Major}.{version.Minor}.{version.Build}"; lblVersionNumber.Text = $@"Version: {version.Major}.{version.Minor}.{version.Build}";
} }
private void InitializeFormState()
{
foreach (var control in this.Controls)
{
if (control is GroupBox groupBox)
{
groupBox.Hide();
}
}
this.btnSetup.Tag = SoftwareFunctions.GENERAL_SETUP;
this.btnAlarm.Tag = SoftwareFunctions.GENERAL_ALARM;
this.btnRegisterStore.Tag = SoftwareFunctions.GENERAL_REGISTER_STORE;
this.btnTempLogger.Tag = SoftwareFunctions.GENERAL_TEMP_METER;
this.btnStreamingQuality.Tag = SoftwareFunctions.GENERAL_STREAM_QUALITY;
this.btnFwUpdate.Tag = SoftwareFunctions.GENERAL_FIRMWARE_UPDATE;
this.btnLutUpdate.Tag = SoftwareFunctions.GENERAL_LUT_UPDATE;
this.button4.Tag = SoftwareFunctions.GENERAL_LUT_MANAGEMENT;
this.btnPressure.Tag = SoftwareFunctions.GENERAL_PRESSURE_LOG;
this.button1.Tag = SoftwareFunctions.GENERAL_PULS_CONFIG;
this.btnPassword.Tag = SoftwareFunctions.LAA_PASSWORD;
this.btnRegHistory.Tag = SoftwareFunctions.LAA_REGISTER_HISTORY;
this.btnPara.Tag = SoftwareFunctions.LAA_PARAMETERIZATION;
this.button2.Tag = SoftwareFunctions.LAA_PROCESS_PARAMETER;
this.button5.Tag = SoftwareFunctions.LAA_MAPPING_NA;
this.btnLegacyTestApp.Tag = SoftwareFunctions.DEV_LEGACY_TEST_APP;
this.btnFiles.Tag = SoftwareFunctions.DEV_FILE_CONTROL;
this.BtnFileSplit.Tag = SoftwareFunctions.DEV_FILE_SPLIT;
this.btnLowLevelTools.Tag = SoftwareFunctions.DEV_LOW_LEVEL_TOOLS;
if (!ApplicationState.Initialized)
{
this.Controls.Add(new Label()
{
Dock = DockStyle.Fill,
Text = ApplicationState.UNAVAILABLE,
TextAlign = ContentAlignment.MiddleCenter,
Font = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Bold),
ForeColor = Color.DarkRed,
Padding = new Padding(15)
});
}
else if (!ApplicationState.IsAuthorized)
{
this.Controls.Add(new LoginForm(this.LoginFormSubmitted));
}
else
{
this.ShowAvailableSoftwareFunctions();
}
}
private void LoginFormSubmitted(string username, string password, object sender)
{
if (sender is LoginForm loginForm)
{
var errorMessage = default(string);
if (ApplicationState.Authorize(username, password, out errorMessage))
{
this.Controls.Remove(loginForm);
this.ShowAvailableSoftwareFunctions();
}
loginForm.ShowError(errorMessage);
}
}
private void ShowAvailableSoftwareFunctions()
{
foreach (var control in this.Controls)
{
if (control is GroupBox groupBox)
{
foreach (var groupBoxControl in groupBox.Controls)
{
if (groupBoxControl is Button button && button.Tag is SoftwareFunctions softwareFunction)
{
button.Enabled = ApplicationState.IsEnabled(softwareFunction);
}
}
groupBox.Show();
}
}
}
private void btnSetup_Click(Object sender, EventArgs e) private void btnSetup_Click(Object sender, EventArgs e)
{ {
var form = new FrmSetup(); var form = new FrmSetup();
@@ -481,5 +392,125 @@ namespace Xylem.Common.Ui.GenesisToolBox
form.Closed += Form_Closed; form.Closed += Form_Closed;
Hide(); Hide();
} }
#region Form initialization
private void HideContent()
{
foreach (var control in this.Controls)
{
if (control is GroupBox groupBox)
{
groupBox.Hide();
}
}
}
private void SetSoftwareFunctions()
{
this.btnSetup.Tag = SoftwareFunctions.GENERAL_SETUP;
this.btnAlarm.Tag = SoftwareFunctions.GENERAL_ALARM;
this.btnRegisterStore.Tag = SoftwareFunctions.GENERAL_REGISTER_STORE;
this.btnTempLogger.Tag = SoftwareFunctions.GENERAL_TEMP_METER;
this.btnStreamingQuality.Tag = SoftwareFunctions.GENERAL_STREAM_QUALITY;
this.btnFwUpdate.Tag = SoftwareFunctions.GENERAL_FIRMWARE_UPDATE;
this.btnLutUpdate.Tag = SoftwareFunctions.GENERAL_LUT_UPDATE;
this.button4.Tag = SoftwareFunctions.GENERAL_LUT_MANAGEMENT;
this.btnPressure.Tag = SoftwareFunctions.GENERAL_PRESSURE_LOG;
this.button1.Tag = SoftwareFunctions.GENERAL_PULS_CONFIG;
this.btnPassword.Tag = SoftwareFunctions.LAA_PASSWORD;
this.btnRegHistory.Tag = SoftwareFunctions.LAA_REGISTER_HISTORY;
this.btnPara.Tag = SoftwareFunctions.LAA_PARAMETERIZATION;
this.button2.Tag = SoftwareFunctions.LAA_PROCESS_PARAMETER;
this.button5.Tag = SoftwareFunctions.LAA_MAPPING_NA;
this.btnLegacyTestApp.Tag = SoftwareFunctions.DEV_LEGACY_TEST_APP;
this.btnFiles.Tag = SoftwareFunctions.DEV_FILE_CONTROL;
this.BtnFileSplit.Tag = SoftwareFunctions.DEV_FILE_SPLIT;
this.btnLowLevelTools.Tag = SoftwareFunctions.DEV_LOW_LEVEL_TOOLS;
}
private void ShowErrorMessage()
{
this.Controls.Add(new Label()
{
Dock = DockStyle.Fill,
Text = ApplicationState.UNAVAILABLE,
TextAlign = ContentAlignment.MiddleCenter,
Font = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Bold),
ForeColor = Color.DarkRed,
Padding = new Padding(15)
});
}
private void LoginFormSubmitted(string username, string password, object sender)
{
if (sender is LoginForm loginForm)
{
var errorMessage = default(string);
if (ApplicationState.Authorize(username, password, out errorMessage))
{
this.Controls.Remove(loginForm);
this.ShowAvailableSoftwareFunctions();
}
loginForm.ShowError(errorMessage);
}
}
private void ShowAvailableSoftwareFunctions()
{
foreach (var control in this.Controls)
{
if (control is GroupBox groupBox)
{
foreach (var groupBoxControl in groupBox.Controls)
{
if (groupBoxControl is Button button)
{
if (button.Tag is SoftwareFunctions softwareFunction)
{
button.Enabled = ApplicationState.IsEnabled(softwareFunction);
}
button.Click += LogUserAction;
}
}
groupBox.Show();
}
}
}
private void LogUserAction(object sender, EventArgs e)
{
if (sender is Button button)
{
ApplicationHttp.LogAction(button.Text, $"{button.Tag}", ApplicationState.User, ApplicationState.Id);
}
}
private void InitializeFormState()
{
this.HideContent();
this.SetSoftwareFunctions();
if (!ApplicationState.Initialized)
{
this.ShowErrorMessage();
}
else if (!ApplicationState.IsAuthorized)
{
this.Controls.Add(new LoginForm(this.LoginFormSubmitted));
}
else
{
this.ShowAvailableSoftwareFunctions();
}
}
#endregion Form initialization
} }
} }
@@ -53,15 +53,19 @@
.ExecuteReader(x => x.GetString()); .ExecuteReader(x => x.GetString());
public short Login(string username, string password) public short Login(string username, string password)
=> this.sqlClient.FirstOrDefault($@" {
SELECT TOP 1 [MitarbeiterNr] var userId = this.sqlClient
FROM [Mitarbeiter] .FirstOrDefault($@"
WHERE [Benutzername] LIKE @{nameof(username)} SELECT TOP 1 [MitarbeiterNr]
AND [PasswordHash] LIKE @{nameof(password)}", FROM [Mitarbeiter]
parameters => parameters WHERE [Benutzername] LIKE @{nameof(username)}
.Add(nameof(username), username) AND [PasswordHash] LIKE @{nameof(password)}",
.Add(nameof(password), password), parameters => parameters
reader => reader.GetSmallint()); .Add(nameof(username), username)
.Add(nameof(password), password),
reader => reader.GetSmallint());
return userId;
}
public int ResetPassword(string username) public int ResetPassword(string username)
=> this.sqlClient => this.sqlClient
@@ -0,0 +1,9 @@
namespace LaaProductionWeb.Services.Interfaces
{
using System;
public interface ILoggerService
{
void Log(Action<LoggerService.LogModel> logModel);
}
}
@@ -10,7 +10,7 @@
void DeleteFunction(int funcId); void DeleteFunction(int funcId);
short FindAndUpdateSoftware(string name, IEnumerable<string> functions); short FindAndUpdateSoftware(string windowsUser, string software, IEnumerable<string> functions);
IEnumerable<SoftwareFunction> GetAllSoftwareFunctions(); IEnumerable<SoftwareFunction> GetAllSoftwareFunctions();
@@ -61,11 +61,13 @@
<Compile Include="Interfaces\IAccountService.cs" /> <Compile Include="Interfaces\IAccountService.cs" />
<Compile Include="Interfaces\IApprovalsService.cs" /> <Compile Include="Interfaces\IApprovalsService.cs" />
<Compile Include="Interfaces\IHttpService.cs" /> <Compile Include="Interfaces\IHttpService.cs" />
<Compile Include="Interfaces\ILoggerService.cs" />
<Compile Include="Interfaces\IOrdersService.cs" /> <Compile Include="Interfaces\IOrdersService.cs" />
<Compile Include="Interfaces\IProtocolService.cs" /> <Compile Include="Interfaces\IProtocolService.cs" />
<Compile Include="Interfaces\IReportService.cs" /> <Compile Include="Interfaces\IReportService.cs" />
<Compile Include="Interfaces\IShipmentsService.cs" /> <Compile Include="Interfaces\IShipmentsService.cs" />
<Compile Include="Interfaces\ISoftwareService.cs" /> <Compile Include="Interfaces\ISoftwareService.cs" />
<Compile Include="LoggerService.cs" />
<Compile Include="Models\Employee.cs" /> <Compile Include="Models\Employee.cs" />
<Compile Include="Models\HttpResponseModel.cs" /> <Compile Include="Models\HttpResponseModel.cs" />
<Compile Include="Models\MissingItem.cs" /> <Compile Include="Models\MissingItem.cs" />
@@ -0,0 +1,54 @@
namespace LaaProductionWeb.Services
{
using LaaProductionWeb.Data.Interfaces;
using LaaProductionWeb.Services.Interfaces;
using System;
public class LoggerService : ILoggerService
{
private readonly ISqlClient sqlClient;
public LoggerService(ISqlClient sqlClient)
=> this.sqlClient = sqlClient;
public class Actions
{
public const string RUN = nameof(RUN);
}
public class LogModel
{
public long Id { get; internal set; }
public DateTime Date { get; internal set; }
= DateTime.Now;
public string User { get; set; }
public string Action { get; set; }
public string Data { get; set; }
}
public void Log(Action<LogModel> logModel)
{
var model = new LogModel();
logModel?.Invoke(model);
this.sqlClient
.CreateCommand($@"
INSERT INTO [SoftwareFunctionsLog] (
[User]
, [Action]
, [Data])
VALUES (@{nameof(model.User)}
, @{nameof(model.Action)}
, @{nameof(model.Data)})")
.AddParameter(nameof(model.User), model.User)
.AddParameter(nameof(model.Action), model.Action)
.AddParameter(nameof(model.Data), model.Data)
.ExecuteNonQuery();
}
}
}
@@ -55,7 +55,7 @@
.ExecuteNonQuery(); .ExecuteNonQuery();
} }
public short FindAndUpdateSoftware(string name, IEnumerable<string> functions) public short FindAndUpdateSoftware(string windowsUser, string name, IEnumerable<string> functions)
{ {
var appId = this.sqlClient var appId = this.sqlClient
.CreateCommand($@" .CreateCommand($@"
@@ -67,13 +67,17 @@
.AddParameter(nameof(name), name) .AddParameter(nameof(name), name)
.FirstOrDefault(x => x.GetSmallint()); .FirstOrDefault(x => x.GetSmallint());
if (appId > 0 && functions != null && functions.Any()) if (appId > 0)
{ {
foreach (var function in functions) if (functions != null && functions.Any())
{ {
if (Regex.IsMatch(function, "[a-zA-Z_]+"))
foreach (var function in functions)
{ {
this.AddFunction(appId, function); if (Regex.IsMatch(function, "[a-zA-Z_]+"))
{
this.AddFunction(appId, function);
}
} }
} }
} }
@@ -41,6 +41,7 @@
services.AddScoped<IAccountService, AccountService>(); services.AddScoped<IAccountService, AccountService>();
services.AddScoped<IApprovalsService, ApprovalsService>(); services.AddScoped<IApprovalsService, ApprovalsService>();
services.AddScoped<ILoggerService, LoggerService>();
services.AddScoped<IOrdersService, OrdersService>(); services.AddScoped<IOrdersService, OrdersService>();
services.AddScoped<IProtocolService, ProtocolService>(); services.AddScoped<IProtocolService, ProtocolService>();
services.AddScoped<IReportService, ReportService>(); services.AddScoped<IReportService, ReportService>();
@@ -2,23 +2,41 @@
{ {
using LaaProductionWeb.Services.Interfaces; using LaaProductionWeb.Services.Interfaces;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Web.Http; using System.Web.Http;
public class AppIdController : ApiController public class AppIdController : ApiController
{ {
private readonly ISoftwareService softwareService; private readonly ISoftwareService softwareService;
private readonly ILoggerService loggerService;
public AppIdController() public AppIdController()
=> this.softwareService = ServiceProvider.Current.GetService<ISoftwareService>(); {
this.softwareService = ServiceProvider.Current.GetService<ISoftwareService>();
this.loggerService = ServiceProvider.Current.GetService<ILoggerService>();
}
[HttpPost] [HttpPost]
public int Post(AppIdPostInputModel model) public int Post(AppIdPostInputModel model)
=> this.softwareService.FindAndUpdateSoftware(model.Software, model.Functions); {
var appId = this.softwareService.FindAndUpdateSoftware(model.WindowsUser, model.Software, model.Functions);
this.loggerService.Log(x =>
{
x.User = model.WindowsUser;
x.Action = "STARTING APPLICATION";
x.Data = $"AppId: {appId}, Functions: {string.Join(", ", model.Functions ?? Array.Empty<string>())}";
});
return appId;
}
} }
public class AppIdPostInputModel public class AppIdPostInputModel
{ {
public string WindowsUser { get; set; }
public string Software { get; set; } public string Software { get; set; }
public IEnumerable<string> Functions { get; set; } public IEnumerable<string> Functions { get; set; }
@@ -1,18 +1,21 @@
namespace LaaProductionWeb.Areas.Software.Controllers namespace LaaProductionWeb.Areas.Software.Controllers
{ {
using LaaProductionWeb.Services.Interfaces; using LaaProductionWeb.Services.Interfaces;
using System;
using System.Web.Http; using System.Web.Http;
public class FunctionsController : ApiController public class FunctionsController : ApiController
{ {
private readonly IAccountService accountService; private readonly IAccountService accountService;
private readonly ISoftwareService softwareService; private readonly ISoftwareService softwareService;
private readonly ILoggerService loggerService;
public FunctionsController() public FunctionsController()
{ {
this.accountService = ServiceProvider.Current.GetService<IAccountService>(); this.accountService = ServiceProvider.Current.GetService<IAccountService>();
this.softwareService = ServiceProvider.Current.GetService<ISoftwareService>(); this.softwareService = ServiceProvider.Current.GetService<ISoftwareService>();
this.loggerService = ServiceProvider.Current.GetService<ILoggerService>();
} }
[HttpPost] [HttpPost]
@@ -22,21 +25,61 @@
if (userId <= 0) if (userId <= 0)
{ {
this.loggerService.Log(options =>
{
options.User = model.WindowsUser;
options.Action = "LOG IN FAILED";
options.Data = $"{model.WindowsUser}:{model.AppId} - for user {model.Username} with password {model.Password}";
});
return this.Unauthorized(); return this.Unauthorized();
} }
var functions = this.softwareService.GetSoftwareFunctions(model.AppId, userId); var functions = this.softwareService.GetSoftwareFunctions(model.AppId, userId);
this.loggerService.Log(options =>
{
options.User = model.WindowsUser;
options.Action = "LOG IN SUCCEEDED";
options.Data = $"{model.WindowsUser}:{model.AppId} - for user {model.Username} with password {model.Password}. User has following functions {string.Join(", ", functions ?? Array.Empty<string>())}";
});
return this.Json(functions); return this.Json(functions);
} }
[HttpPut]
public IHttpActionResult Put(FunctionsPutInputModel model)
{
this.loggerService.Log(options =>
{
options.User = model.WindowsUser;
options.Action = model.Action;
options.Data = $"AppId: {model.AppId} - reports: {model.Message}";
});
return this.Ok();
}
} }
public class FunctionsPostInputModel public class FunctionsPostInputModel
{ {
public short AppId { get; set; } public short AppId { get; set; }
public string WindowsUser { get; set; }
public string Username { get; set; } public string Username { get; set; }
public string Password { get; set; } public string Password { get; set; }
} }
public class FunctionsPutInputModel
{
public short AppId { get; set; }
public string WindowsUser { get; set; }
public string Message { get; set; }
public string Action { get; set; }
}
} }