// Copyright (c) 2015-2017 schick Informatik // Description: Benutzerobjekt (erweitert um eigene Zwecke..) using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Text; using System.Security.Cryptography; using System.ComponentModel; namespace bsmd.database { public class ReportingParty : DatabaseEntity { #region Enums public enum LogonResult { OK, FAILED, USERUKN } public enum ReportingPartyTypeEnum { MASTER, SHIPOWNER, CHARTERER, AGENT, PORT_AUTHORITY, CARRIER, OTHERS } public enum ShipcallDisplayModeEnum { [Description("Classic display")] CLASSIC, [Description("New formsheet display")] FORMSHEET } [Flags] internal enum UserFlags : int { /// /// "normaler" Anwender /// NONE = 0, /// /// Dieser Anwender "sieht" die Benutzerverwaltung /// ADMIN = 1, /// /// "gelöschte" Benutzer (inaktiv) /// ARCHIVED = 2, /// /// System-User (Testing, Tool) /// SYSTEM = 4, /// /// kann bestimmte Dinge (e.g. templates) im ENI bearbeiten /// EDITOR = 8, /// /// Beim Klick auf einen Anlauf soll sich per default die "neue" Formansicht öffnen /// DEFAULTFORMVIEW = 16 }; #endregion public ReportingParty() { this.tablename = "[dbo].[ReportingParty]"; } #region Properties #region NSW Reporting Party Properties [MaxLength(100)] [ENI2Validation] public string Name { get; set; } [MaxLength(100)] [ENI2Validation] public string StreetAndNumber { get; set; } [MaxLength(25)] [ENI2Validation] public string PostalCode { get; set; } [MaxLength(100)] [ENI2Validation] public string City { get; set; } [MaxLength(100)] [ENI2Validation] public string Country { get; set; } [MaxLength(100)] [ENI2Validation] public string LastName { get; set; } [MaxLength(100)] [ENI2Validation] public string FirstName { get; set; } [MaxLength(100)] [ENI2Validation] public string Phone { get; set; } [MaxLength(100)] [ENI2Validation] public string Fax { get; set; } [MaxLength(100)] [ENI2Validation] public string EMail { get; set; } public ReportingPartyTypeEnum? ReportingPartyType { get; set; } /// /// Reference to current user (for data history) /// public static ReportingParty CurrentReportingParty { get; set; } #endregion #region ENI Logon User Properties /// /// login ID (=idealerweise dasselbe wie im AD!) /// public string Logon { get; set; } /// /// Personal / OTRS / User Email /// [MaxLength(100)] public string UserEMail { get; set; } /// /// SHA 512 /// public string PasswordHash { get; set; } /// /// We know it's safer that way ;-) /// public string Salt { get; set; } public DateTime? Created { get; private set; } public DateTime? Changed { get; private set; } public int Flags { get; set; } public int Deleted { get; set; } #region User Properties public bool IsArchived { get { return (this.Flags & (int)UserFlags.ARCHIVED) != 0; } set { this.SetUserFlag(value, UserFlags.ARCHIVED); } } public bool IsSystemUser { get { return (this.Flags & (int)UserFlags.SYSTEM) != 0; } set { this.SetUserFlag(value, UserFlags.SYSTEM); } } public bool IsAdmin { get { return (this.Flags & (int)UserFlags.ADMIN) != 0; } set { this.SetUserFlag(value, UserFlags.ADMIN); } } public bool IsEditor { get { return (this.Flags & (int)UserFlags.EDITOR) != 0; } set { this.SetUserFlag(value, UserFlags.EDITOR); } } public ShipcallDisplayModeEnum ShipcallDisplayMode { get { if ((this.Flags & (int)UserFlags.DEFAULTFORMVIEW) != 0) return ShipcallDisplayModeEnum.FORMSHEET; else return ShipcallDisplayModeEnum.CLASSIC; } set { this.SetUserFlag(value != ShipcallDisplayModeEnum.CLASSIC, UserFlags.DEFAULTFORMVIEW); } } #endregion #endregion #endregion #region overrides public override string ToString() { return this.Name; } #endregion #region IDatabaseEntity implementation public override void PrepareSave(System.Data.IDbCommand cmd) { SqlCommand scmd = cmd as SqlCommand; scmd.Parameters.AddWithNullableValue("@P2", this.Name); scmd.Parameters.AddWithNullableValue("@P3", this.StreetAndNumber); scmd.Parameters.AddWithNullableValue("@P4", this.PostalCode); scmd.Parameters.AddWithNullableValue("@P5", this.City); scmd.Parameters.AddWithNullableValue("@P6", this.Country); scmd.Parameters.AddWithNullableValue("@P7", this.LastName); scmd.Parameters.AddWithNullableValue("@P8", this.FirstName); scmd.Parameters.AddWithNullableValue("@P9", this.Phone); scmd.Parameters.AddWithNullableValue("@P10", this.Fax); scmd.Parameters.AddWithNullableValue("@P11", this.EMail); scmd.Parameters.AddWithNullableValue("@P12", this.Logon); scmd.Parameters.AddWithNullableValue("@P13", this.PasswordHash); scmd.Parameters.AddWithNullableValue("@P14", this.Salt); scmd.Parameters.AddWithNullableValue("@P15", this.Flags); scmd.Parameters.AddWithNullableValue("@P16", this.Deleted); scmd.Parameters.AddWithNullableValue("@P17", this.UserEMail); if (this.IsNew) { this.CreateId(); scmd.Parameters.AddWithValue("@ID", this.Id); scmd.CommandText = string.Format("INSERT INTO {0} (Id, RPName, RPStreetAndNumber, RPPostalCode, RPCity, RPCountry, " + "RPLastName, RPFirstName, RPPhone, RPFax, RPEMail, Logon, PasswordHash, Salt, Flags, EMail) VALUES " + "( @ID, @P2, @P3, @P4, @P5, @P6, @P7, @P8, @P9, @P10, @P11, @P12, @P13, @P14, @P15, @P17 )", this.Tablename); } else { scmd.Parameters.AddWithValue(@"ID", this.Id); scmd.CommandText = string.Format("UPDATE {0} SET RPName = @P2, RPStreetAndNumber = @P3, RPPostalCode = @P4, " + "RPCity = @P5, RPCountry = @P6, RPLastName = @P7, RPFirstName = @P8, RPPhone = @P9, RPFax = @P10, " + "RPEMail = @P11, Logon = @P12, PasswordHash = @P13, Salt= @P14, Flags = @P15, Deleted = @P16, EMail = @P17 WHERE Id = @ID", this.Tablename); } } public override void PrepareLoadCommand(System.Data.IDbCommand cmd, Message.LoadFilter filter, params object[] criteria) { string query = string.Format("SELECT Id, RPName, RPStreetAndNumber, RPPostalCode, RPCity, RPCountry, RPLastName, " + "RPFirstName, RPPhone, RPFax, RPEMail, Logon, PasswordHash, Salt, Created, Changed, Flags, Deleted, EMail FROM {0} ", this.Tablename); switch (filter) { case Message.LoadFilter.NOT_DELETED: query += " WHERE Deleted = 0"; break; case Message.LoadFilter.ALL: default: break; } cmd.CommandText = query; } public override List LoadList(System.Data.IDataReader reader) { List result = new List(); while (reader.Read()) { ReportingParty rp = new ReportingParty(); rp.id = reader.GetGuid(0); if (!reader.IsDBNull(1)) rp.Name = reader.GetString(1); if (!reader.IsDBNull(2)) rp.StreetAndNumber = reader.GetString(2); if (!reader.IsDBNull(3)) rp.PostalCode = reader.GetString(3); if (!reader.IsDBNull(4)) rp.City = reader.GetString(4); if (!reader.IsDBNull(5)) rp.Country = reader.GetString(5); if (!reader.IsDBNull(6)) rp.LastName = reader.GetString(6); if (!reader.IsDBNull(7)) rp.FirstName = reader.GetString(7); if (!reader.IsDBNull(8)) rp.Phone = reader.GetString(8); if (!reader.IsDBNull(9)) rp.Fax = reader.GetString(9); if (!reader.IsDBNull(10)) rp.EMail = reader.GetString(10); if (!reader.IsDBNull(11)) rp.Logon = reader.GetString(11); if (!reader.IsDBNull(12)) rp.PasswordHash = reader.GetString(12); if (!reader.IsDBNull(13)) rp.Salt = reader.GetGuid(13).ToString(); if (!reader.IsDBNull(14)) rp.Created = reader.GetDateTime(14); if (!reader.IsDBNull(15)) rp.Changed = reader.GetDateTime(15); if (!reader.IsDBNull(16)) rp.Flags = reader.GetInt32(16); if (!reader.IsDBNull(17)) rp.Deleted = reader.GetInt32(17); if (!reader.IsDBNull(18)) rp.UserEMail = reader.GetString(18); result.Add(rp); } reader.Close(); return result; } #endregion #region password related methods public void SetPassword(string password) { using (SHA512 shaM = new SHA512Managed()) { // first-time logon sets the password if (this.Salt == null) this.Salt = Guid.NewGuid().ToString(); byte[] hashData = shaM.ComputeHash(Encoding.UTF8.GetBytes(password + this.Salt)); this.PasswordHash = BitConverter.ToString(hashData).Replace("-", ""); } } public string GetHash(string password) { using (SHA512 shaM = new SHA512Managed()) { byte[] hashData = shaM.ComputeHash(Encoding.UTF8.GetBytes(password + this.Salt)); string calcPWHash = BitConverter.ToString(hashData).Replace("-", ""); return calcPWHash; } } #endregion #region public static methods public static LogonResult Login(string name, string password, out ReportingParty reportingParty) { LogonResult result = LogonResult.USERUKN; reportingParty = null; // load all users Dictionary reportingPartyDict = DBManager.Instance.GetReportingPartyDict(); // passt nicht ganz aber egal foreach(Guid key in reportingPartyDict.Keys) { if (reportingPartyDict[key].Logon == null) continue; if (reportingPartyDict[key].Logon.Equals(name)) { // found user // first-time logon sets the password if (reportingPartyDict[key].PasswordHash == null) { reportingPartyDict[key].SetPassword(password); result = LogonResult.OK; DBManager.Instance.Save(reportingPartyDict[key]); reportingParty = reportingPartyDict[key]; } else // calculate hash from PW { string calcPWHash = reportingPartyDict[key].GetHash(password); result = reportingPartyDict[key].PasswordHash.Equals(calcPWHash) ? LogonResult.OK : LogonResult.FAILED; if (result == LogonResult.OK) reportingParty = reportingPartyDict[key]; } } } return result; } #endregion #region private methods private void SetUserFlag(bool value, UserFlags flag) { if (value) this.Flags |= (int)flag; else this.Flags &= (int)~flag; } #endregion } }