2012-11-26 96 views
0

我有2个域对象,用户和SystemRights(这是一个多对多的,所以1个用户可以有很多权利,1个权利可以为许多用户所有)。我正在寻找一种简单的方法来检查用户是否具有所需的权限。Grails:GORM:遍历多对多关系

用户域

class User { 

    static hasMany = [systemRights: SystemRight, enterpriseUsers: EnterpriseUser] 

    String email; 
    String passwordHash; 
} 

SystemRight域

class SystemRight { 

    public static final String LOGIN = "LOGIN" 
    public static final String MODIFY_ALL_ENTERPRISES = "MODIFY_ALL_ENTERPRISES" 
    public static final String ADMINISTER_SYSTEM = "ADMINISTER_SYSTEM" 
    public static final String VALIDATE_SUPPLIER_SCORECARDS = "VALIDATE_SUPPLIER_SCORECARDS" 

    static hasMany = [users:User] 
    static belongsTo = User 

    String name 
} 

下并没有为我工作:

在User.class

public boolean hasRights(List<String> requiredRights) { 

    def userHasRight = SystemRight.findByUserAndSystemRight (this, SystemRight.findByName(requiredRight)); 

    // Nor this 

    def userHasRight = this.systemRights.contains(SystemRight.findByName(requiredRight)); 

} 

当前可怕的解决方案

public boolean hasRights(List<String> requiredRights) { 

    for (String requiredRight : requiredRights) { 

     def has = false 

     for (SystemRight userRight : user.systemRights) { 
      if (userRight.name == requiredRight) { 
       has = true 
       break; 
      } 
     } 

     if (has == false) { 
      return false; 
     }    
    } 

    return true   

} 

回答

2

如果你能够/愿意改变了一点东西,我强烈建议执行以下操作。它会让你的生活变得如此简单。

首先,从两个域中删除hasMany for SystemRight和User,并从SystemRight中删除belongsTo User。

接下来,创建表示连接表的域。

class UserSystemRight { 
    User user 
    SystemRight systemRight 

    boolean equals(other) { 
     if (!(other instanceof UserSystemRight)) { 
      return false 
     } 
     other.user?.id == user?.id && other.systemRight?.id == systemRight?.id 
    } 

    int hashCode() { 
     def builder = new HashCodeBuilder() 
     if (user) builder.append(user.id) 
     if (systemRight) builder.append(systemRight.id) 
     builder.toHashCode() 
    } 


    // add some more convenience methods here if you want like... 
    static UserSystemRight get(long userId, long systemRightId, String systemRightName) { 
     find 'from UserSystemRight where user.id=:userId and systemRight.id=:systemRightId and systemRight.name=:systemRightName', 
      [userId: userId, systemRightId: systemRightId, systemRightName: systemRightName] 
    } 
} 

然后,在你的用户类,你可以添加这个方法:

Set<SystemRight> getSystemRights() { 
    UserSystemRight.findAllByUser(this).collect { it.systemRight } as Set 
} 

然后,将它添加到您的SystemRight域:

Set<User> getUsers() { 
    UserSystemRight.findAllBySystemRight(this).collect { it.user } as Set 
} 

对于为什么这个更详细的explenation除了真正解决你的问题,方法是充满胜利的,take a gander at this

+0

您好格雷格,感谢您的回答。你是否建议失去多对多的关系?由于这些限制,我在User和Enterprise和UserEnterprise上做了这些工作。如果这是你的建议,那么我想我会杀死我项目中的所有m2m关系。 – Spider

+1

它仍然是m2m,你只是自己管理连接表。 – Gregg

+0

完成!没有更多的麻烦! – Spider

0

以下情况如何?

public boolean hasRights(List<String> requiredRights) { 
    return null != (this.systemRights.find { requiredRights.contains(it) }); 
} 

(未测试:这里的Groovy新手)

+0

我完全喜欢null!=技巧。以前从未想过这件事! – Spider

1

我肯定会尝试在数据库中解决此问题。

def relevantUserRights = SystemRight.withCriteria { 
    eq("user", this) 
    "in"("name", requiredRights); 
} 

return relevantUserRights.size() == requiredRights.size() 
+0

+1谢谢。我测试了它并且它可以工作,但我决定使用@ Gregg的答案并重构我的域对象来创建一个明确的连接表。 – Spider