WPF UI 权限,在数据库中定义

WPF UI Permissions, which are defined in database

到目前为止,我使用的是非常简单的用户角色版本,并根据 Visibility/IsEnabled/Command.CanExecute 和转换器控制权限:

 <TabItem Visibility="{Binding UserRole, Converter={StaticResource PackerVisible}}" >...

我的转换器看起来像:

 <conv:UserVisibilityConverter x:Key="PackerVisible" Allow="Packer,Lagerleiter,Entwickler" />

如果您没有太多角色,这相对容易,但即便如此,您也没有很好的概览:谁将获得此或其他 UI 元素的访问权限。

另一件坏事是 UserRoles(存储在数据库中)在这里用作字符串 - Allow="Role1, Role2, Role3"

而且在我的新项目中我有更多 roles/permissions,是什么让这个解决方案更难看。

我已经搜索过,但没有发现如何更好地实施它。更好一点的可能是在代码中使用 enum 作为角色名称,但是如何将 enum 与数据库同步?

我找到的其他解决方案 (solution1, solution2) 更好,因为它们不需要转换器,但权限在 XAML:

中再次设置为字符串
// AuthToVisibility
<Image ... Visibility="{op:AuthToVisibility "CanView"}" />

// AutoToEnabled
<MenuItem IsEnabled="{op:AuthToEnabled "CanClose"}">...</MenuItem>

处理数据库中针对 UI 的权限的最佳方式是什么?有规律吗?

只要没人回答,我就试试。我有一个更好的(不理想的)解决方案。
第一次实现,下面我会写一些关于它的内容。

  1. 权限Class:

    public class Permission
    {
        public bool IsAllowed { get; set; }
        internal List<string> AccessControllList { get; private set; }
    
        internal Permission(params string[] allowedRoles)
        {
            IsAllowed = false;
            AccessControllList = new List<string>();
            foreach (var role in allowedRoles)
            {
                AccessControllList.Add(role);
            }
        }
    }
    
    • 主要属性 - IsAllowed
    • 角色名称的内部列表 AccessControlList 允许 run/see 一些 function/block
    • 填充 ACL 的内部构造函数。
      小巧简单。
  2. 权限控制器:

    public class PermissionController : INotifyPropertyChanged
    {
        #region Singleton
        ...
        //constructor
        private PermissionController()
        {
            Initialize();
            UserModel.Instance.LoginChanged += new LoginChangedEventHandler(UpdatePermissions);
        }
        #endregion
    
        //role names from database as string const
        private const string PACKER = "Packer";
        private const string CHIEF = "Lagerleiter";
        private const string QSWORKER = "QSMitarbeiter";
        private const string DEVELOPER = "Entwickler";
    
        PropertyInfo[] _localProperties;
    
        //Permissions defined as properties
        public Permission WEstart { get; private set; }
        public Permission WEreset { get; private set; }
        public Permission WEclose { get; private set; }
    
        public Permission Manage { get; private set; }
        public Permission TestPhase { get; private set; }
    
        private void Initialize()
        {
            _localProperties = typeof(PermissionController).GetProperties();
    
            WEwork          = new Permission(PACKER, CHIEF);
            WEreset         = new Permission(CHIEF);
            WEclose         = new Permission(PACKER, CHIEF);           
            Manage          = new Permission(CHIEF);
            TestPhase       = new Permission(DEVELOPER);
        }
    
        private void UpdatePermissions(object sender, EventArgs e)
        {            
            var currentUser = (UserModel)sender;
    
            //if user is logged out -> return
            if (!currentUser.IsLoggedIn)
                return;
    
            var permissionType = typeof(Permission);
            foreach (PropertyInfo property in _localProperties)
            {
                if (property.PropertyType != permissionType)
                    continue;
    
                var permission = (Permission)property.GetValue(this, null);
                permission.IsAllowed = false;
                if (permission.AccessControllList.Contains(currentUser.UserRole))
                {
                    permission.IsAllowed = true;
                }
                OnPropertyChanged(property.Name);
            }
        }
    
        #region INotifyPropertyChangedImplementation
        ...
        protected virtual void OnPropertyChanged(string propertyName)
        {
            ...
        }
        ...
        #endregion 
    }
    
    • 实现INotifyPropertyChanged(直接在XAML中使用它的属性)
    • 使用单例模式只有一个实例
    • const 个数据库中定义的用户角色字符串。它只是代码中将用户角色用作字符串值的一处。如果您需要更新角色列表 - 您应该只更改 const 列表和初始化方法(权限初始化)。
    • 订阅 User.LoginChanged 事件并更新每个权限的 IsAllowed 属性。
  3. 不同的转换器(IValueConverter)将权限对象(在XAML中设置)转换为Visibility/IsEnabled 属性 (可以post代码如果你需要)

  4. XAML:

    <Image Visibility="{Binding Permissions.TestPhase, Converter={StaticResource PermissionToVisibility}}" ... />
    <TextBox IsEnabled="{Binding Permissions.WEwork, Converter={StaticResource PermissionToBoolean}}" ... />
    <Button Command="..." CommandParameter="{Binding Permissions.Manage}" ... />
    
    • 如果您重新定义角色权限,则无需编辑 XAML
    • 你可以应付Visibility/IsEnabled/Command.CanExecute

现在我可以在 GUI 中自由管理用户角色,角色权限仅在代码中定义。但管理角色权限不是我的要求。
足够好的是,如果我需要 update/change 角色权限,我将只在代码中的一个地方完成。

如果您有任何问题或建议 - 我愿意与您对话。