using System; using System.Collections.Generic; using Sarand.Net.Standard.Base.App; using Sarand.Net.Standard.Base.Core; using Sarand.Net.Standard.Base.Bus; using Sarand.Net.Standard.Base.Dbas; using Sarand.Net.Standard.Base.Security; using Sarand.Net.Standard.Dbas.Utils; using Sarand.Net.Standard.Base.Utils; namespace Sarand.Net.Standard.Dbas.Security { //======================================================================= public abstract class SaSecurityConsole_Dbas : SaSecurityConsole { //------------------------------------------------------------------- // Data members. private SaSecurityMgr_Dbas securityMgr = null; //------------------------------------------------------------------- // Protected construction - use derived class. protected SaSecurityConsole_Dbas(ISacsDatabase database) { Database = database; // Initialise security manager. securityMgr = new SaSecurityMgr_Dbas(this); } protected override void Dispose(bool disposing) { if (disposing) { if (securityMgr != null) securityMgr.Dispose(); securityMgr = null; } base.Dispose(disposing); } //------------------------------------------------------------------- // Database properties. internal ISacsDatabase Database { get; set; } public override bool DatabaseIsValid { get { return securityMgr.DatabaseIsValid; } } public override bool CanUpdateDatabase { get { return securityMgr.CanUpdateDatabase; } } public override bool ColumnExists(SaSecurityDbDfn.ColumnIdx columnIdx) { return Database != null && Database.ColumnExists(SaSecurityDbDfn.GetTableName(SaSecurityDbDfn.GetTableForColumn(columnIdx), false), SaSecurityDbDfn.GetColumnName(columnIdx, false)); } //------------------------------------------------------------------- // A p p l i c a t i o n I n t e r f a c e //------------------------------------------------------------------- // Show User Login form. protected delegate bool ShowUserLoginFormFunction(SaSecurityConsole securityConsole, DbUpdateInfo dbUpdateInfo); protected abstract ShowUserLoginFormFunction ShowUserLoginFormFn { get; } // Manage security. public override bool ShowUserLoginForm(DbUpdateInfo dbUpdateInfo) { ClearErrorState(); if (ShowUserLoginFormFn != null) return ShowUserLoginFormFn(this, dbUpdateInfo); return false; } //------------------------------------------------------------------- // Method to display Security management form. protected delegate bool ShowManageSecurityDialogFunction(SaSecurityConsole securityConsole, SaSecurityMgr securityMgr, bool userCanManageSecurity, DbUpdateInfo dbUpdateInfo); protected abstract ShowManageSecurityDialogFunction ShowManageSecurityDialogFn { get; } // Manage security. public override bool ManageSecurity(bool userCanManageSecurity, DbUpdateInfo dbUpdateInfo) { ClearErrorState(); if (ShowManageSecurityDialogFn != null) return ShowManageSecurityDialogFn(this, securityMgr, userCanManageSecurity, dbUpdateInfo); return false; } //------------------------------------------------------------------- public override bool ShowChangePasswordForm(DbUpdateInfo dbUpdateInfo) { ClearErrorState(); throw new NotImplementedException(); } //------------------------------------------------------------------- // A p p l i c a t i o n S e c u r i t y R i g h t s //------------------------------------------------------------------- public override bool RequiresPopulation() { ClearErrorState(); if (SecurityRights.Count == 0) return false; foreach (SaSecurityRight securityRight in SecurityRights) { if (!securityMgr.SecurityItemExistsByTypeCode(SaSecurity.ItemType.Right, securityRight.Code)) return true; } return false; } public override bool PopulateSecurityRights(DbUpdateInfo dbUpdateInfo) { ClearErrorState(); if (SecurityRights.Count == 0) return false; foreach (SaSecurityRight securityRight in SecurityRights) { if (securityMgr.SecurityItemExistsByTypeCode(SaSecurity.ItemType.Right, securityRight.Code)) continue; SaSecurityItem securityItem = securityMgr.CreateSecurityItem(SaSecurity.ItemType.Right); securityItem.Code = securityRight.Code; securityItem.Description = securityRight.Desc; securityItem.DataItemType = securityRight.DataItemType; if (!securityMgr.InsertSecurityItem(securityItem, dbUpdateInfo)) return SetErrorState(securityMgr.ErrorStateMessage); } // Ensure that there is a 'Superuser' group with all rights. if (!HasErrorState()) PopulateSuperGroup(dbUpdateInfo); // Create the 'admin' user. if (!HasErrorState()) PopulateAdminUser(dbUpdateInfo); return !HasErrorState(); } private bool PopulateSuperGroup(DbUpdateInfo dbUpdateInfo) { ClearErrorState(); SaSecurityItem superGroup = securityMgr.GetSecurityItemByTypeCode(SaSecurity.ItemType.Group, GroupSuperCode); if (superGroup == null) { superGroup = securityMgr.CreateSecurityItem(SaSecurity.ItemType.Group); superGroup.Code = GroupSuperCode; superGroup.Description = "Superuser"; if (!securityMgr.InsertSecurityItem(superGroup, dbUpdateInfo)) return SetErrorState(securityMgr.ErrorStateMessage); } if (superGroup != null) { // Create a link with each right in the list. SaSecurityItem.Params prmSecItem = new SaSecurityItem.Params(); prmSecItem.SecurityItemType = SaSecurity.ItemType.Right; foreach (SaSecurityItem securityItem in securityMgr.GetSecurityItemList(prmSecItem)) { // Assign right to the superuser group, apart from those that specify a data item type. SysId securityRightId = securityItem.Id; if (SysId.IsValid(securityRightId) && securityItem.DataItemType < 1 && !securityMgr.SecurityItemHasLinksWith(superGroup.Id, securityRightId)) { SaSecurityLink superGroupRight = securityMgr.CreateSecurityLink(superGroup.Id, securityRightId, null); if (!securityMgr.InsertSecurityLink(superGroupRight, dbUpdateInfo)) return SetErrorState(securityMgr.ErrorStateMessage); } } } return !HasErrorState(); } private bool PopulateAdminUser(DbUpdateInfo dbUpdateInfo) { ClearErrorState(); SaSecurityItem user = null; if (!securityMgr.SecurityItemExistsByTypeCode(SaSecurity.ItemType.User, AdminUserCode)) { // Create the admin user. user = securityMgr.CreateSecurityItem(SaSecurity.ItemType.User); user.Code = AdminUserCode; user.Description = ""; user.Location = ""; user.PasswordEncrypted = SaSecurityItem.EncryptPassword(AdminUserCode); if (!securityMgr.InsertSecurityItem(user, dbUpdateInfo)) return SetErrorState(securityMgr.ErrorStateMessage); } // Retrieve the user (even if just created). user = securityMgr.GetSecurityItemByTypeCode(SaSecurity.ItemType.User, AdminUserCode); if (user != null) { // Give this user superuser rights. SaSecurityItem superGroup = securityMgr.GetSecurityItemByTypeCode(SaSecurity.ItemType.Group, GroupSuperCode); if (superGroup != null) { if (!securityMgr.SecurityItemHasLinksWith(user.Id, superGroup.Id)) { SaSecurityLink userSuperGroup = securityMgr.CreateSecurityLink(user.Id, superGroup.Id, null); if (!securityMgr.InsertSecurityLink(userSuperGroup, dbUpdateInfo)) return SetErrorState(securityMgr.ErrorStateMessage); } } } return !HasErrorState(); } //------------------------------------------------------------------- // A p p l i c a t i o n D a t a I t e m s //------------------------------------------------------------------- //------------------------------------------------------------------- // L o g i n //------------------------------------------------------------------- public override bool LoginUser(SysId userId, bool recordLastLogin = true) { String fn = GetType().Name + ".LoginUser"; ClearErrorState(); using (SaSecurityItem secItemUser = securityMgr.GetSecurityItemById(userId)) { if (secItemUser == null || secItemUser.ItemType != SaSecurity.ItemType.User || !secItemUser.IsStatusEnabled) { SaLogger.Error(fn + " Failed to retrieve user for login. Id: " + SysId.ToString(userId) + " - " + securityMgr.ErrorStateMessage, true); return SetErrorState("Invalid credentials supplied"); } if (recordLastLogin) { secItemUser.LastLogin = DateTime.Now; if (!securityMgr.UpdateSecurityItem(secItemUser, new DbUpdateInfo(secItemUser.Id, secItemUser.Description, SacsSystem.ComputerName))) SaLogger.Error(fn + " Failed to update user on login. Id: " + SysId.ToString(userId) + "' - " + securityMgr.ErrorStateMessage, true); } OnLogin(secItemUser != null ? secItemUser.Id : null); } return true; } public override bool LoginAuthenticatedUser() { String fn = GetType().Name + ".LoginAuthenticatedUser"; ClearErrorState(); String userCode = System.Environment.UserName; SaSecurityItem secItem = securityMgr.GetSecurityItemByTypeCode(SaSecurity.ItemType.User, userCode); if (secItem != null) { secItem.LastLogin = DateTime.Now; if (!securityMgr.UpdateSecurityItem(secItem, new DbUpdateInfo(secItem.Id, secItem.Description, SacsSystem.ComputerName))) SaLogger.Error(fn + " Failed to update user '" + userCode + "' - " + securityMgr.ErrorStateMessage, true); } else { // Create user. secItem = securityMgr.CreateSecurityItem(SaSecurity.ItemType.User); secItem.Code = userCode; secItem.Description = StringUtil.OnEmpty(SystemUtil.GetUserDisplayName(), userCode); secItem.LastLogin = DateTime.Now; secItem.AuthenticatedUser = true; if (!securityMgr.InsertSecurityItem(secItem, new DbUpdateInfo(new SysId(), secItem.Description, SacsSystem.ComputerName))) { SaLogger.Error(fn + " Failed to create user '" + userCode + "' - " + securityMgr.ErrorStateMessage, true); secItem = null; } } OnLogin(secItem != null ? secItem.Id : null); return !HasErrorState(); } //------------------------------------------------------------------- /// Logout - Clear user and security details. public override bool LogoutUser() { OnLogout(); return true; } //------------------------------------------------------------------- // S e c u r i t y P r o f i l e s //------------------------------------------------------------------- private SaSecurityProfile hostSecurityProfile; /// Retrieve security profile for host computer public override SaSecurityProfile GetHostSecurityProfile() { ClearErrorState(); if (hostSecurityProfile == null) { String hostCode = System.Environment.MachineName; hostSecurityProfile = GetSecurityProfile(securityMgr.GetSecurityItemByTypeCode(SaSecurity.ItemType.Computer, hostCode)); } return hostSecurityProfile; } /// Retrieve security profile for specified user public override SaSecurityProfile GetUserSecurityProfile(SysId userId) { ClearErrorState(); return GetSecurityProfile(securityMgr.GetSecurityItemById(userId)); } private SaSecurityProfile GetSecurityProfile(SaSecurityItem secItem) { String fn = GetType().Name + ".PopulateSecurityProfile"; if (secItem == null || !SysId.IsValid(secItem.Id)) return null; if (LogSecurityProfile) SaLogger.Info(fn + " Populating security profile for user " + secItem.Code + " '" + secItem.Description + "'"); // Retrieve Group links associated with the Item. SaSecurityLink.Params prmSecLinkGroups = new SaSecurityLink.Params(); prmSecLinkGroups.includedItemIdsOwner.Add(secItem.Id); prmSecLinkGroups.TargetItemType = SaSecurity.ItemType.Group; List groupLinks = securityMgr.GetSecurityLinkList(prmSecLinkGroups); // Retrieve Right links associated with the Item and its Groups. SaSecurityLink.Params prmSecLinkRights = new SaSecurityLink.Params(); prmSecLinkRights.includedItemIdsOwner.Add(secItem.Id); prmSecLinkRights.includedItemIdsOwner.AddRange(groupLinks.GetTargetItemIds()); prmSecLinkRights.TargetItemType = SaSecurity.ItemType.Right; List rightLinks = securityMgr.GetSecurityLinkList(prmSecLinkRights); // Retrieve security Group and Right items. SaSecurityItem.Params prmSecItem = new SaSecurityItem.Params(); prmSecItem.IncludedIds.AddRange(groupLinks.GetTargetItemIds()); prmSecItem.IncludedIds.AddRange(rightLinks.GetTargetItemIds()); List secItems = securityMgr.GetSecurityItemList(prmSecItem); // Add the Groups to the profile. List profileGroups = new List(); foreach (SaSecurityLink secGroupLink in groupLinks) { // Retrieve Group. SaSecurityItem secGroup = secItems.Find(item => item.Id.Equals(secGroupLink.ItemIdTarget) && item.ItemType == SaSecurity.ItemType.Group); if (secGroup == null) { SaLogger.Warn(fn + " Failed to retrieve security group. Id: " + SysId.ToString(secGroupLink.ItemIdTarget)); continue; } if (LogSecurityProfile) SaLogger.Info(fn + " Adding group to profile: " + secGroup.Code + " '" + secGroup.Description + "'"); // Retrieve rights for group. List profileGroupRights = new List(); foreach (SaSecurityLink secRightLink in rightLinks.FindAll(item => item.ItemIdOwner.Equals(secGroup.Id))) { // Retrieve Right. SaSecurityItem secRight = secItems.Find(item => item.Id.Equals(secRightLink.ItemIdTarget) && item.ItemType == SaSecurity.ItemType.Right); if (secRight == null) { SaLogger.Warn(fn + " Failed to retrieve security group right. Id: " + SysId.ToString(secRightLink.ItemIdTarget)); continue; } bool rightGranted = (secRightLink.Status == SaStatus.Granted); if (LogSecurityProfile) SaLogger.Info(fn + " Adding group right to profile: " + secRight.Code + " '" + secRight.Description + "' [" + (rightGranted ? "Granted" : "Denied") + "]"); try { SaSecurityProfile.RightData rightData = new SaSecurityProfile.RightData(secRight, secRightLink); profileGroupRights.Add(rightData); } catch (Exception exc) { SaLogger.Warn(fn + " " + exc.Message); } } try { SaSecurityProfile.GroupData groupData = new SaSecurityProfile.GroupData(secGroup, profileGroupRights); profileGroups.Add(groupData); } catch (Exception exc) { SaLogger.Warn(fn + " " + exc.Message); } } // Add the Rights to the profile. List profileRights = new List(); foreach (SaSecurityLink secRightLink in rightLinks.FindAll(item => item.ItemIdOwner.Equals(secItem.Id))) { // Retrieve Right. SaSecurityItem secRight = secItems.Find(item => item.Id.Equals(secRightLink.ItemIdTarget) && item.ItemType == SaSecurity.ItemType.Right); if (secRight == null) { SaLogger.Warn(fn + " Failed to retrieve security right. Id: " + SysId.ToString(secRightLink.ItemIdTarget)); continue; } bool rightGranted = (secRightLink.Status == SaStatus.Granted); if (LogSecurityProfile) SaLogger.Info(fn + " Adding right to profile: " + secRight.Code + " '" + secRight.Description + "' [" + (rightGranted ? "Granted" : "Denied") + "]"); try { SaSecurityProfile.RightData rightData = new SaSecurityProfile.RightData(secRight, secRightLink); profileRights.Add(rightData); } catch (Exception exc) { SaLogger.Warn(fn + " " + exc.Message); } } // Create security profile. #if DEBUG return CreateSecurityProfile(secItem, profileGroups, profileRights, !RequireDebugLogin); #else return CreateSecurityProfile(secItem, profileGroups, profileRights, false); #endif } //------------------------------------------------------------------- // U s e r S e c u r i t y R i g h t s //------------------------------------------------------------------- //------------------------------------------------------------------- // S e c u r i t y I t e m s //------------------------------------------------------------------- public override SaSecurityItem GetUserByEmail(String emailAddress) { return securityMgr.GetSecurityItemByTypeEmail(SaSecurity.ItemType.User, emailAddress); } public override SaSecurityItem GetSecurityItemById(SaSecurity.ItemType securityItemType, SysId id) { return securityMgr.GetSecurityItemByTypeId(securityItemType, id); } public override SaSecurityItem GetSecurityItemByCode(SaSecurity.ItemType securityItemType, string code) { return securityMgr.GetSecurityItemByTypeCode(securityItemType, code); } public override SaSecurityItem GetSecurityItem(SaSecurityItem.Params prm) { ClearErrorState(); SaSecurityItem securityItem = securityMgr.GetSecurityItem(prm); SetErrorState(securityMgr.ErrorStateMessage); return securityItem; } //------------------------------------------------------------------- // Security Item properties. public override SysId GetIdForItemCode(SaSecurity.ItemType securityItemType, string code) { ClearErrorState(); if (securityItemType != SaSecurity.ItemType.Unknown && !StringUtil.IsEmpty(code)) { // Columns to query. ColumnDfn colSecItemId = securityMgr.GetSecurityItemColumnDfn(SaSecurityItem.Column.Id); ColumnDfn colSecItemCode = securityMgr.GetSecurityItemColumnDfn(SaSecurityItem.Column.Code); List columns = new List { colSecItemId, colSecItemCode }; // Filter. SaSecurityItem.Params prmSecItem = new SaSecurityItem.Params(); prmSecItem.Code = code; prmSecItem.StatusCat = SaSecurityItem.StatusCat.Any; if (securityMgr.GetSecurityItemCount(prmSecItem) != 1) return null; // Execute query. using (DbResultSet dbResultSet = securityMgr.ExecuteSecurityItemQuery(columns, prmSecItem)) { if (dbResultSet != null && dbResultSet.NextRecord()) { NamedValue.Map values = dbResultSet.GetRecordValues(); SysId itemId = new SysId(StringUtil.ToInt(values.GetValue(colSecItemId.DataName).ToString())); String itemCode = values.GetValue(colSecItemCode.DataName).ToString(); if (itemCode.EqualsCI(code)) return itemId; } } } return null; } public override string GetCodeForItemId(SysId itemId) { ClearErrorState(); if (!SysId.IsValid(itemId)) { SetErrorState("Item id nust be specified"); return ""; } // Columns to query. ColumnDfn colSecItemId = securityMgr.GetSecurityItemColumnDfn(SaSecurityItem.Column.Id); ColumnDfn colSecItemCode = securityMgr.GetSecurityItemColumnDfn(SaSecurityItem.Column.Code); List columns = new List { colSecItemId, colSecItemCode }; // Filter. SaSecurityItem.Params prmSecItem = new SaSecurityItem.Params(); prmSecItem.IncludedIds.Add(itemId); prmSecItem.StatusCat = SaSecurityItem.StatusCat.Any; if (securityMgr.GetSecurityItemCount(prmSecItem) != 1) return null; // Execute query. using (DbResultSet dbResultSet = securityMgr.ExecuteSecurityItemQuery(columns, prmSecItem)) { if (dbResultSet != null && dbResultSet.NextRecord()) { NamedValue.Map values = dbResultSet.GetRecordValues(); if (new SysId(StringUtil.ToInt(values.GetValue(colSecItemId.DataName).ToString())).Equals(itemId)) return values.GetValue(colSecItemCode.DataName).ToString(); } } return ""; } public override string GetNameForItemId(SysId itemId) { ClearErrorState(); if (!SysId.IsValid(itemId)) { SetErrorState("Item id nust be specified"); return ""; } // Columns to query. ColumnDfn colSecItemId = securityMgr.GetSecurityItemColumnDfn(SaSecurityItem.Column.Id); ColumnDfn colSecItemDesc = securityMgr.GetSecurityItemColumnDfn(SaSecurityItem.Column.Description); List columns = new List { colSecItemId, colSecItemDesc }; // Filter. SaSecurityItem.Params prmSecItem = new SaSecurityItem.Params(); prmSecItem.IncludedIds.Add(itemId); prmSecItem.StatusCat = SaSecurityItem.StatusCat.Any; if (securityMgr.GetSecurityItemCount(prmSecItem) != 1) return null; // Execute query. using (DbResultSet dbResultSet = securityMgr.ExecuteSecurityItemQuery(columns, prmSecItem)) { if (dbResultSet != null && dbResultSet.NextRecord()) { NamedValue.Map values = dbResultSet.GetRecordValues(); if (new SysId(StringUtil.ToInt(values.GetValue(colSecItemId.DataName).ToString())).Equals(itemId)) return values.GetValue(colSecItemDesc.DataName).ToString(); } } return ""; } public override Dictionary GetSecurityItemDescriptions(List securityItemIds) { ClearErrorState(); Dictionary securityItemDescs = new Dictionary(); if (securityItemIds.Count < 1) return securityItemDescs; // Columns to query. ColumnDfn colSecItemId = securityMgr.GetSecurityItemColumnDfn(SaSecurityItem.Column.Id); ColumnDfn colSecItemDesc = securityMgr.GetSecurityItemColumnDfn(SaSecurityItem.Column.Description); List columns = new List { colSecItemId, colSecItemDesc }; // Filter. SaSecurityItem.Params prmSecItem = new SaSecurityItem.Params(); prmSecItem.IncludedIds.AddRange(securityItemIds); prmSecItem.StatusCat = SaSecurityItem.StatusCat.Any; // Execute query. using (DbResultSet dbResultSet = securityMgr.ExecuteSecurityItemQuery(columns, prmSecItem)) { while (dbResultSet != null && dbResultSet.NextRecord()) { NamedValue.Map values = dbResultSet.GetRecordValues(); SysId itemId = new SysId(StringUtil.ToInt(values.GetValue(colSecItemId.DataName).ToString())); String itemDesc = values.GetValue(colSecItemDesc.DataName).ToString(); securityItemDescs[itemId] = itemDesc; } } return securityItemDescs; } //------------------------------------------------------------------- // Security item updates. public override bool CreateUser(string code, string name, DbUpdateInfo dbUpdateInfo) { ClearErrorState(); if (StringUtil.IsEmpty(code) || StringUtil.IsEmpty(name)) return SetErrorState("User code and name must be supplied"); if (SecurityItemCodeExists(SaSecurity.ItemType.User, code)) return SetErrorState("User code already exists"); // Create User. SaSecurityItem secItem = securityMgr.CreateSecurityItem(SaSecurity.ItemType.User); secItem.Code = code; secItem.Description = name; // Insert on database. if (!securityMgr.InsertSecurityItem(secItem, dbUpdateInfo)) return SetErrorState(securityMgr.ErrorStateMessage); return !HasErrorState(); } public override bool AssignUserToGroup(string userCode, string groupCode, DbUpdateInfo dbUpdateInfo) { ClearErrorState(); throw new NotImplementedException(); } public override bool UpdateSecurityItem(SaSecurityItem securityItem, DbUpdateInfo dbUpdateInfo) { ClearErrorState(); if (!securityMgr.UpdateSecurityItem(securityItem, dbUpdateInfo)) return SetErrorState(securityMgr.ErrorStateMessage); return !HasErrorState(); } //------------------------------------------------------------------- // Security Item list. public override ColumnDfn GetSecurityItemColumnDfn(SaSecurityItem.Column columnId, String caption = "", int width = 0) { ClearErrorState(); return securityMgr.GetSecurityItemColumnDfn(columnId, caption, width); } public override long GetSecurityItemCount(SaSecurityItem.Params prm) { ClearErrorState(); return securityMgr.GetSecurityItemCount(prm); } public override List GetSecurityItemList(SaSecurityItem.Params prm) { ClearErrorState(); return securityMgr.GetSecurityItemList(prm); } public override DbResultSet ExecuteSecurityItemQuery(List columns, SaSecurityItem.Params prm) { ClearErrorState(); DbResultSet resultSet = securityMgr.ExecuteSecurityItemQuery(columns, prm); SetErrorState(securityMgr.ErrorStateMessage); return resultSet; } public override DataValue GetSecurityItemDataValue(ColumnDfn column, NamedValue.Map values) { ClearErrorState(); return securityMgr.GetSecurityItemDataValue(column, values); } //------------------------------------------------------------------- // S e c u r i t y I t e m s L i n k s //------------------------------------------------------------------- // Security item links. public override bool ItemsAreLinked(SysId itemId1, SysId itemId2) { ClearErrorState(); if (!SysId.IsValid(itemId1) || !SysId.IsValid(itemId2)) return false; // From-To. SaSecurityLink.Params prmSecLink = new SaSecurityLink.Params(); prmSecLink.includedItemIdsOwner.Add(itemId1); prmSecLink.includedItemIdsTarget.Add(itemId2); prmSecLink.StatusCat = SaSecurityLink.StatusCat.Any; if (securityMgr.GetSecurityLinkCount(prmSecLink) > 0) return true; // To-From. prmSecLink = new SaSecurityLink.Params(); prmSecLink.includedItemIdsOwner.Add(itemId2); prmSecLink.includedItemIdsTarget.Add(itemId1); prmSecLink.StatusCat = SaSecurityLink.StatusCat.Any; if (securityMgr.GetSecurityLinkCount(prmSecLink) > 0) return true; return false; } //------------------------------------------------------------------- } //======================================================================= }