Genesis Toolbox login form

This commit is contained in:
Stoyan Zlatev
2023-06-02 15:49:59 +02:00
parent 9fbcecdfb9
commit 82bb4b87b6
22 changed files with 853 additions and 109 deletions
+1
View File
@@ -9,6 +9,7 @@
*.user
*.userosscache
*.sln.docstates
*MagFlux/MjkControlledCodeRef*
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
@@ -199,6 +199,13 @@ namespace Xylem.Common.CommonCore.Configuration
private const String PressureSensorTestURL_GetTestResults
= "http://sla12iis01.emea.sensus.net/MeterProcessState/api/CordonelPressureSensorTest/GetTestResults/{0}";
public const string LaaProductionAPI
#if DEBUG
= "http://localhost:54448";
#else
= "http://sla12iis01.emea.sensus.net";
#endif
/// <summary>
/// GET: test specification for water meter with pressure sensor.
@@ -1 +1 @@
f64d563def603c89cafafa61a3219ba97e1e344c
57a46bdf07e306281dc4ae72a3747ed460385fe7
+160
View File
@@ -0,0 +1,160 @@
namespace Xylem.Common.Ui.GenesisToolBox.Ctls
{
partial class LoginForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.LoginFormPanel = new System.Windows.Forms.Panel();
this.ErrorMessage = new System.Windows.Forms.Label();
this.LoginButton = new System.Windows.Forms.Button();
this.Password = new System.Windows.Forms.TextBox();
this.UsernameLabel = new System.Windows.Forms.Label();
this.Username = new System.Windows.Forms.TextBox();
this.PasswordLabel = new System.Windows.Forms.Label();
this.LoginErrorProvider = new System.Windows.Forms.ErrorProvider(this.components);
this.LoginFormPanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.LoginErrorProvider)).BeginInit();
this.SuspendLayout();
//
// LoginFormPanel
//
this.LoginFormPanel.Controls.Add(this.ErrorMessage);
this.LoginFormPanel.Controls.Add(this.LoginButton);
this.LoginFormPanel.Controls.Add(this.Password);
this.LoginFormPanel.Controls.Add(this.UsernameLabel);
this.LoginFormPanel.Controls.Add(this.Username);
this.LoginFormPanel.Controls.Add(this.PasswordLabel);
this.LoginFormPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.LoginFormPanel.Location = new System.Drawing.Point(0, 0);
this.LoginFormPanel.Name = "LoginFormPanel";
this.LoginFormPanel.Size = new System.Drawing.Size(458, 439);
this.LoginFormPanel.TabIndex = 0;
//
// ErrorMessage
//
this.ErrorMessage.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.ErrorMessage.AutoSize = true;
this.ErrorMessage.ForeColor = System.Drawing.Color.Red;
this.ErrorMessage.Location = new System.Drawing.Point(96, 251);
this.ErrorMessage.Name = "ErrorMessage";
this.ErrorMessage.Size = new System.Drawing.Size(0, 13);
this.ErrorMessage.TabIndex = 5;
//
// LoginButton
//
this.LoginButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.LoginButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.LoginButton.Location = new System.Drawing.Point(97, 221);
this.LoginButton.Name = "LoginButton";
this.LoginButton.Size = new System.Drawing.Size(266, 23);
this.LoginButton.TabIndex = 4;
this.LoginButton.Text = "Login";
this.LoginButton.UseVisualStyleBackColor = true;
this.LoginButton.Click += new System.EventHandler(this.LoginButtonClick);
//
// Password
//
this.Password.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.Password.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.Password.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Password.Location = new System.Drawing.Point(97, 195);
this.Password.Name = "Password";
this.Password.PasswordChar = '*';
this.Password.Size = new System.Drawing.Size(266, 20);
this.Password.TabIndex = 3;
this.Password.UseSystemPasswordChar = true;
//
// UsernameLabel
//
this.UsernameLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.UsernameLabel.AutoSize = true;
this.UsernameLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.UsernameLabel.Location = new System.Drawing.Point(94, 140);
this.UsernameLabel.Name = "UsernameLabel";
this.UsernameLabel.Size = new System.Drawing.Size(63, 13);
this.UsernameLabel.TabIndex = 0;
this.UsernameLabel.Text = "Username";
//
// Username
//
this.Username.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.Username.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Username.Location = new System.Drawing.Point(97, 156);
this.Username.Name = "Username";
this.Username.Size = new System.Drawing.Size(266, 20);
this.Username.TabIndex = 2;
//
// PasswordLabel
//
this.PasswordLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.PasswordLabel.AutoSize = true;
this.PasswordLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.PasswordLabel.Location = new System.Drawing.Point(94, 179);
this.PasswordLabel.Name = "PasswordLabel";
this.PasswordLabel.Size = new System.Drawing.Size(61, 13);
this.PasswordLabel.TabIndex = 1;
this.PasswordLabel.Text = "Password";
//
// LoginErrorProvider
//
this.LoginErrorProvider.BlinkRate = 0;
this.LoginErrorProvider.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.NeverBlink;
this.LoginErrorProvider.ContainerControl = this;
//
// LoginForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.LoginFormPanel);
this.Name = "LoginForm";
this.Size = new System.Drawing.Size(458, 439);
this.LoginFormPanel.ResumeLayout(false);
this.LoginFormPanel.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.LoginErrorProvider)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel LoginFormPanel;
private System.Windows.Forms.Button LoginButton;
private System.Windows.Forms.TextBox Password;
private System.Windows.Forms.Label UsernameLabel;
private System.Windows.Forms.TextBox Username;
private System.Windows.Forms.Label PasswordLabel;
private System.Windows.Forms.ErrorProvider LoginErrorProvider;
private System.Windows.Forms.Label ErrorMessage;
}
}
@@ -0,0 +1,68 @@
namespace Xylem.Common.Ui.GenesisToolBox.Ctls
{
using System;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;
public partial class LoginForm : UserControl
{
private readonly Action<string, string, object> submittedCallback;
public LoginForm()
{
this.InitializeComponent();
this.Dock = DockStyle.Fill;
}
public LoginForm(Action<string, string, object> submittedCallback) : this()
=> this.submittedCallback = submittedCallback;
private void LoginButtonClick(object sender, EventArgs e)
{
this.ErrorMessage.Text = default(string);
this.LoginErrorProvider.Clear();
var isValid = true;
if (string.IsNullOrWhiteSpace(this.Username.Text))
{
isValid = false;
this.LoginErrorProvider.SetError(this.Username, "Username is required.");
}
if (string.IsNullOrWhiteSpace(this.Password.Text))
{
isValid = false;
this.LoginErrorProvider.SetError(this.Password, "Password is required.");
}
if (isValid)
{
this.submittedCallback?.Invoke(this.Username.Text, this.Password.Text.ComputeBase64Hash(), this);
}
}
internal void ShowError(string errorMessage)
=> this.ErrorMessage.Text = errorMessage;
}
internal static class PasswordExtensions
{
internal static string ComputeBase64Hash(this string plainText)
{
if (string.IsNullOrWhiteSpace(plainText))
{
return plainText;
}
var buffer = Encoding.UTF8.GetBytes(plainText);
var hash = SHA256.Create().ComputeHash(buffer);
return Convert.ToBase64String(hash);
}
}
}
@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="LoginErrorProvider.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>
@@ -43,6 +43,7 @@
<LangVersion>7.0</LangVersion>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\Xylem.Common.Ui.GenesisToolBox.xml</DocumentationFile>
<NoWarn>1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -170,6 +171,7 @@
<Reference Include="System.Core" />
<Reference Include="System.DirectoryServices" />
<Reference Include="System.DirectoryServices.AccountManagement" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Transactions" />
@@ -196,6 +198,12 @@
<Compile Include="ctlConnectInterface.Designer.cs">
<DependentUpon>ctlConnectInterface.cs</DependentUpon>
</Compile>
<Compile Include="Ctls\LoginForm.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Ctls\LoginForm.Designer.cs">
<DependentUpon>LoginForm.cs</DependentUpon>
</Compile>
<Compile Include="Ctls\TextProgressBar.cs">
<SubType>Component</SubType>
</Compile>
@@ -404,6 +412,10 @@
<Compile Include="FrmTempMeter.Designer.cs">
<DependentUpon>FrmTempMeter.cs</DependentUpon>
</Compile>
<Compile Include="Infrastructure\ApplicationHttp.cs" />
<Compile Include="Infrastructure\ApplicationState.cs" />
<Compile Include="Infrastructure\ApplicationVersion.cs" />
<Compile Include="Infrastructure\SoftwareFunctions.cs" />
<Compile Include="ProccessConfig.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -422,6 +434,9 @@
<Compile Include="TextFileMatchControl.Designer.cs">
<DependentUpon>TextFileMatchControl.cs</DependentUpon>
</Compile>
<EmbeddedResource Include="Ctls\LoginForm.resx">
<DependentUpon>LoginForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="FrmCalibrationResults.resx">
<DependentUpon>FrmCalibrationResults.cs</DependentUpon>
</EmbeddedResource>
@@ -10,5 +10,6 @@
<ErrorReportUrlHistory />
<FallbackCulture>de-DE</FallbackCulture>
<VerifyUploadedFiles>false</VerifyUploadedFiles>
<ProjectView>ProjectFiles</ProjectView>
</PropertyGroup>
</Project>
@@ -0,0 +1,105 @@
namespace Xylem.Common.Ui.GenesisToolBox.Infrastructure
{
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Xylem.Common.CommonCore.Configuration;
internal class ApplicationHttp
{
const string APPLICATION_JSON = "application/json";
private static readonly HttpClient httpClient = new HttpClient()
{
BaseAddress = new Uri(ServiceUrls.LaaProductionAPI)
};
internal static int ApplicationId(string software, params string[] functions)
=> Task
.Run(async () =>
{
var applicationId = default(int);
try
{
using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, "api/software/appid"))
{
httpRequestMessage.Content = new StringContent(
mediaType: APPLICATION_JSON,
encoding: Encoding.UTF8,
content: JsonConvert.SerializeObject(new
{
software,
functions
}));
using (var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage))
{
if (httpResponseMessage.Content != null)
{
var httpResponseContent = await httpResponseMessage.Content.ReadAsStringAsync();
_ = int.TryParse(httpResponseContent, out applicationId);
}
}
}
}
catch (Exception)
{
// TODO: Log the error message.
}
return applicationId;
})
.ConfigureAwait(true)
.GetAwaiter()
.GetResult();
internal static IEnumerable<T> GetSoftwareFunction<T>(int appId, string username, string password)
=> Task
.Run(async () =>
{
var functions = default(IEnumerable<T>);
try
{
using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, "api/software/functions"))
{
httpRequestMessage.Content = new StringContent(
mediaType: APPLICATION_JSON,
encoding: Encoding.UTF8,
content: JsonConvert.SerializeObject(new
{
appId,
username,
password,
}));
using (var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage))
{
if (httpResponseMessage.IsSuccessStatusCode && httpResponseMessage.Content != null)
{
var httpResponseContent = await httpResponseMessage.Content.ReadAsStringAsync();
functions = JsonConvert.DeserializeObject<T[]>(httpResponseContent);
}
}
}
}
catch (Exception)
{
// TODO: Log the error message.
}
return functions;
})
.ConfigureAwait(true)
.GetAwaiter()
.GetResult();
}
}
@@ -0,0 +1,57 @@
namespace Xylem.Common.Ui.GenesisToolBox.Infrastructure
{
using System;
using System.Collections.Generic;
using System.Linq;
internal class ApplicationState
{
internal const string UNAVAILABLE = "Genesis Toolbox is currently not available.";
private static IEnumerable<SoftwareFunctions> softwareFunctions;
internal static int Id { get; private set; }
internal static bool IsAuthorized { get; private set; }
internal static bool Initialized { get; private set; }
internal static ApplicationVersion Version { get; private set; }
= ApplicationVersion.Current;
internal static void Initialize()
{
Id = ApplicationHttp.ApplicationId(
software: Version.Assembly.Name,
functions: Enum.GetNames(typeof(SoftwareFunctions)));
Initialized = Id > 0;
}
internal static bool Authorize(string username, string password, out string error)
{
error = default(string);
if (Id <= 0)
{
error = "Genesis Toolbox is currently not available.";
}
else
{
softwareFunctions = ApplicationHttp.GetSoftwareFunction<SoftwareFunctions>(Id, username, password);
IsAuthorized = softwareFunctions != null;
if (!IsAuthorized)
{
error = "Genesis Toolbox is currently not available.";
softwareFunctions = Array.Empty<SoftwareFunctions>();
}
}
return IsAuthorized;
}
internal static Boolean IsEnabled(SoftwareFunctions softwareFunction)
=> softwareFunctions.Contains(softwareFunction);
}
}
@@ -0,0 +1,44 @@
namespace Xylem.Common.Ui.GenesisToolBox.Infrastructure
{
using System;
using System.Reflection;
internal struct ApplicationVersion
{
private ApplicationVersion(bool initialize)
{
if (initialize)
{
this.Assembly = System.Reflection.Assembly
.GetExecutingAssembly()
.GetName();
this.Major = this.Assembly.Version.Major;
this.Minor = this.Assembly.Version.Minor;
this.Build = this.Assembly.Version.Build;
}
else
{
this.Major = default(int);
this.Minor = default(int);
this.Build = default(int);
this.Assembly = default(AssemblyName);
}
}
public int Major { get; }
public int Minor { get; }
public int Build { get; }
public AssemblyName Assembly { get; }
public override string ToString()
=> $"{nameof(Version)}: {this.Major}.{this.Minor}.{this.Build}";
public static ApplicationVersion Current => new ApplicationVersion(true);
public static implicit operator string(ApplicationVersion assemblyVersion)
=> assemblyVersion.ToString();
}
}
@@ -0,0 +1,27 @@
namespace Xylem.Common.Ui.GenesisToolBox.Infrastructure
{
internal enum SoftwareFunctions
{
DEV_FILE_CONTROL,
DEV_FILE_SPLIT,
DEV_LEGACY_TEST_APP,
DEV_LOW_LEVEL_TOOLS,
GENERAL_ALARM,
GENERAL_FIRMWARE_UPDATE,
GENERAL_LUT_MANAGEMENT,
GENERAL_LUT_UPDATE,
GENERAL_PRESSURE_LOG,
GENERAL_PULS_CONFIG,
GENERAL_REGISTER_STORE,
GENERAL_SETUP,
GENERAL_STREAM_QUALITY,
GENERAL_TEMP_METER,
LAA_MAPPING_NA,
LAA_PASSWORD,
LAA_PARAMETERIZATION,
LAA_PROCESS_PARAMETER,
LAA_REGISTER_HISTORY,
}
}
+8 -5
View File
@@ -1,16 +1,19 @@
using System;
using System.Windows.Forms;
namespace Xylem.Common.Ui.GenesisToolBox
namespace Xylem.Common.Ui.GenesisToolBox
{
using System;
using System.Windows.Forms;
using Xylem.Common.Ui.GenesisToolBox.Infrastructure;
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
internal static void Main()
{
ApplicationState.Initialize();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FrmMainForm());
+97 -1
View File
@@ -1,9 +1,14 @@
using GenesisToolBox;
using System;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using Xylem.Common.CommonCore.Consts;
using Xylem.Common.Ui.GenesisToolBox.Ctls;
using Xylem.Common.Ui.GenesisToolBox.Infrastructure;
using Xylem.Common.Utils.Logging;
namespace Xylem.Common.Ui.GenesisToolBox
@@ -19,7 +24,9 @@ namespace Xylem.Common.Ui.GenesisToolBox
/// </summary>
public FrmMainForm()
{
InitializeComponent();
this.InitializeComponent();
this.InitializeFormState();
var logger = NLogHelper.CreateOrGetLogger("GenesisToolBox");
var version = Assembly.GetExecutingAssembly().GetName().Version;
logger.Info($"GenesisToolBox Version: {version.Major}.{version.Minor}.{version.Build}");
@@ -34,6 +41,95 @@ namespace Xylem.Common.Ui.GenesisToolBox
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)
{
var form = new FrmSetup();
@@ -10,12 +10,14 @@
void DeleteFunction(int funcId);
IEnumerable<string> FindSoftwareForUser(short appId, string username, string password);
short FindAndUpdateSoftware(string name, IEnumerable<string> functions);
IEnumerable<SoftwareFunction> GetAllSoftwareFunctions();
IEnumerable<SoftwareFunction> GetSoftwareFunctions(short appId);
IEnumerable<string> GetSoftwareFunctions(short appId, short userId);
SoftwareOverview GetSoftwareOverview(short appId);
IEnumerable<Software> GetSoftwareVersions(short appId);
@@ -6,7 +6,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
public class SoftwareService : ISoftwareService
{
@@ -27,6 +29,15 @@
.AddParameter(nameof(name), name)
.ExecuteNonQuery();
public int ApplicationId(string name)
=> this.sqlClient
.CreateCommand($@"
SELECT TOP 1 [AppId]
FROM [VersionSoftwareAccess]
WHERE [SoftwareAccess_Program] = @{nameof(name)}")
.AddParameter(nameof(name), name)
.FirstOrDefault(x => x.GetSmallint());
public void DeleteFunction(int funcId)
{
this.sqlClient
@@ -44,9 +55,30 @@
.ExecuteNonQuery();
}
public IEnumerable<string> FindSoftwareForUser(short appId, string username, string password)
public short FindAndUpdateSoftware(string name, IEnumerable<string> functions)
{
throw new NotImplementedException();
var appId = this.sqlClient
.CreateCommand($@"
SELECT TOP 1 [AppId]
, MAX([SoftwareAccess_VaildTo]) OVER (PARTITION BY [AppId])
FROM [VersionSoftwareAccess]
WHERE [SoftwareAccess_Program] = @{nameof(name)}
AND [SoftwareAccess_VaildTo] > GETDATE()")
.AddParameter(nameof(name), name)
.FirstOrDefault(x => x.GetSmallint());
if (appId > 0 && functions != null && functions.Any())
{
foreach (var function in functions)
{
if (Regex.IsMatch(function, "[a-zA-Z_]+"))
{
this.AddFunction(appId, function);
}
}
}
return appId;
}
public IEnumerable<SoftwareFunction> GetAllSoftwareFunctions()
@@ -79,6 +111,19 @@
Function = f.GetString()
});
public IEnumerable<string> GetSoftwareFunctions(short appId, short userId)
=> this.sqlClient
.CreateCommand($@"
SELECT [SF].[Function] AS [Function]
FROM [UsersFunctions] AS [UF]
JOIN [SoftwareFunctions] AS [SF]
ON [SF].[Id] = [UF].[SoftwareFunctionId]
WHERE [UF].[UserId] = @{nameof(userId)}
AND [SF].[AppId] = @{nameof(appId)}")
.AddParameter(nameof(appId), appId)
.AddParameter(nameof(userId), userId)
.ExecuteReader(x => x.GetString());
public SoftwareOverview GetSoftwareOverview(short appId)
=> this.sqlClient
.CreateCommand($@"
@@ -1,54 +0,0 @@
namespace LaaProductionWeb.Areas.Account.Controllers
{
using LaaProductionWeb.Services.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Http;
[AllowAnonymous]
public class FunctionsController : ApiController
{
private readonly IAccountService accountService;
public FunctionsController()
=> this.accountService = ServiceProvider.Current.GetService<IAccountService>();
[HttpGet]
public IHttpActionResult Get()
{
if (this.ActionContext.Request.Headers.TryGetValues("Authorization", out IEnumerable<string> values) && values.Any())
{
var bearer = values
.FirstOrDefault()
.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.LastOrDefault();
try
{
var tokens = Encoding.UTF8
.GetString(Convert.FromBase64String(bearer))
.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
if (tokens != null && tokens.Length == 3 && short.TryParse(tokens[0], out short appId))
{
var username = tokens[1];
var password = tokens[2];
var functions = this.accountService.FindUserFunctions(appId, username, password);
return this.Ok(functions);
}
}
catch (Exception)
{
// TODO: Log exception.
}
}
return this.BadRequest("Endpoint expects bearer authorization header with appId:username:password base64 encoded.");
}
}
}
@@ -1,40 +0,0 @@
namespace LaaProductionWeb.Areas.Account.Controllers
{
using LaaProductionWeb.Services.Interfaces;
using System.Web.Http;
public class PWDController : ApiController
{
private readonly IAccountService accountService;
public PWDController()
=> this.accountService = ServiceProvider.Current.GetService<IAccountService>();
[HttpPost]
public IHttpActionResult Post(string username, string password)
{
if (string.IsNullOrWhiteSpace(password))
{
return this.BadRequest("Invalid password.");
}
else if (this.accountService.ResetPassword(username, password) == 1)
{
return this.Ok();
}
return this.BadRequest("Password was not reseted.");
}
[HttpDelete]
public IHttpActionResult Delete(string username)
{
if (this.accountService.ResetPassword(username) == 1)
{
return this.Ok();
}
return this.BadRequest("Password was not reseted.");
}
}
}
@@ -0,0 +1,26 @@
namespace LaaProductionWeb.Areas.Software.Controllers
{
using LaaProductionWeb.Services.Interfaces;
using System.Collections.Generic;
using System.Web.Http;
public class AppIdController : ApiController
{
private readonly ISoftwareService softwareService;
public AppIdController()
=> this.softwareService = ServiceProvider.Current.GetService<ISoftwareService>();
[HttpPost]
public int Post(AppIdPostInputModel model)
=> this.softwareService.FindAndUpdateSoftware(model.Software, model.Functions);
}
public class AppIdPostInputModel
{
public string Software { get; set; }
public IEnumerable<string> Functions { get; set; }
}
}
@@ -0,0 +1,42 @@
namespace LaaProductionWeb.Areas.Software.Controllers
{
using LaaProductionWeb.Services.Interfaces;
using System.Web.Http;
public class FunctionsController : ApiController
{
private readonly IAccountService accountService;
private readonly ISoftwareService softwareService;
public FunctionsController()
{
this.accountService = ServiceProvider.Current.GetService<IAccountService>();
this.softwareService = ServiceProvider.Current.GetService<ISoftwareService>();
}
[HttpPost]
public IHttpActionResult Post(FunctionsPostInputModel model)
{
var userId = this.accountService.Login(model.Username, model.Password);
if (userId <= 0)
{
return this.Unauthorized();
}
var functions = this.softwareService.GetSoftwareFunctions(model.AppId, userId);
return this.Json(functions);
}
}
public class FunctionsPostInputModel
{
public short AppId { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
}
@@ -0,0 +1,17 @@
namespace LaaProductionWeb.Areas.Software
{
using System.Web.Mvc;
public class SoftwareAreaRegistration : AreaRegistration
{
public override string AreaName => "Software";
public override void RegisterArea(AreaRegistrationContext context)
{
//context.MapRoute(
// "Software_default",
// "api/Software/{controller}/{id}",
// new { action = "Index", id = UrlParameter.Optional });
}
}
}
@@ -135,8 +135,6 @@
<Compile Include="App_Start\FilterConfig.cs" />
<Compile Include="App_Start\RouteConfig.cs" />
<Compile Include="App_Start\WebApiConfig.cs" />
<Compile Include="Areas\Account\Controllers\FunctionsController.cs" />
<Compile Include="Areas\Account\Controllers\PWDController.cs" />
<Compile Include="Areas\Administration\AdministrationAreaRegistration.cs" />
<Compile Include="Areas\Administration\Controllers\SoftwareController.cs" />
<Compile Include="Areas\Administration\Models\Software\AddFunctionModel.cs" />
@@ -161,6 +159,9 @@
<Compile Include="Areas\Shipment\Controllers\ScannedController.cs" />
<Compile Include="Areas\Shipment\Models\Interfaces\IScanModel.cs" />
<Compile Include="Areas\Shipment\Models\ScanModel.cs" />
<Compile Include="Areas\Software\Controllers\AppIdController.cs" />
<Compile Include="Areas\Software\Controllers\FunctionsController.cs" />
<Compile Include="Areas\Software\SoftwareAreaRegistration.cs" />
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Controllers\ApprovalsController.cs" />
<Compile Include="Controllers\EmailController.cs" />
@@ -194,9 +195,7 @@
<Content Include="Global.asax" />
<Content Include="Web.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="Areas\Account\Models\" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Content Include="App_Content\css\bootstrap.min.css.map" />
<Content Include="App_Content\font\fonts\bootstrap-icons.woff" />