using Newtonsoft.Json; using Sarand.BusinessMgr.Net.Standard.Base.Bus; using Sarand.BusinessMgr.Net.Standard.Base.Consoles; using Sarand.BusinessMgr.Net.Standard.Base.Core; 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, ISbmSecurityProfile_Core { //------------------------------------------------------------------- // 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. [JsonConstructor] private SbmSecurityProfile() { } public SbmSecurityProfile(bool includeHostSecurityProfile) { this.includeHostSecurityProfile = includeHostSecurityProfile; Admin = new AdminProfile(); Manage = new ManageProfile(); Financial = new FinancialProfile(); Contacts = new ContactsProfile(); Transaction = new TransactionsProfile(); } //------------------------------------------------------------------- // Properties. //------------------------------------------------------------------- // Refresh profile. public void RefreshProfile(SbmSessionConsole sessionConsole, SaSecurityConsole securityConsole, SysId userId, List securityRights) { 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($"{SysUtil.Fn} User: '{UserDisplayName}' [Id: {UserId}]" + (SysId.IsValid(previousUserId) ? ". Previous UserId: " + SysId.ToString(previousUserId) : "")); RefreshProfileSettings(sessionConsole); } protected void RefreshProfile(SbmSessionConsole sessionConsole, SaSecurityProfile userSecurityProfile, SaSecurityProfile hostSecurityProfile) { this.userSecurityProfile = userSecurityProfile; this.hostSecurityProfile = hostSecurityProfile; RefreshProfileSettings(sessionConsole); } private void RefreshProfileSettings(SbmSessionConsole sessionConsole) { RefreshAdminProfile(sessionConsole); RefreshManageProfile(sessionConsole); RefreshFinancialProfile(sessionConsole); RefreshContactsProfile(sessionConsole); RefreshTransactionProfile(sessionConsole); RefreshItemTypeProfile(sessionConsole); // ToDo Commodities. } private void ClearProfile() { // Reset security profiles. Admin = new AdminProfile(); Manage = new ManageProfile(); Financial = new FinancialProfile(); Contacts = new ContactsProfile(); Transaction = new TransactionsProfile(); } //------------------------------------------------------------------- // 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 { internal AdminProfile() { } 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; } public AdminProfile Admin { get; internal set; } private void RefreshAdminProfile(SbmSessionConsole sessionConsole) { 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); } //------------------------------------------------------------------- // Security rights - Manage. public class ManageProfile { internal ManageProfile() { } public bool CanManageTasks { get; internal set; } = false; public bool CanManageTimesheets { get; internal set; } = false; } public ManageProfile Manage { get; internal set; } private void RefreshManageProfile(SbmSessionConsole sessionConsole) { Manage.CanManageTasks = UserHasSecurityRight(Sbm.SecurityRight.TaskManager); Manage.CanManageTimesheets = UserHasSecurityRight(Sbm.SecurityRight.TimesheetManager); } //------------------------------------------------------------------- // Security rights - Financials. public class FinancialProfile { internal FinancialProfile() { } public bool ViewFinancials { get; internal set; } public bool UpdateFinancials { get; internal set; } public bool ViewCommoditySupplyFinancials { get; internal set; } public bool UpdateCommoditySupplyFinancials { get; internal set; } public bool ViewCommoditySalesFinancials { get; internal set; } public bool UpdateCommoditySalesFinancials { get; internal set; } public bool FinancialsAccessControl { get; internal set; } } public FinancialProfile Financial { get; internal set; } private void RefreshFinancialProfile(SbmSessionConsole sessionConsole) { Financial.ViewFinancials = UserHasSecurityRight(Sbm.SecurityRight.Financial_View); Financial.UpdateFinancials = UserHasSecurityRight(Sbm.SecurityRight.Financial_Update); Financial.ViewCommoditySupplyFinancials = UserCanAccessFinancialViewOfType(Sbm.FinancialType.CommoditySupply); Financial.UpdateCommoditySupplyFinancials = UserCanAccessFinancialUpdateOfType(Sbm.FinancialType.CommoditySupply); Financial.ViewCommoditySalesFinancials = UserCanAccessFinancialViewOfType(Sbm.FinancialType.CommoditySales); Financial.UpdateCommoditySalesFinancials = UserCanAccessFinancialUpdateOfType(Sbm.FinancialType.CommoditySales); // Config options. Financial.FinancialsAccessControl = (sessionConsole != null && !sessionConsole.AllowOption(Sbm.ConfigOption.FinancialsAccessControl)); } private 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; } private 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; } /// Does the user have sufficient rights to view the specified financials. public bool UserCanViewFinancials(Sbm.FinancialType financialType = Sbm.FinancialType.Any) { if (!Financial.FinancialsAccessControl) return true; if (Financial.UpdateFinancials || Financial.ViewFinancials) { // If specific type of financial is requested, check that view access is not denied. if (financialType == Sbm.FinancialType.CommoditySupply) return Financial.ViewCommoditySupplyFinancials; else if (financialType == Sbm.FinancialType.CommoditySales) return Financial.ViewCommoditySalesFinancials; else return true; } return false; } /// Does the user have sufficient rights to update the specified financials. public bool UserCanUpdateFinancials(Sbm.FinancialType financialType = Sbm.FinancialType.Any) { if (!Financial.FinancialsAccessControl) return true; if (Financial.UpdateFinancials) { // If specific type of financial is requested, check that update access is not denied. if (financialType == Sbm.FinancialType.CommoditySupply) return Financial.UpdateCommoditySupplyFinancials; else if (financialType == Sbm.FinancialType.CommoditySales) return Financial.UpdateCommoditySalesFinancials; else return true; } return false; } //------------------------------------------------------------------- // Security rights - Contacts. public class ContactsProfile { internal ContactsProfile() { } public bool Create { get; internal set; } = false; public bool Update { get; internal set; } = false; } public ContactsProfile Contacts { get; internal set; } public bool UserCanCreateContacts() { return Contacts.Create; } public bool UserCanUpdateContacts() { return Contacts.Update; } private void RefreshContactsProfile(SbmSessionConsole sessionConsole) { Contacts.Update = (UserHasSecurityRight(Sbm.SecurityRight.Affiliate_Update)); Contacts.Create = (Contacts.Update || UserHasSecurityRight(Sbm.SecurityRight.Affiliate_Create)); } //------------------------------------------------------------------- // Security rights - Transactions. public class TransactionsProfile { internal TransactionsProfile() { } public bool Create { get; internal set; } = false; public bool Update { get; internal set; } = false; public bool CanUpdateTransactionTypeStatusCat(SbmSecurityProfile securityProfile, 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(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; } } public TransactionsProfile Transaction { get; internal set; } private void RefreshTransactionProfile(SbmSessionConsole sessionConsole) { Transaction.Update = (UserHasSecurityRight(Sbm.SecurityRight.Transaction_Update)); Transaction.Create = (Transaction.Update || UserHasSecurityRight(Sbm.SecurityRight.Transaction_View)); } 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 Create { get; internal set; } public bool Update { get; internal set; } public bool Remove { get; internal set; } // Config options. public bool Processes { get; internal set; } public bool Contacts { get; internal set; } public bool Commodities { get; internal set; } public bool Portfolios { get; internal set; } public bool PriceSets { get; internal set; } public bool CommodityCustomers { get; internal set; } public bool CommoditySuppliers { get; internal set; } public bool Transactions { get; internal set; } public bool Assets { get; internal set; } public bool Vehicles { get; internal set; } public bool StockLocations { get; internal set; } public bool StockContainers { get; internal set; } public bool StockControl { get; internal set; } } public ItemTypesProfile ItemType { get; } = new ItemTypesProfile(); private void RefreshItemTypeProfile(SbmSessionConsole sessionConsole) { ItemType.Processes = sessionConsole.AllowOption(Sbm.ConfigOption.Processes); ItemType.Contacts = sessionConsole.AllowOption(Sbm.ConfigOption.Contacts); ItemType.Commodities = sessionConsole.AllowOption(Sbm.ConfigOption.Commodities); ItemType.Portfolios = sessionConsole.AllowOption(Sbm.ConfigOption.Portfolios); ItemType.PriceSets = sessionConsole.AllowOption(Sbm.ConfigOption.PriceSets); ItemType.CommodityCustomers = sessionConsole.AllowOption(Sbm.ConfigOption.CommodityCustomers); ItemType.CommoditySuppliers = sessionConsole.AllowOption(Sbm.ConfigOption.CommoditySuppliers); ItemType.Transactions = sessionConsole.AllowOption(Sbm.ConfigOption.Transactions); ItemType.Assets = sessionConsole.AllowOption(Sbm.ConfigOption.Assets); ItemType.Vehicles = sessionConsole.AllowOption(Sbm.ConfigOption.Vehicles); ItemType.StockLocations = sessionConsole.GetStockControlConfig().AllowStockLocations(); ItemType.StockContainers = sessionConsole.GetStockControlConfig().AllowStockContainers(); ItemType.StockControl = sessionConsole.GetStockControlConfig().AllowStockControl(); } public bool ItemTypeIsAllowed(Sbm.ItemType itemType) { 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 ItemType.Processes; case Sbm.ItemType.Affiliate: case Sbm.ItemType.Address: return ItemType.Contacts; case Sbm.ItemType.Commodity: return ItemType.Commodities; case Sbm.ItemType.PortfolioItem: return ItemType.Portfolios; case Sbm.ItemType.Location: return ItemType.StockLocations; case Sbm.ItemType.Container: case Sbm.ItemType.ContainerItem: return ItemType.StockContainers; case Sbm.ItemType.Movement: case Sbm.ItemType.StockLevel: return ItemType.StockControl; case Sbm.ItemType.PriceSet: case Sbm.ItemType.Price: return ItemType.PriceSets; case Sbm.ItemType.CommodityCustomer: return ItemType.CommodityCustomers; case Sbm.ItemType.CommoditySupplier: return ItemType.CommoditySuppliers; //case Sbm.ItemType.Association: case Sbm.ItemType.Transaction: case Sbm.ItemType.Requirement: case Sbm.ItemType.Constituent: return ItemType.Transactions; //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 ItemType.Assets; case Sbm.ItemType.VehicleClass: case Sbm.ItemType.Vehicle: case Sbm.ItemType.VehicleEvent: case Sbm.ItemType.VehicleFeature: return ItemType.Vehicles; case Sbm.ItemType.CommodityProcess: return ItemType.Processes; case Sbm.ItemType.RequirementProcess: return ItemType.Processes; //case Sbm.ItemType.Interface: } return true; } public bool UserCanCreateItemType(Sbm.ItemType itemType) { if (userSecurityProfile?.SystemAdmin ?? false) return true; 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) { if (userSecurityProfile?.SystemAdmin ?? false) return true; 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. public 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; } //------------------------------------------------------------------- } //======================================================================= }