using Sarand.BusinessMgr.Net.Standard.Base.Bus; using Sarand.Net.Standard.Base.App; using Sarand.Net.Standard.Base.Bus; using Sarand.Net.Standard.Base.Core; using Sarand.Net.Standard.Base.Security; using Sarand.Net.Standard.Base.Utils; using System; using System.Collections.Generic; namespace Sarand.BusinessMgr.Net.Standard.Base.App { //======================================================================= public class SbmSecurityProfile : SaErrorStateItem { //------------------------------------------------------------------- // Data members. private static readonly String userNameUnknown = "Unknown"; private bool includeHostSecurityProfile = false; private SaSecurityProfile userSecurityProfile; private SaSecurityProfile hostSecurityProfile; private readonly List securityRights = new List(); //------------------------------------------------------------------- // Construction. public SbmSecurityProfile(SbmUserContext userContext, bool includeHostSecurityProfile) { this.UserContext = userContext; this.includeHostSecurityProfile = includeHostSecurityProfile; Admin = new AdminProfile(this); Manage = new ManageProfile(this); Financial = new FinancialProfile(this); Contacts = new ContactsProfile(this); Transaction = new TransactionsProfile(this); } //------------------------------------------------------------------- // Properties. public SbmUserContext UserContext { get; } //------------------------------------------------------------------- // Refresh profile. public void RefreshProfile(SaSecurityConsole securityConsole, SysId userId, List securityRights) { String fn = GetType().Name + ".RefreshProfile"; ClearErrorState(); // Make a note of the security right. this.securityRights.Clear(); this.securityRights.AddRange(securityRights); SysId previousUserId = UserId; // Clear existing profile. UserId = SysId.InvalidOnNull(userId); // Load new profile. if (securityConsole != null) { userSecurityProfile = securityConsole.GetUserSecurityProfile(UserId); if (hostSecurityProfile == null && includeHostSecurityProfile) hostSecurityProfile = securityConsole.GetHostSecurityProfile(); } SaLogger.Debug(fn + " User: '" + UserDisplayName + "' [Id: " + UserId + "]" + (SysId.IsValid(previousUserId) ? ". Previous UserId: " + SysId.ToString(previousUserId) : "")); RefreshProfileSettings(); } protected void RefreshProfile(SaSecurityProfile userSecurityProfile, SaSecurityProfile hostSecurityProfile) { this.userSecurityProfile = userSecurityProfile; this.hostSecurityProfile = hostSecurityProfile; RefreshProfileSettings(); } private void RefreshProfileSettings() { // Admin. Admin.CanManageSecurity = UserHasSecurityRight(Sbm.SecurityRight.Security_Admin); Admin.CanManageDatabase = UserHasSecurityRight(Sbm.SecurityRight.Database_Admin); Admin.CanManageReferenceData = UserHasSecurityRight(Sbm.SecurityRight.ReferenceData_Admin); Admin.CanManageInterfaces = UserHasSecurityRight(Sbm.SecurityRight.InterfaceConfig); // Manage. Manage.CanManageTasks = UserHasSecurityRight(Sbm.SecurityRight.TaskManager); Manage.CanManageTimesheets = UserHasSecurityRight(Sbm.SecurityRight.TimesheetManager); //Financials. Financial.CanViewFinancials = UserHasSecurityRight(Sbm.SecurityRight.Financial_View); Financial.CanUpdateFinancials = UserHasSecurityRight(Sbm.SecurityRight.Financial_Update); Financial.CanViewCommoditySupplyFinancials = UserCanAccessFinancialViewOfType(Sbm.FinancialType.CommoditySupply); Financial.CanUpdateCommoditySupplyFinancials = UserCanAccessFinancialUpdateOfType(Sbm.FinancialType.CommoditySupply); Financial.CanViewCommoditySalesFinancials = UserCanAccessFinancialViewOfType(Sbm.FinancialType.CommoditySales); Financial.CanUpdateCommoditySalesFinancials = UserCanAccessFinancialUpdateOfType(Sbm.FinancialType.CommoditySales); // Contacts. Contacts.CanUpdate = (UserHasSecurityRight(Sbm.SecurityRight.Affiliate_Update)); Contacts.CanCreate = (Contacts.CanUpdate || UserHasSecurityRight(Sbm.SecurityRight.Affiliate_Create)); // Transactions. Transaction.CanUpdate = (UserHasSecurityRight(Sbm.SecurityRight.Transaction_Update)); Transaction.CanCreate = (Transaction.CanUpdate || UserHasSecurityRight(Sbm.SecurityRight.Transaction_View)); // ToDo Commodities. } private void ClearProfile() { // Reset security profiles. Admin.Clear(); Manage.Clear(); Financial.Clear(); Contacts.Clear(); Transaction.Clear(); } //------------------------------------------------------------------- // User. public SysId UserId { get; protected set; } = new SysId(); public String UserDisplayName { get { return (userSecurityProfile != null ? userSecurityProfile.Description : userNameUnknown); } } public String UserLocation { get { return (userSecurityProfile != null ? userSecurityProfile.Location : ""); } } public DateTime UserLastLogin { get { return (userSecurityProfile != null ? userSecurityProfile.LastLogin : DateTime.MinValue); } } //------------------------------------------------------------------- // Utilities. public bool IsUserMemberOfSecurityGroup(SysId secGroupId) { if (userSecurityProfile != null) return userSecurityProfile.IsMemberOfSecurityGroup(secGroupId); return false; } public bool IsSecurityRightGranted(Sbm.SecurityRight securityRight, SysId id = null) { if (userSecurityProfile != null) return userSecurityProfile.IsSecurityRightGranted(securityRights.GetCodeForType(securityRight)); return false; } public bool IsSecurityRightDenied(Sbm.SecurityRight securityRight, SysId id = null) { if (userSecurityProfile != null) return userSecurityProfile.IsSecurityRightDenied(securityRights.GetCodeForType(securityRight), id); return true; } //------------------------------------------------------------------- // Security rights - Admin. public class AdminProfile { private readonly SbmSecurityProfile securityProfile; internal AdminProfile(SbmSecurityProfile securityProfile) { this.securityProfile = securityProfile; } public bool CanManageSecurity { get; internal set; } = false; public bool CanManageDatabase { get; internal set; } = false; public bool CanManageReferenceData { get; internal set; } = false; public bool CanManageInterfaces { get; internal set; } = false; internal void Clear() { CanManageSecurity = false; CanManageDatabase = false; CanManageReferenceData = false; CanManageInterfaces = false; } } public AdminProfile Admin { get; } //------------------------------------------------------------------- // Security rights - Manage. public class ManageProfile { private readonly SbmSecurityProfile securityProfile; internal ManageProfile(SbmSecurityProfile securityProfile) { this.securityProfile = securityProfile; } public bool CanManageTasks { get; internal set; } = false; public bool CanManageTimesheets { get; internal set; } = false; internal void Clear() { CanManageTasks = false; } } public ManageProfile Manage { get; } //------------------------------------------------------------------- // Security rights - Financials. public class FinancialProfile { private readonly SbmSecurityProfile securityProfile; internal FinancialProfile(SbmSecurityProfile securityProfile) { this.securityProfile = securityProfile; } public bool CanViewFinancials { get; internal set; } = false; public bool CanUpdateFinancials { get; internal set; } = false; public bool CanViewCommoditySupplyFinancials { get; internal set; } = false; public bool CanUpdateCommoditySupplyFinancials { get; internal set; } = false; public bool CanViewCommoditySalesFinancials { get; internal set; } = false; public bool CanUpdateCommoditySalesFinancials { get; internal set; } = false; internal void Clear() { CanViewFinancials = false; CanUpdateFinancials = false; CanViewCommoditySupplyFinancials = false; CanUpdateCommoditySupplyFinancials = false; CanViewCommoditySalesFinancials = false; CanUpdateCommoditySalesFinancials = false; } } public FinancialProfile Financial { get; } public bool UserCanViewFinancials(Sbm.FinancialType financialType = Sbm.FinancialType.Any) { SbmConfigConsole configConsole = SbmGlobals.GetConfigConsole(UserContext.SessionContext); if (configConsole != null && !configConsole.AllowOption(UserContext, Sbm.ConfigOption.AllowFinancialsAccessControl)) return true; if (IsSecurityRightGranted(Sbm.SecurityRight.Financial_Update) || IsSecurityRightGranted(Sbm.SecurityRight.Financial_View)) { // If specific type of financial is requested, check that view is not denied. if (financialType > 0 && IsSecurityRightDenied(Sbm.SecurityRight.Financial_ViewByType, new SysId((int)financialType))) return false; return true; } return false; } public bool UserCanUpdateFinancials(Sbm.FinancialType financialType = Sbm.FinancialType.Any) { SbmConfigConsole configConsole = SbmGlobals.GetConfigConsole(UserContext.SessionContext); if (configConsole != null && !configConsole.AllowOption(UserContext, Sbm.ConfigOption.AllowFinancialsAccessControl)) return true; if (IsSecurityRightGranted(Sbm.SecurityRight.Financial_Update)) { // If specific type of financial is requested, check that update is not denied. if (financialType > 0 && IsSecurityRightDenied(Sbm.SecurityRight.Financial_UpdateByType, new SysId((int)financialType))) return false; return true; } return false; } bool UserCanAccessFinancialViewOfType(Sbm.FinancialType financialType) { if ((int)financialType < 1) return false; // If specific type of financial is requested, check that view is not denied. if (IsSecurityRightDenied(Sbm.SecurityRight.Financial_ViewByType, new SysId((int)financialType))) return false; return true; } bool UserCanAccessFinancialUpdateOfType(Sbm.FinancialType financialType) { if ((int)financialType < 1) return false; // If specific type of financial is requested, check that update is not denied. if (IsSecurityRightDenied(Sbm.SecurityRight.Financial_UpdateByType, new SysId((int)financialType))) return false; return true; } //------------------------------------------------------------------- // Security rights - Contacts. public class ContactsProfile { private readonly SbmSecurityProfile securityProfile; internal ContactsProfile(SbmSecurityProfile securityProfile) { this.securityProfile = securityProfile; } public bool CanCreate { get; internal set; } = false; public bool CanUpdate { get; internal set; } = false; internal void Clear() { CanCreate = false; CanUpdate = false; } } public ContactsProfile Contacts { get; } //------------------------------------------------------------------- // Security rights - Transactions. public class TransactionsProfile { private readonly SbmSecurityProfile securityProfile; internal TransactionsProfile(SbmSecurityProfile securityProfile) { this.securityProfile = securityProfile; } public bool CanCreate { get; internal set; } = false; public bool CanUpdate { get; internal set; } = false; public bool CanUpdateTransactionTypeStatusCat(Sbm.TransactionType transactionType, SbmTransaction.StatusCat transactionStatusCat) { SysId transactionTypeStatusCatId = SbmTransaction.GetTransactionTypeStatusId(transactionType, transactionStatusCat); // Check if update of this transaction type and status is denied: if (securityProfile.IsSecurityRightDenied(Sbm.SecurityRight.Transaction_UpdateByTypeStatus, transactionTypeStatusCatId)) return false; // Check if update of this transaction type and status is explicitly allowed: if (securityProfile.IsSecurityRightGranted(Sbm.SecurityRight.Transaction_UpdateByTypeStatus, transactionTypeStatusCatId)) return true; // Check if any other statuses for this type of transaction are allowed. foreach (TypeCodeDesc statusCat in SbmTransaction.GetTransactionStatusCats(securityProfile.UserContext, transactionType)) { SbmTransaction.StatusCat transactionStatusCatOther = (SbmTransaction.StatusCat)statusCat.Type; // Ignore the transaction status category. if (transactionStatusCatOther == transactionStatusCat) continue; if (securityProfile.IsSecurityRightGranted(Sbm.SecurityRight.Transaction_UpdateByTypeStatus, SbmTransaction.GetTransactionTypeStatusId(transactionType, transactionStatusCatOther))) // Explicit granting of right to another status for this transaction right // implies that other statuses are implicitly denied. return false; } return true; } internal void Clear() { CanCreate = false; CanUpdate = false; } } public TransactionsProfile Transaction { get; } public bool UserCanAccessTransactionsOfType(Sbm.TransactionType transactionType) { if ((int)transactionType < 1) return false; // Check if specific type of transaction is denied. if (IsSecurityRightDenied(Sbm.SecurityRight.Transaction_ByType, new SysId((int)transactionType))) return false; return true; } //------------------------------------------------------------------- // Security rights - ItemType. public class ItemTypesProfile { internal ItemTypesProfile() { } public bool CanCreate { get; internal set; } = false; public bool CanUpdate { get; internal set; } = false; public bool CanRemove { get; internal set; } = false; internal void Clear() { CanCreate = false; CanUpdate = false; CanRemove = false; } } public ItemTypesProfile ItemType { get; } = new ItemTypesProfile(); public bool ItemTypeIsAllowed(Sbm.ItemType itemType) { SbmConfigConsole configConsole = SbmGlobals.GetConfigConsole(UserContext.SessionContext); if (configConsole == null) return false; switch (itemType) { //case Sbm.ItemType.SecItem: //case Sbm.ItemType.Currency: //case Sbm.ItemType.Region: //case Sbm.ItemType.Language: //case Sbm.ItemType.TaxCode: //case Sbm.ItemType.UnitMeasure: case Sbm.ItemType.Process: return configConsole.AllowOption(UserContext, Sbm.ConfigOption.AllowProcesses); case Sbm.ItemType.Affiliate: case Sbm.ItemType.Address: return configConsole.AllowOption(UserContext, Sbm.ConfigOption.AllowContacts); case Sbm.ItemType.Commodity: return configConsole.AllowOption(UserContext, Sbm.ConfigOption.AllowCommodities); case Sbm.ItemType.PortfolioItem: return configConsole.AllowOption(UserContext, Sbm.ConfigOption.AllowPortfolios); case Sbm.ItemType.Location: return configConsole.GetStockControlConfig(UserContext).AllowStockLocations(); case Sbm.ItemType.Container: case Sbm.ItemType.ContainerItem: return configConsole.GetStockControlConfig(UserContext).AllowStockContainers(); case Sbm.ItemType.Movement: case Sbm.ItemType.StockLevel: return configConsole.GetStockControlConfig(UserContext).AllowStockControl(); case Sbm.ItemType.PriceSet: case Sbm.ItemType.Price: return configConsole.AllowOption(UserContext, Sbm.ConfigOption.AllowPriceSets); case Sbm.ItemType.CommodityCustomer: return configConsole.AllowOption(UserContext, Sbm.ConfigOption.CommodityCustomers); case Sbm.ItemType.CommoditySupplier: return configConsole.AllowOption(UserContext, Sbm.ConfigOption.CommoditySuppliers); //case Sbm.ItemType.Association: case Sbm.ItemType.Transaction: case Sbm.ItemType.Requirement: case Sbm.ItemType.Constituent: return configConsole.AllowOption(UserContext, Sbm.ConfigOption.AllowTransactions); //case Sbm.ItemType.SystemAccount: //case Sbm.ItemType.SystemUser: //case Sbm.ItemType.SystemAccountUser: case Sbm.ItemType.AssetCategory: case Sbm.ItemType.AssetCategoryProcess: case Sbm.ItemType.Asset: case Sbm.ItemType.AssetProcess: return configConsole.AllowOption(UserContext, Sbm.ConfigOption.AllowAssets); case Sbm.ItemType.VehicleClass: case Sbm.ItemType.Vehicle: case Sbm.ItemType.VehicleEvent: case Sbm.ItemType.VehicleFeature: return configConsole.AllowOption(UserContext, Sbm.ConfigOption.AllowVehicles); case Sbm.ItemType.CommodityProcess: return configConsole.AllowOption(UserContext, Sbm.ConfigOption.AllowProcesses); case Sbm.ItemType.RequirementProcess: return configConsole.AllowOption(UserContext, Sbm.ConfigOption.AllowProcesses); //case Sbm.ItemType.Interface: } return true; } public bool UserCanCreateItemType(Sbm.ItemType itemType) { if (!ItemTypeIsAllowed(itemType)) return false; switch (itemType) { case Sbm.ItemType.SecItem: return IsSecurityRightGranted(Sbm.SecurityRight.Security_Admin); case Sbm.ItemType.Currency: case Sbm.ItemType.Region: case Sbm.ItemType.Language: case Sbm.ItemType.TaxCode: case Sbm.ItemType.UnitMeasure: return IsSecurityRightGranted(Sbm.SecurityRight.ReferenceData_Admin); case Sbm.ItemType.Process: return IsSecurityRightGranted(Sbm.SecurityRight.ReferenceData_Admin); case Sbm.ItemType.Affiliate: return IsSecurityRightGranted(Sbm.SecurityRight.Affiliate_Create); case Sbm.ItemType.Address: return IsSecurityRightGranted(Sbm.SecurityRight.Affiliate_Update); case Sbm.ItemType.Commodity: return IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Create); case Sbm.ItemType.PortfolioItem: return IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Update); case Sbm.ItemType.Location: return IsSecurityRightGranted(Sbm.SecurityRight.ReferenceData_Admin); case Sbm.ItemType.Container: return IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Create); case Sbm.ItemType.ContainerItem: return IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Update); case Sbm.ItemType.Movement: return IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Update); case Sbm.ItemType.StockLevel: return IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Update); case Sbm.ItemType.PriceSet: case Sbm.ItemType.Price: return IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Update) && UserCanUpdateFinancials(); case Sbm.ItemType.CommodityCustomer: case Sbm.ItemType.CommoditySupplier: return IsSecurityRightGranted(Sbm.SecurityRight.Association_Update) && IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Update); case Sbm.ItemType.Association: return IsSecurityRightGranted(Sbm.SecurityRight.Association_Create); case Sbm.ItemType.Transaction: return IsSecurityRightGranted(Sbm.SecurityRight.Transaction_Create); case Sbm.ItemType.Requirement: case Sbm.ItemType.Constituent: return IsSecurityRightGranted(Sbm.SecurityRight.Transaction_Update); case Sbm.ItemType.SystemAccount: case Sbm.ItemType.SystemUser: case Sbm.ItemType.SystemAccountUser: return IsSecurityRightGranted(Sbm.SecurityRight.Security_Admin); case Sbm.ItemType.AssetCategory: case Sbm.ItemType.AssetCategoryProcess: case Sbm.ItemType.Asset: case Sbm.ItemType.AssetProcess: return IsSecurityRightGranted(Sbm.SecurityRight.Asset_Create); case Sbm.ItemType.VehicleClass: case Sbm.ItemType.Vehicle: case Sbm.ItemType.VehicleEvent: case Sbm.ItemType.VehicleFeature: return IsSecurityRightGranted(Sbm.SecurityRight.Asset_Create); case Sbm.ItemType.CommodityProcess: return IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Update); case Sbm.ItemType.RequirementProcess: return IsSecurityRightGranted(Sbm.SecurityRight.Transaction_Update); case Sbm.ItemType.Interface: return IsSecurityRightGranted(Sbm.SecurityRight.InterfaceConfig); } return false; } public bool UserCanUpdateItemType(Sbm.ItemType itemType) { switch (itemType) { case Sbm.ItemType.SecItem: return IsSecurityRightGranted(Sbm.SecurityRight.Security_Admin); case Sbm.ItemType.Currency: case Sbm.ItemType.Region: case Sbm.ItemType.Language: case Sbm.ItemType.TaxCode: case Sbm.ItemType.UnitMeasure: return IsSecurityRightGranted(Sbm.SecurityRight.ReferenceData_Admin); case Sbm.ItemType.Process: return IsSecurityRightGranted(Sbm.SecurityRight.ReferenceData_Admin); case Sbm.ItemType.Affiliate: case Sbm.ItemType.Address: return IsSecurityRightGranted(Sbm.SecurityRight.Affiliate_Update); case Sbm.ItemType.Commodity: return IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Update); case Sbm.ItemType.PortfolioItem: return IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Update); case Sbm.ItemType.Location: return IsSecurityRightGranted(Sbm.SecurityRight.ReferenceData_Admin); case Sbm.ItemType.Container: case Sbm.ItemType.ContainerItem: return IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Update); case Sbm.ItemType.Movement: case Sbm.ItemType.StockLevel: return IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Update); case Sbm.ItemType.PriceSet: case Sbm.ItemType.Price: return IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Update) && UserCanUpdateFinancials(); case Sbm.ItemType.CommodityCustomer: case Sbm.ItemType.CommoditySupplier: return IsSecurityRightGranted(Sbm.SecurityRight.Association_Update) && IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Update); case Sbm.ItemType.Association: return IsSecurityRightGranted(Sbm.SecurityRight.Association_Update); case Sbm.ItemType.Transaction: case Sbm.ItemType.Requirement: case Sbm.ItemType.Constituent: return IsSecurityRightGranted(Sbm.SecurityRight.Transaction_Update); case Sbm.ItemType.SystemAccount: case Sbm.ItemType.SystemUser: case Sbm.ItemType.SystemAccountUser: return IsSecurityRightGranted(Sbm.SecurityRight.Security_Admin); case Sbm.ItemType.AssetCategory: case Sbm.ItemType.AssetCategoryProcess: case Sbm.ItemType.Asset: case Sbm.ItemType.AssetProcess: return IsSecurityRightGranted(Sbm.SecurityRight.Asset_Update); case Sbm.ItemType.VehicleClass: case Sbm.ItemType.Vehicle: case Sbm.ItemType.VehicleEvent: case Sbm.ItemType.VehicleFeature: return IsSecurityRightGranted(Sbm.SecurityRight.Asset_Update); case Sbm.ItemType.CommodityProcess: return IsSecurityRightGranted(Sbm.SecurityRight.Commodity_Update); case Sbm.ItemType.RequirementProcess: return IsSecurityRightGranted(Sbm.SecurityRight.Transaction_Update); case Sbm.ItemType.Interface: return IsSecurityRightGranted(Sbm.SecurityRight.InterfaceConfig); } return false; } public bool UserCanRemoveItemType(Sbm.ItemType itemType) { switch (itemType) { case Sbm.ItemType.Transaction: if (!IsSecurityRightGranted(Sbm.SecurityRight.Transaction_Remove)) return false; break; } return (UserCanCreateItemType(itemType) && UserCanUpdateItemType(itemType)); } //------------------------------------------------------------------- // Security rights. private bool UserHasSecurityRight(Sbm.SecurityRight securityRight, SysId dataItemId = null) { String rightCode = securityRights.GetCodeForType(securityRight); if (StringUtil.IsEmpty(rightCode)) return false; // Check if right is denied by either user or host profiles. if (userSecurityProfile != null && userSecurityProfile.IsSecurityRightDenied(rightCode)) return false; if (hostSecurityProfile != null && hostSecurityProfile.IsSecurityRightDenied(rightCode)) return false; // Check if right is granted by either user or host profiles. if (userSecurityProfile != null && userSecurityProfile.IsSecurityRightGranted(rightCode)) return true; if (hostSecurityProfile != null && hostSecurityProfile.IsSecurityRightGranted(rightCode)) return true; return false; } //------------------------------------------------------------------- } //======================================================================= }