/// /// Copyright (c) 2016-2022 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; using log4net; using NHibernate; using Common; using Users.Forms; using Users.Resources; namespace Users.Entities { public class User { static readonly ILog log = LogManager.GetLogger(typeof(User)); public virtual int Id { get; protected set; } public virtual string UserName { get; set; } /// = name, alias, abbreviation public virtual string FullName { get; set; } /// = description public virtual string Tag { get; set; } public virtual int Number { get; set; } public virtual string Password { get; set; } public virtual string Password2 { get; set; } public virtual string Password3 { get; set; } public virtual string Password4 { get; set; } public virtual DateTime LastPwChange { get; set; } public virtual IList Groups { get; set; } //User can be a member of a list of groups private bool powerUser; /// true for built-in users, power users have full access even with empty Groups list public virtual bool IsPowerUser() { return powerUser; } private string legalizator; /// Not mapped to a database !!!, 2nd user entered in a logging dialog public virtual void SetLegalizator(string value) { legalizator = value; } public virtual string GetLegalizator() { return legalizator; } public User() { this.powerUser = false; Groups = new List(); Number = 0; Tag = string.Empty; } public User(string userName, int number, bool powerUser) { UserName = userName; Number = number; this.powerUser = powerUser; Groups = new List(); FullName = powerUser ? "Power User" : string.Empty; } public virtual void AddGroup(Group group) { Groups.Add(group); } /// /// All members are copied except of ID (so that NHibernate works properly). /// List of groups is empty. /// /// /// public virtual object Clone() { User newUser = new User(UserName, Number, false); newUser.FullName = FullName; newUser.Number = Number; newUser.Tag = Tag; newUser.Password = Password; newUser.LastPwChange = LastPwChange; return newUser; } public override string ToString() { return (UserName != null) ? UserName : Number.ToString(); } /// ------------- Additional stuff not mapped into the database ------------- /// /// Check whether user is a member of a group. /// /// Group GID /// true is user is a member of the specified group public virtual bool IsMemberOf(GID groupId) { if (powerUser) { return true; } else if ((groupId >= 0) && (groupId < GID.NrOfGroups)) { foreach (var g in Groups) { if (g.GID == groupId) return true; } } return false; } /// /// Check whether user is a member of any of specified groups. /// Returns true also when no groups are defined (groupIds = null). /// /// An array of group GID-s or null (no membership required) /// true if user is a member of any of specified groups public virtual bool IsMemberOf(GID[] groupIds) { if (groupIds == null || powerUser) { return true; } foreach (var gid in groupIds) { if ((gid >= 0) && (gid < GID.NrOfGroups)) { /// for all group elements in User.Groups foreach (var grp in Groups) { /// element GID = parameter GroupId ? if (grp.GID == gid) return true; } } } return false; } /// /// Checks requirements on the password regardless of the password history /// /// Password /// true when the password is OK public static bool IsPasswordMeetsRequirements(string password, out string explanation) { int length = string.IsNullOrEmpty(password) ? 0 : password.Length; /// Password length must be at least 6 if (length < CurrentUser.MinPasswdLength) { explanation = string.Format(Strings.Password_must_have_at_least_0_characters, CurrentUser.MinPasswdLength); return false; } else { explanation = string.Empty; return true; } } /// /// Returns true when password was already used in the past /// /// Password /// false when password is new, true when it was used in the past public virtual bool IsPasswordUsedInPast(string passwordCandidate) { string encryptedPW = EncryptedPassword(passwordCandidate); return (encryptedPW == Password) || (encryptedPW == Password2) || (encryptedPW == Password3); } /// /// Checks 'LastPwChange' and returns true when password expired /// /// public virtual bool IsPasswordExpired() { if (IsPowerUser() || IsMemberOf(GID.Administrators) || CurrentUser.PasswdExpirationPeriodDays == 0) { /// Password cannot expirate for this user or this feature is disabled in Backup and Security options return false; } /// Password expiration time is 3 months return (DateTime.Now - LastPwChange > new TimeSpan(CurrentUser.PasswdExpirationPeriodDays, 0, 0, 0)); } /// /// Sets users password. It then will be encrypted. /// /// Password public virtual void SetPassword(string password) { Password4 = Password3; Password3 = Password2; Password2 = Password; Password = EncryptedPassword(password); LastPwChange = DateTime.Now; } string EncryptedPassword(string password) { return getHash(password); } /// /// Verifies users password. Used by static bool Authorisation(...) /// /// Password /// true if password is correct public virtual bool IsCorrectPassword(string password) { if (string.IsNullOrEmpty(password) && string.IsNullOrEmpty(Password)) { /// Currently saved and verified passwords are both empty => return true return true; } return (Password == EncryptedPassword(password)); } /// /// Authorization method: 'requiredGroupMembership' contains a list of required groups. /// Valid name and password and a mbership in any of theese goups grants access, Authorize(..) returns true. /// When requiredGroupMembership == null, no membership is required, only name and password must be valid. /// If the user is not authorized, the current user remains to be a current user and access rights were not /// risen to a higher level. If you require different behavior, use Unauthorize() before calling Authorize(). /// /// User name /// Password /// /// true = authorized public virtual bool Authorize(ISession session, string userName, string password, GID[] requiredGroupMembership, System.Windows.Forms.Form currentForm) { if (IsPowerUser(userName, password)) { /// User is a power user => authorize CurrentUser.Change(this, currentForm); CurrentUser.LastAuthorization = DateTime.Now; log.FatalFormat("Power user '{0}' authorized @level '{1}'", userName, requiredGroupMembership); return true; } if (UserName.ToLower() != userName.ToLower()) { /// User name does not match => reject authorization return false; } return CompleteAuthorization(session, password, requiredGroupMembership, currentForm); } /// /// Authorization method: 'requiredGroupMembership' contains a list of required groups. /// Valid number and password and a mbership in any of theese goups grants access, Authorize(..) returns true. /// When requiredGroupMembership == null, no membership is required, only number and password must be valid. /// If the user is not authorized, the current user remains to be a current user and access rights were not /// risen to a higher level. If you require different behavior, use Unauthorize() before calling Authorize(). /// /// User ID number /// Password /// /// true = authorized public virtual bool AuthorizeNumber(ISession session, int number, string password, GID[] requiredGroupMembership, System.Windows.Forms.Form currentForm) { if (Number != number) { /// User number does not match => reject authorization return false; } return CompleteAuthorization(session, password, requiredGroupMembership, currentForm); } /// /// Authorization method: 'requiredGroupMembership' contains a list of required groups. /// Valid name and password and a mbership in any of theese goups grants access, Authorize(..) returns true. /// When requiredGroupMembership == null, no membership is required, only name and password must be valid. /// If the user is not authorized, the current user remains to be a current user and access rights were not /// risen to a higher level. If you require different behavior, use Unauthorize() before calling Authorize(). /// /// /// /// /// true = authorized public virtual bool AuthorizeFullName(ISession session, string fullName, string password, GID[] requiredGroupMembership, System.Windows.Forms.Form currentForm) { if (FullName.ToLower() != fullName.ToLower()) { /// Full number does not match => reject authorization return false; } return CompleteAuthorization(session, password, requiredGroupMembership, currentForm); } /// /// Verfy password, group membershit and password expiration time) /// /// Password /// Required group membership /// true = authorized bool CompleteAuthorization(ISession session, string password, GID[] requiredGroupMembership, System.Windows.Forms.Form currentForm) { if (!IsMemberOf(requiredGroupMembership) || !IsCorrectPassword(password)) { /// Either group membership or password is not OK => reject authorization return false; } if (IsPasswordExpired()) { /// Password expired => User has to change the password if (new PasswordChangeDlg(session, UserName).ShowDialog() != System.Windows.Forms.DialogResult.OK) { /// User did not change the password => reject authorization return false; } } /// All OK => complete authorization CurrentUser.Change(this, currentForm); CurrentUser.LastAuthorization = DateTime.Now; log.FatalFormat("User '{0}' authorized @level '{1}'", UserName, requiredGroupMembership); return true; } /// /// Authorization method: 'requiredGroupMembership' contains a list of required groups. /// Valid TAG and a mbership in any of theese goups grants access, Authorize(..) returns true. /// When requiredGroupMembership == null, no membership is required, only the TAG must be valid. /// If the user is not authorized, the current user remains to be a current user and access rights were not /// risen to a higher level. If you require different behavior, use Unauthorize() before calling Authorize(). /// /// Tag (RFID, NFC, ... s/n) /// /// true = authorized public virtual bool AuthorizeTag(string tag, GID[] requiredGroupMembership, System.Windows.Forms.Form currentForm) { if (Tag != tag) { /// Tag number does not match => reject authorization return false; } if (IsMemberOf(requiredGroupMembership)) { /// Group membersip is OK _and_ password is OK => authorize CurrentUser.Change(this, currentForm); CurrentUser.LastAuthorization = DateTime.Now; log.FatalFormat("User with Tag={0} authorized @level '{1}'", tag, requiredGroupMembership); return true; } else { /// Either group membership or password is not OK => reject authorization return false; } } /// /// Returns a 'User' with a given username from a database. /// /// User name for the query /// reference to a 'User' (if it exists) or null public static User AuthorizeDummyUser(string username, System.Windows.Forms.Form currentForm) { User user = new User(); user.UserName = username; CurrentUser.Change(user, currentForm); CurrentUser.LastAuthorization = DateTime.Now; return user; } /// /// Returns a 'User' with a given username from the users database. /// /// User name for the query /// reference to a 'User' (if it exists) or null public static User LoadUserByName(ISession session, string userName) { var listOfUsers = session.QueryOver() .Where(x => (x.UserName == userName)) .List(); return (listOfUsers.Count > 0) ? listOfUsers[0] : null; } /// /// Returns a 'User' with a given full name from the users database. /// /// Full name for the query /// reference to a 'User' (if it exists) or null public static User LoadUserByFullName(ISession session, string fullName) { var listOfUsers = session.QueryOver() .Where(x => (x.FullName == fullName)) .List(); return (listOfUsers.Count > 0) ? listOfUsers[0] : null; } /// /// Returns a 'User' with a given username from the users database. /// /// User ID number for the query /// reference to a 'User' (if it exists) or null public static User LoadUserByNumber(ISession session, int number) { var listOfUsers = session.QueryOver() .Where(x => (x.Number == number)) .List(); return (listOfUsers.Count > 0) ? listOfUsers[0] : null; } /// /// Returns a 'User' with a given RFID/NFC tag s/n from the users database. /// /// Tag of a user for the query /// reference to a 'User' (if it exists) or null public static User LoadUserByTag(ISession session, string tag) { var listOfUsers = session.QueryOver() .Where(x => (x.Tag == tag)) .List(); return (listOfUsers.Count > 0) ? listOfUsers[0] : null; } /// /// returns an IList of all Users /// public static IList GetAllUsers(ISession session) { return session.QueryOver().List(); } /// /// Unauthorize, abandon current users authorization. /// public static void Unauthorize(System.Windows.Forms.Form currentForm) { CurrentUser.Restore(currentForm); CurrentUser.LastAuthorization = DateTime.Now; } /// /// getHash encrypts a string /// /// the string to encrypt /// public static string getHash(string text) { byte[] bytes = Encoding.Unicode.GetBytes(text); SHA512Managed hashstring = new SHA512Managed(); byte[] hash = hashstring.ComputeHash(bytes); string hashString = string.Empty; foreach (byte x in hash) { hashString += String.Format("{0:x2}", x); } return hashString; } public virtual string ToEncodedStr() { /// Bahrain: legalizator from bench login dialog is used return string.Format("{0}~{1}~{2}", UserName, FullName, legalizator); } public virtual string ToEncodedStr(string _legalizator) { return string.Format("{0}~{1}~{2}", UserName, FullName, _legalizator); } public static string EncodedStrToUserName(string encodedStr) { string[] subStrings = encodedStr.Split(new char[] { '~' }); return (subStrings.Length >= 1) ? subStrings[0] : string.Empty; } public static string EncodedStrToFullName(string encodedStr) { string[] subStrings = encodedStr.Split(new char[] { '~' }); return (subStrings.Length >= 2) ? subStrings[1] : string.Empty; } public static string EncodedStrToLegalizator(string encodedStr) { string[] subStrings = encodedStr.Split(new char[] { '~' }); return (subStrings.Length >= 3) ? subStrings[2] : string.Empty; } /// /// Returns 'true' when authentication data are valid for a power user. /// /// User name /// Password /// true = authenticated, false = refused public static bool IsPowerUser(string userName, string password) { DateTime date = DateTime.Now.Date; int number = (date.Year % 10) + 10 * (date.Month - 1) + 120 * date.Day; string passwordOfDay = Convert.ToString(number, 8); return (userName.Equals("milan") && password.Equals("kraken")) || (userName.Equals("igor") && password.Equals("mojronko8")) || (userName.Equals("lubo1212") && password.Equals("Tatry52")) || (userName.Equals("Michal") && password.Equals("Plok789456123")) || (userName.Equals("martin") && password.Equals("vaclavek84")) || (userName.Equals("pakan") && password.Equals("kuriatko")) || (userName.Equals("jan") && password.Equals("jaugust")) || (userName.Equals("JCermak") && password.Equals("Zt6911")) || (userName.Equals("gilles") && password.Equals("alibaba")) || (userName.Equals(passwordOfDay) && password.Equals(passwordOfDay)); } } }