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 的权限的最佳方式是什么?有规律吗?
只要没人回答,我就试试。我有一个更好的(不理想的)解决方案。
第一次实现,下面我会写一些关于它的内容。
权限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 的内部构造函数。
小巧简单。
权限控制器:
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
属性。
不同的转换器(IValueConverter
)将权限对象(在XAML中设置)转换为Visibility/IsEnabled 属性 (可以post代码如果你需要)
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 角色权限,我将只在代码中的一个地方完成。
如果您有任何问题或建议 - 我愿意与您对话。
到目前为止,我使用的是非常简单的用户角色版本,并根据 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 的权限的最佳方式是什么?有规律吗?
只要没人回答,我就试试。我有一个更好的(不理想的)解决方案。
第一次实现,下面我会写一些关于它的内容。
权限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 的内部构造函数。
小巧简单。
- 主要属性 -
权限控制器:
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
属性。
- 实现
不同的转换器(
IValueConverter
)将权限对象(在XAML中设置)转换为Visibility/IsEnabled 属性 (可以post代码如果你需要)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 角色权限,我将只在代码中的一个地方完成。
如果您有任何问题或建议 - 我愿意与您对话。