From 9e9a01bd431bb09766150d8f298eff5a1bdd68de Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Wed, 23 Nov 2022 16:27:14 +0100 Subject: [PATCH] Approval by legalizator when #define LANG_PL, ver. 3.5.1993 --- Common/CurrentUser.cs | 10 + SharedDatabase/Entities/User.cs | 5 + .../Forms/PlainLoginDlg.Designer.cs | 112 +++++++ SharedDatabase/Forms/PlainLoginDlg.cs | 315 ++++++++++++++++++ SharedDatabase/Forms/PlainLoginDlg.resx | 300 +++++++++++++++++ SharedDatabase/Resources/Strings.Designer.cs | 2 +- SharedDatabase/Resources/Strings.resx | 2 +- SharedDatabase/SharedDatabase.csproj | 9 + TBF/Properties/AssemblyInfo.cs | 4 +- TBF/Rig/Sequences/MainSeq.cs | 39 ++- TBF/Rig/Sequences/MainSeqUtils.cs | 2 +- TBF/UI/Shared/LoginDlgWithBenchSelection.cs | 2 +- 12 files changed, 794 insertions(+), 8 deletions(-) create mode 100644 SharedDatabase/Forms/PlainLoginDlg.Designer.cs create mode 100644 SharedDatabase/Forms/PlainLoginDlg.cs create mode 100644 SharedDatabase/Forms/PlainLoginDlg.resx diff --git a/Common/CurrentUser.cs b/Common/CurrentUser.cs index 27bfb4df1..6d7bc62a7 100644 --- a/Common/CurrentUser.cs +++ b/Common/CurrentUser.cs @@ -96,6 +96,16 @@ namespace Common return string.Format("{0},{1},{2}", User().UserName, User2.UserName, User3.UserName); } + public static string GetEncodedString(string legalizator) + { + if (User() == null || User().UserName == null) return string.Empty; + return string.Format("{0}~{1}~{2}", + User().UserName, + User().FullName == null ? string.Empty : User().FullName, + legalizator == null ? string.Empty : legalizator); + } + + /// /// Return the current user number or 0 /// diff --git a/SharedDatabase/Entities/User.cs b/SharedDatabase/Entities/User.cs index d999a3a07..5c4dfea13 100644 --- a/SharedDatabase/Entities/User.cs +++ b/SharedDatabase/Entities/User.cs @@ -501,5 +501,10 @@ namespace SharedDatabase.Entities { return string.Format("{0}~{1}~{2}", UserName, FullName, legalizator); } + + public virtual string ToEncodedStr(string _legalizator) + { + return string.Format("{0}~{1}~{2}", UserName, FullName, _legalizator); + } } } diff --git a/SharedDatabase/Forms/PlainLoginDlg.Designer.cs b/SharedDatabase/Forms/PlainLoginDlg.Designer.cs new file mode 100644 index 000000000..6c4ba2142 --- /dev/null +++ b/SharedDatabase/Forms/PlainLoginDlg.Designer.cs @@ -0,0 +1,112 @@ +/// +/// Copyright (c) 2022 Sensus Slovensko a.s. +/// +namespace SharedDatabase.Forms +{ + partial class PlainLoginDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PlainLoginDlg)); + this.userNameLabel = new System.Windows.Forms.Label(); + this.passwordLabel = new System.Windows.Forms.Label(); + this.passwordTextBox = new System.Windows.Forms.TextBox(); + this.cancelButton = new System.Windows.Forms.Button(); + this.okButton = new System.Windows.Forms.Button(); + this.userNameTextBox = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // aliasLabel + // + resources.ApplyResources(this.userNameLabel, "aliasLabel"); + this.userNameLabel.Name = "aliasLabel"; + // + // passwordLabel + // + resources.ApplyResources(this.passwordLabel, "passwordLabel"); + this.passwordLabel.Name = "passwordLabel"; + // + // passwordTextBox + // + resources.ApplyResources(this.passwordTextBox, "passwordTextBox"); + this.passwordTextBox.Name = "passwordTextBox"; + this.passwordTextBox.UseSystemPasswordChar = true; + this.passwordTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.passwordTextBox_KeyPress); + // + // cancelButton + // + resources.ApplyResources(this.cancelButton, "cancelButton"); + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.Name = "cancelButton"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // okButton + // + resources.ApplyResources(this.okButton, "okButton"); + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.Name = "okButton"; + this.okButton.UseVisualStyleBackColor = true; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // userNameTextBox + // + resources.ApplyResources(this.userNameTextBox, "userNameTextBox"); + this.userNameTextBox.Name = "userNameTextBox"; + this.userNameTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.userNameTextBox_KeyPress); + // + // PlainLoginDlg + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.cancelButton; + this.Controls.Add(this.userNameTextBox); + this.Controls.Add(this.okButton); + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.passwordTextBox); + this.Controls.Add(this.passwordLabel); + this.Controls.Add(this.userNameLabel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Name = "PlainLoginDlg"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.PlainLoginDlg_FormClosing); + this.Load += new System.EventHandler(this.LoginDlg_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label userNameLabel; + private System.Windows.Forms.Label passwordLabel; + private System.Windows.Forms.TextBox userNameTextBox; + private System.Windows.Forms.TextBox passwordTextBox; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button okButton; + } +} \ No newline at end of file diff --git a/SharedDatabase/Forms/PlainLoginDlg.cs b/SharedDatabase/Forms/PlainLoginDlg.cs new file mode 100644 index 000000000..d2b85840a --- /dev/null +++ b/SharedDatabase/Forms/PlainLoginDlg.cs @@ -0,0 +1,315 @@ +/// +/// Copyright (c) 2022 Sensus Slovensko a.s. +/// +using System; +using System.Drawing; +using System.Windows.Forms; +using log4net; +using Common; +using GemCard; +using SharedDatabase.Entities; +using SharedDatabase.Resources; + +namespace SharedDatabase.Forms +{ + /// + /// Provides login dialog as well as user authorization using TBF.User.Authorize(...) + /// (i.e. when DialogResult is OK, user was authorized). + /// + public partial class PlainLoginDlg : Form + { + private static readonly ILog log = LogManager.GetLogger(typeof(PlainLoginDlg)); + + /// Public readonly + public string UserName { get { return user; } } + public string FullName { get { return fullName; } } + + /// Private fields + string user; + string password; + GID[] requiredGroupMembership; + bool noDatabase; + Color oriBackColor; + string fullName; /// Description of the selected user + + /// Smart card support, card S/N is used as user.Tag + CardNative card; + string smartCardReader; + + public LoginMethod Method; + public string VersionString; + + /// + /// Constructor. + /// + public PlainLoginDlg() + { + InitializeComponent(); + + oriBackColor = BackColor; + } + + /// + /// Constructor with a predefined user. + /// + public PlainLoginDlg(string predefinedUser, string prompt = null) + : this() + { + user = predefinedUser; + userNameTextBox.Text = predefinedUser; + if (prompt != null) Text = prompt; + } + + /// + /// Constructor with 'no Database' flag. + /// + public PlainLoginDlg(bool noDatabase, string prompt = null) + : this() + { + this.noDatabase = noDatabase; + if (prompt != null) Text = prompt; + } + + /// + /// Constructor when a specific group membership is required. + /// + public PlainLoginDlg(GID[] requiredGroupMembership, string prompt = null) + : this() + { + this.requiredGroupMembership = requiredGroupMembership; + if (prompt != null) Text = prompt; + } + + /// + /// Constructor with a predefined user when a specific group membership is required. + /// + public PlainLoginDlg(string predefinedUser, GID[] requiredGroupMembership, string prompt = null) + : this() + { + user = predefinedUser; + userNameTextBox.Text = predefinedUser; + this.requiredGroupMembership = requiredGroupMembership; + + Text = (prompt != null) ? prompt : Strings.User_Login + (string.IsNullOrEmpty(VersionString) ? "" : (" " + VersionString)); + } + + private void LoginDlg_Load(object sender, EventArgs e) + { + Localize(); + + if (user == null) + userNameTextBox.Select(); + else + passwordTextBox.Select(); + + /// + /// Smart card reader detection + /// + smartCardReader = null; /// null = No smart card reader detected + +#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL + try + { + card = new CardNative(); + + /// Find NFC smart card reader + string[] cardReaders = card.ListReaders(); + if (cardReaders != null) + { + foreach (var crd in cardReaders) + { + log.WarnFormat("SMART card reader found: {0}", crd); + } + + foreach (var crd in cardReaders) + { + if (crd.Contains("NFC")) + { + log.ErrorFormat("SMART card reader selected: {0}", crd); + smartCardReader = crd; /// NFC smart card reader detected + break; + } + } + } + + if (!string.IsNullOrEmpty(smartCardReader)) + { + /// Reader found, initialize NFC smart card reader + + card.OnCardInserted += delegate(object sndr, CardInsertedEventArgs args) + { + if (InvokeRequired) { Invoke(new EventHandler(OnCardInserted), sndr, args); } + else OnCardInserted(sndr, args); + }; + + card.OnCardRemoved += delegate(object sndr, CardRemovedEventArgs args) + { + if (InvokeRequired) { Invoke(new EventHandler(OnCardRemoved), sndr, args); } + else OnCardRemoved(sndr, args); + }; + + card.StartCardEvents(smartCardReader); + + Text += " (NFC)"; + } + } + catch (Exception) + { + smartCardReader = null; + } +#endif + } + + void Localize() + { + userNameLabel.Text = Strings.User_name; + passwordLabel.Text = Strings.Password; + okButton.Text = Strings.OkBtnText; + cancelButton.Text = Strings.CancelBtnText; + } + + /// + /// Try to authorize the user when OK clicked. + /// + private void okButton_Click(object sender, EventArgs e) + { + user = userNameTextBox.Text; + password = passwordTextBox.Text; + + bool authorized = Common.Utils.IsPowerUser(user, password); + if (authorized) fullName = "Power user"; + + if (!authorized && !noDatabase) + { + DBSettings[] dbs = new DBSettings[] { CurrentUser.RemoteUsersDB, CurrentUser.LocalUsersDB }; + + foreach (var db in dbs) + { + try + { + var usr1 = Entities.User.LoadUserByName(user, db); + + if (usr1.IsMemberOf(requiredGroupMembership) && usr1.IsCorrectPassword(password)) + { + authorized = true; + fullName = usr1.FullName; + break; + } + } + catch (Exception) { } + } + } + + if (authorized) + { + DialogResult = DialogResult.OK; + Close(); + return; + } + + MessageBox.Show(Strings.Invalid_username_or_password, Strings.Error, MessageBoxButtons.OK); + DialogResult = DialogResult.None; + return; + } + + /// + /// Cancel clicked, do not try to authorize. + /// + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + return; + } + + private void userNameTextBox_KeyPress(object sender, KeyPressEventArgs e) + { + if (Convert.ToInt32(e.KeyChar) == 13) + { + passwordTextBox.Focus(); + } + } + + private void passwordTextBox_KeyPress(object sender, KeyPressEventArgs e) + { + if (Convert.ToInt32(e.KeyChar) == 13) + { + okButton_Click(sender, e); + } + } + + + void OnCardInserted(object sender, CardInsertedEventArgs args) + { + string tag = string.Empty; + + try + { + BackColor = Color.Green; + card.Connect(smartCardReader, SHARE.Shared, PROTOCOL.T0orT1); + + /// Read the serial number of the card + APDUResponse response = card.Transmit(new APDUCommand(0xFF, 0xCA, 0x00, 0x00, null, 7)); + tag = response.ToString(); + + card.Disconnect(DISCONNECT.Leave); + } + catch + { + tag = string.Empty; + } + + DBSettings[] dbs = new DBSettings[] { CurrentUser.RemoteUsersDB, CurrentUser.LocalUsersDB }; + bool authorized = false; + AuthorizedAs authorizedAs = AuthorizedAs.RemoteUser; + /// + foreach (var db in dbs) + { + try + { + Entities.User loadedUser = Entities.User.LoadUserByTag(tag, db); + if (loadedUser != null) + { + authorized = (tag == loadedUser.Tag && loadedUser.IsMemberOf(requiredGroupMembership)); + + if (authorized) + { + user = loadedUser.UserName; + break; + } + } + } + catch (Exception) { } + + authorizedAs = AuthorizedAs.LocalUser; + } + + if (authorized) + { + CurrentUser.AuthorizedAs = authorizedAs; + DialogResult = DialogResult.OK; + Close(); + return; + } + + MessageBox.Show(Strings.Invalid_username_or_password, Strings.Error, MessageBoxButtons.OK); + DialogResult = DialogResult.None; + return; + } + + + void OnCardRemoved(object sender, CardRemovedEventArgs args) + { + BackColor = oriBackColor; + } + + private void PlainLoginDlg_FormClosing(object sender, FormClosingEventArgs e) + { + if (!string.IsNullOrEmpty(smartCardReader)) + { + try { card.StopCardEvents(); } + catch { } + } + } + } +} diff --git a/SharedDatabase/Forms/PlainLoginDlg.resx b/SharedDatabase/Forms/PlainLoginDlg.resx new file mode 100644 index 000000000..955e22ace --- /dev/null +++ b/SharedDatabase/Forms/PlainLoginDlg.resx @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + True + + + + 11, 24 + + + 58, 13 + + + 0 + + + User name + + + aliasLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + True + + + 11, 51 + + + 53, 13 + + + 1 + + + Password + + + passwordLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + + Top, Right + + + 150, 48 + + + 168, 20 + + + 3 + + + passwordTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + Top, Right + + + 336, 48 + + + 105, 28 + + + 5 + + + Cancel + + + cancelButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + Top, Right + + + 336, 14 + + + 105, 28 + + + 4 + + + OK + + + okButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Top, Right + + + 150, 22 + + + 168, 20 + + + 2 + + + userNameTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 6, 13 + + + 456, 88 + + + CenterScreen + + + User login + + + LoginDlg + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SharedDatabase/Resources/Strings.Designer.cs b/SharedDatabase/Resources/Strings.Designer.cs index 0a2ade5e9..4ef0ec213 100644 --- a/SharedDatabase/Resources/Strings.Designer.cs +++ b/SharedDatabase/Resources/Strings.Designer.cs @@ -115,7 +115,7 @@ namespace SharedDatabase.Resources { } /// - /// Looks up a localized string similar to calibration specialist. + /// Looks up a localized string similar to legalizator. /// internal static string calibration_specialist { get { diff --git a/SharedDatabase/Resources/Strings.resx b/SharedDatabase/Resources/Strings.resx index a7d0d7ed7..0ac104029 100644 --- a/SharedDatabase/Resources/Strings.resx +++ b/SharedDatabase/Resources/Strings.resx @@ -157,7 +157,7 @@ Are you sure? - calibration specialist + legalizator Cancel diff --git a/SharedDatabase/SharedDatabase.csproj b/SharedDatabase/SharedDatabase.csproj index 49746eb2f..76cfb96a3 100644 --- a/SharedDatabase/SharedDatabase.csproj +++ b/SharedDatabase/SharedDatabase.csproj @@ -102,6 +102,12 @@ PasswordChangeDlg.cs + + Form + + + PlainLoginDlg.cs + Form @@ -187,6 +193,9 @@ PasswordChangeDlg.cs + + PlainLoginDlg.cs + TripleLoginDlg.cs diff --git a/TBF/Properties/AssemblyInfo.cs b/TBF/Properties/AssemblyInfo.cs index 026ee9119..562d847a3 100644 --- a/TBF/Properties/AssemblyInfo.cs +++ b/TBF/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("3.5.1992.0")] -[assembly: AssemblyFileVersion("3.5.1992.0")] +[assembly: AssemblyVersion("3.5.1993.0")] +[assembly: AssemblyFileVersion("3.5.1993.0")] diff --git a/TBF/Rig/Sequences/MainSeq.cs b/TBF/Rig/Sequences/MainSeq.cs index c051e6131..28b04a488 100644 --- a/TBF/Rig/Sequences/MainSeq.cs +++ b/TBF/Rig/Sequences/MainSeq.cs @@ -1,5 +1,5 @@ /// -/// Copyright (c) 2013-2021 Sensus Slovensko a.s. +/// Copyright (c) 2013-2022 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; @@ -24,6 +24,9 @@ namespace TBF.Rig.Sequences public override string ToString() { return "Sequences.MainSeq"; } + bool isApprovedByLegalizator = false; + string legalizatorName = string.Empty; + DateTime lastApprovalByLegalizatorTime; int simultWithPurgingCount; Generic.IComponentCfg simultWithPurgingCfg; @@ -354,13 +357,24 @@ namespace TBF.Rig.Sequences StateMachine.Procedure = null; } } - catch (Exception) + catch (Exception exc) { + string msg = exc.Message; StateMachine.Procedure = null; } } while (StateMachine.Procedure == null); /// Make sure a valid procedure is selected +#if LANG_PL + /// + /// Approval of a legalizator + /// + if (!string.IsNullOrEmpty(StateMachine.Procedure.AltProcName) && !IsApprovedByLegalizator()) + { + goto select_procedure; /// Loop back to procedure selection if not approved by a legalizator + } +#endif + Debug.WriteLine(string.Empty); Debug.WriteLine(string.Format("TransitionSequences {0}", NHibernateUtil.IsInitialized(StateMachine.TransitionSequences) ? "initialized" : "NOT initialized")); Debug.WriteLine(string.Format("TransitionSteps {0}", NHibernateUtil.IsInitialized(StateMachine.TransitionSteps) ? "initialized" : "NOT initialized")); @@ -1458,6 +1472,27 @@ namespace TBF.Rig.Sequences } + bool IsApprovedByLegalizator() + { + if (isApprovedByLegalizator && DateTime.Now < lastApprovalByLegalizatorTime.Date.AddDays(1)) + { + return true; + } + + var loginDlg = new SharedDatabase.Forms.PlainLoginDlg(new GID[] { GID.CalibrationSpecialists }, "Approval by legalizator"); + if (loginDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) + { + isApprovedByLegalizator = true; + legalizatorName = loginDlg.FullName; + lastApprovalByLegalizatorTime = DateTime.Now; + return true; + } + + legalizatorName = string.Empty; + return false; + } + + /// /// MakeSelection() call context /// diff --git a/TBF/Rig/Sequences/MainSeqUtils.cs b/TBF/Rig/Sequences/MainSeqUtils.cs index 04b4cb97f..e86a87124 100644 --- a/TBF/Rig/Sequences/MainSeqUtils.cs +++ b/TBF/Rig/Sequences/MainSeqUtils.cs @@ -614,7 +614,7 @@ namespace TBF.Rig.Sequences (BenchInfo != null) ? BenchInfo.Address3 : string.Empty, (BenchInfo != null) ? BenchInfo.Address4 : string.Empty, (BenchInfo != null) ? BenchInfo.Address5 : string.Empty, - CurrentUser.UserName(), + CurrentUser.GetEncodedString(legalizatorName), CurrentUser.Number(), Program.Version, StateMachine.Procedure, diff --git a/TBF/UI/Shared/LoginDlgWithBenchSelection.cs b/TBF/UI/Shared/LoginDlgWithBenchSelection.cs index 32efd0759..f8fadfdce 100644 --- a/TBF/UI/Shared/LoginDlgWithBenchSelection.cs +++ b/TBF/UI/Shared/LoginDlgWithBenchSelection.cs @@ -55,7 +55,7 @@ namespace TBF.UI.Shared { benchName = predefinedBench; -#if LANG_PL || BAHRAIN_50 +#if BAHRAIN_50 Height = 156; EnableAndPrepareLegalizatorCombo(legalizatorComboBox); #else