首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有三个层次结构的权限系统LINQ查询

具有三个层次结构的权限系统LINQ查询
EN

Stack Overflow用户
提问于 2011-02-07 19:14:58
回答 1查看 341关注 0票数 0

这一点对我来说有点难以用书面解释,我感谢你们中的任何人花时间阅读这个冗长的问题。我不愿意使用LINQ查询来解决这个问题,只是做某种类型的循环或递归,如果效果更好的话。

我正在开发一个在某种程度上基于NETSqlAzMan的权限/授权系统。

这些是主要的概念:

  • 权限是为两个给定的“安全项”授权的权限。
  • "Securable“是既可以对其进行授权(在这里考虑用户或用户组),也可以为其创建对象(比如文件或文档)的对象。示例: User1和File1都是“安全的”,User1可以被授权编辑File1。
  • "Securables“可以有父级和子级”安全“。
  • “权限”可以具有父权限和/或子权限。

这是一个更具体的例子,它是如何工作的。

保修品:

代码语言:javascript
复制
- Administrators  
    - Tom  
    - Mike  
- Editors  
    - John  
    - Lisa  
- Documents  
    - Document1  
    - Document2  

权限:

  • Edit_Document

代码语言:javascript
复制
- Edit\_Title  
- Edit\_Body  
- Change\_BGColor

上述数据存储在两个表中,安全表和权限表包含两个中间表: GroupMembership (安全层次结构)和PermissionRelationship (权限层次结构)。

还有一个名为“授权”的表,它包含由一个安全为"AuthorizedID“、一个安全为"SecurableID”、一个权限为"PermissionID“和一个Enum组成的授权,可以继承(0)、允许(1)或拒绝(2)。

我为所有表设置了LINQ2SQL实体,还设置了一个函数,该函数返回给定安全的所有祖先和返回所有给定权限的祖先。

我很难确定一个查询,该查询正确地检查每个权限的所有3个层次结构,以确定为给定的authorizedID和SecurableID设置的有效权限和最近级别的授权。

例如:如果授予管理员对"Edit_Document“权限的”允许“,那么对给定的”AuthorizedID“的”管理员“和”文档“的SecurableiD的查询应该返回:

  • AuthorizedID:Administrators SecurableID:文档允许
  • AuthorizedID:Administrators SecurableID:文档允许Permission:Edit_Title
  • AuthorizedID:Administrators SecurableID:文档允许Permission:Edit_Body
  • AuthorizedID:Administrators SecurableID:文档允许Permission:Change_BGColor

另外,如果在"Document1“上添加了"Mike”和"Change_BGColor“的授权(拒绝重写链中的任何允许),那么查询"Mike”的AuthorizedID和"Document1“的SecurableID的结果将返回:

  • AuthorizedID:Administrators SecurableID:文档允许
  • AuthorizedID:Administrators SecurableID:文档允许Permission:Edit_Title
  • AuthorizedID:Administrators SecurableID:文档允许Permission:Edit_Body
  • AuthorizedID:Mike SecurableID:Document1 1拒绝Permission:Change_BGColor

这就是我到目前为止处理AuthorizedID和SecurableID层次结构的方法,但是没有正确地考虑权限层次结构。我不确定如何将权限层次结构考虑在内,以便如果权限的一个祖先被设置为拒绝,那么子权限也会显示拒绝,结果包括设置拒绝的AuthorizedID和SecurableID。

代码语言:javascript
复制
public List<LocalPermission> GetSecurablesLocalPermissions(Guid authorizedID, Guid securableID)
    {
        var localAuthorization = (from eff in
                                       (from p in dc.Permissions
                                        let a = (from sa in dc.AllSecurablesAuthorizations(authorizedID)
                                                 where sa.PermissionID == p.PermissionID
                                                 group sa by sa.PermissionID into g
                                                 select g.OrderBy(x => x.Lvl).OrderByDescending(x => x.AuthorizationBits).First()).FirstOrDefault()
                                        select new
                                        {
                                            PermissionID = p.PermissionID,
                                            PermissionName = p.PermissionName,
                                            AuthorizationBits = a.AuthorizationBits ?? 0,
                                            SecurableID = a.SecurableID ?? Guid.Empty,
                                            SecurableName = a.SecurableName,
                                            AuthorizedName = a.AuthorizedName,
                                            AuthorizedID = a.AuthorizedID ?? Guid.Empty
                                        })
                                   join l in
                                       (from p in dc.Permissions
                                        join la in dc.Authorizations
                                           on p.PermissionID equals la.PermissionID into laJoin
                                        from localJoin in laJoin.Where(x => (x.SecurableID == securableID /*|| localJoin.SecurableID == Guid.Empty*/) && (x.AuthorizedID == authorizedID /*|| localJoin.AuthorizedID == Guid.Empty*/)).DefaultIfEmpty()
                                        select new
                                                   {
                                                       PermissionID = p.PermissionID,
                                                       PermissionName = p.PermissionName,
                                                       AuthorizationBits = localJoin == null ? 0 : localJoin.AuthorizationBits,
                                                       SecurableID = localJoin == null ? Guid.Empty : localJoin.SecurableID,
                                                       SecurableName = localJoin == null ? null : localJoin.SecurableName,
                                                       AuthorizedName = localJoin == null ? null : localJoin.AuthorizedName,
                                                       AuthorizedID = localJoin == null ? Guid.Empty : localJoin.AuthorizedID
                                                   }) on eff.PermissionID equals l.PermissionID
                                   select new LocalPermission
                                   {
                                       PermissionID = l.PermissionID,
                                       PermissionName = l.PermissionName,
                                       AuthorizationBits = l.AuthorizationBits,
                                       SecurableID = securableID,
                                       SecurableName = (from s in dc.Securables
                                                        where s.SecurableID == securableID
                                                        select s).SingleOrDefault().SecurableName,
                                       AuthorizedID = authorizedID,
                                       AuthorizedName = (from s in dc.Securables
                                                         where s.SecurableID == authorizedID
                                                         select s).SingleOrDefault().SecurableName,
                                       EffectiveAuthorizationBits = eff.AuthorizationBits == 0 ? l.AuthorizationBits : eff.AuthorizationBits
                                   }).ToList<LocalPermission>();

        return localAuthorization;
    }
EN

回答 1

Stack Overflow用户

发布于 2011-02-08 21:40:09

这太恶心了。

回答:“因此,如果权限的一个祖先被设置为拒绝,那么子权限也会显示拒绝”,这意味着您需要递归。数据库中的父/子关系通常意味着递归。linq不支持递归,但本机sql支持递归(公共表表达式)。

我的策略是将所有权限都拉到一个列表中,然后编写普通的过程递归代码来回答您的查询(我没有完全理解)。在这种情况下,我推荐TDD。希望这能让你走上正轨。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4925437

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档