到目前为止,我已经使用非常简单的用户角色版本和每个Visibility / IsEnabled / Command.CanExecute和转换器控制权限:
<TabItem Visibility="{Binding UserRole, Converter={StaticResource PackerVisible}}" >...
我的转换器看起来像:
<conv:UserVisibilityConverter x:Key="PackerVisible" Allow="Packer,Lagerleiter,Entwickler" />
如果您没有多少角色,这相对容易,但即使如此,您也没有很好的概述:谁可以访问此元素或其他UI元素。
另一个坏处是UserRoles(存储在DB中)在这里用作字符串 - Allow="Role1, Role2, Role3"
。
在我的新项目中,我有更多的角色/权限,这使得这个解决方案变得更加丑陋。
我已经搜索过,没有发现如何更好地实现它。更好的是,可以在代码中使用枚举作为角色名称,但如何将枚举与数据库同步?
我发现的其他解决方案(solution1,solution2)更好,因为他们不需要转换器,但权限在XAML中再次设置为字符串:
// AuthToVisibility
<Image ... Visibility="{op:AuthToVisibility "CanView"}" />
// AutoToEnabled
<MenuItem IsEnabled="{op:AuthToEnabled "CanClose"}">...</MenuItem>
在UI中处理存储在数据库中的权限的最佳方法是什么?有什么模式吗?
答案 0 :(得分:2)
只要没有人回答,我会尝试。我有一个更好(不理想)的解决方案 首先实现,下面我将写一些关于它的文字。
权限类:
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
的内部列表
PermissionController:
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
列表和初始化方法(权限初始化)。 IsAllowed
属性。将Permission对象(在XAML中设置)转换为Visibility / IsEnabled属性的不同转换器(IValueConverter
)(如果需要,可以发布代码)
XAML:
<Image Visibility="{Binding Permissions.TestPhase, Converter={StaticResource PermissionToVisibility}}" ... />
<TextBox IsEnabled="{Binding Permissions.WEwork, Converter={StaticResource PermissionToBoolean}}" ... />
<Button Command="..." CommandParameter="{Binding Permissions.Manage}" ... />
现在我可以自由管理GUI中的用户角色,角色权限仅在代码中定义。但是我不需要管理角色权限 足够好的是,如果我需要更新/更改角色权限,我将只在代码中的一个位置执行此操作。
如果您有任何问题或建议 - 我愿意接受对话。