mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-08 00:50:28 +08:00
feat: support RBAC model in permission (#1006)
Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com> Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com>
This commit is contained in:
@ -27,8 +27,9 @@ type Permission struct {
|
|||||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||||
|
|
||||||
Users []string `xorm:"mediumtext" json:"users"`
|
Users []string `xorm:"mediumtext" json:"users"`
|
||||||
Roles []string `xorm:"mediumtext" json:"roles"`
|
Roles []string `xorm:"mediumtext" json:"roles"`
|
||||||
|
Domains []string `xorm:"mediumtext" json:"domains"`
|
||||||
|
|
||||||
Model string `xorm:"varchar(100)" json:"model"`
|
Model string `xorm:"varchar(100)" json:"model"`
|
||||||
ResourceType string `xorm:"varchar(100)" json:"resourceType"`
|
ResourceType string `xorm:"varchar(100)" json:"resourceType"`
|
||||||
|
@ -37,11 +37,14 @@ r = sub, obj, act
|
|||||||
[policy_definition]
|
[policy_definition]
|
||||||
p = permission, sub, obj, act
|
p = permission, sub, obj, act
|
||||||
|
|
||||||
|
[role_definition]
|
||||||
|
g = _, _
|
||||||
|
|
||||||
[policy_effect]
|
[policy_effect]
|
||||||
e = some(where (p.eft == allow))
|
e = some(where (p.eft == allow))
|
||||||
|
|
||||||
[matchers]
|
[matchers]
|
||||||
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act`
|
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act`
|
||||||
permissionModel := getModel(permission.Owner, permission.Model)
|
permissionModel := getModel(permission.Owner, permission.Model)
|
||||||
if permissionModel != nil {
|
if permissionModel != nil {
|
||||||
modelText = permissionModel.ModelText
|
modelText = permissionModel.ModelText
|
||||||
@ -56,11 +59,6 @@ m = r.sub == p.sub && r.obj == p.obj && r.act == p.act`
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = enforcer.LoadFilteredPolicy(xormadapter.Filter{V0: []string{permission.GetId()}})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return enforcer
|
return enforcer
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,6 +100,37 @@ func removePolicies(permission *Permission) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getGroupingPolicies(role *Role) [][]string {
|
||||||
|
var groupingPolicies [][]string
|
||||||
|
for _, subUser := range role.Users {
|
||||||
|
groupingPolicies = append(groupingPolicies, []string{subUser, role.GetId()})
|
||||||
|
}
|
||||||
|
for _, subRole := range role.Roles {
|
||||||
|
groupingPolicies = append(groupingPolicies, []string{subRole, role.GetId()})
|
||||||
|
}
|
||||||
|
return groupingPolicies
|
||||||
|
}
|
||||||
|
|
||||||
|
func addGroupingPolicies(role *Role) {
|
||||||
|
enforcer := getEnforcer(&Permission{})
|
||||||
|
groupingPolicies := getGroupingPolicies(role)
|
||||||
|
|
||||||
|
_, err := enforcer.AddGroupingPolicies(groupingPolicies)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeGroupingPolicies(role *Role) {
|
||||||
|
enforcer := getEnforcer(&Permission{})
|
||||||
|
groupingPolicies := getGroupingPolicies(role)
|
||||||
|
|
||||||
|
_, err := enforcer.RemoveGroupingPolicies(groupingPolicies)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Enforce(userId string, permissionRule *PermissionRule) bool {
|
func Enforce(userId string, permissionRule *PermissionRule) bool {
|
||||||
permission := GetPermission(permissionRule.V0)
|
permission := GetPermission(permissionRule.V0)
|
||||||
enforcer := getEnforcer(permission)
|
enforcer := getEnforcer(permission)
|
||||||
|
@ -29,6 +29,7 @@ type Role struct {
|
|||||||
|
|
||||||
Users []string `xorm:"mediumtext" json:"users"`
|
Users []string `xorm:"mediumtext" json:"users"`
|
||||||
Roles []string `xorm:"mediumtext" json:"roles"`
|
Roles []string `xorm:"mediumtext" json:"roles"`
|
||||||
|
Domains []string `xorm:"mediumtext" json:"domains"`
|
||||||
IsEnabled bool `json:"isEnabled"`
|
IsEnabled bool `json:"isEnabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +89,8 @@ func GetRole(id string) *Role {
|
|||||||
|
|
||||||
func UpdateRole(id string, role *Role) bool {
|
func UpdateRole(id string, role *Role) bool {
|
||||||
owner, name := util.GetOwnerAndNameFromId(id)
|
owner, name := util.GetOwnerAndNameFromId(id)
|
||||||
if getRole(owner, name) == nil {
|
oldRole := getRole(owner, name)
|
||||||
|
if oldRole == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +99,11 @@ func UpdateRole(id string, role *Role) bool {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if affected != 0 {
|
||||||
|
removeGroupingPolicies(oldRole)
|
||||||
|
addGroupingPolicies(role)
|
||||||
|
}
|
||||||
|
|
||||||
return affected != 0
|
return affected != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,6 +113,10 @@ func AddRole(role *Role) bool {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if affected != 0 {
|
||||||
|
addGroupingPolicies(role)
|
||||||
|
}
|
||||||
|
|
||||||
return affected != 0
|
return affected != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +126,10 @@ func DeleteRole(role *Role) bool {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if affected != 0 {
|
||||||
|
removeGroupingPolicies(role)
|
||||||
|
}
|
||||||
|
|
||||||
return affected != 0
|
return affected != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,6 +210,20 @@ class PermissionEditPage extends React.Component {
|
|||||||
</Select>
|
</Select>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row style={{marginTop: "20px"}} >
|
||||||
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("role:Sub domains"), i18next.t("role:Sub domains - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<Select virtual={false} mode="tags" style={{width: "100%"}} value={this.state.permission.domains} onChange={(value => {
|
||||||
|
this.updateRoleField("domains", value);
|
||||||
|
})}>
|
||||||
|
{
|
||||||
|
this.state.permission.domains.map((domain, index) => <Option key={index} value={domain}>{domain}</Option>)
|
||||||
|
}
|
||||||
|
</Select>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("permission:Resource type"), i18next.t("permission:Resource type - Tooltip"))} :
|
{Setting.getLabel(i18next.t("permission:Resource type"), i18next.t("permission:Resource type - Tooltip"))} :
|
||||||
|
@ -31,6 +31,7 @@ class PermissionListPage extends BaseListPage {
|
|||||||
displayName: `New Permission - ${randomName}`,
|
displayName: `New Permission - ${randomName}`,
|
||||||
users: [],
|
users: [],
|
||||||
roles: [],
|
roles: [],
|
||||||
|
domains: [],
|
||||||
resourceType: "Application",
|
resourceType: "Application",
|
||||||
resources: ["app-built-in"],
|
resources: ["app-built-in"],
|
||||||
actions: ["Read"],
|
actions: ["Read"],
|
||||||
@ -139,6 +140,16 @@ class PermissionListPage extends BaseListPage {
|
|||||||
return Setting.getTags(text);
|
return Setting.getTags(text);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: i18next.t("role:Sub domains"),
|
||||||
|
dataIndex: "domains",
|
||||||
|
key: "domains",
|
||||||
|
sorter: true,
|
||||||
|
...this.getColumnSearchProps("domains"),
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return Setting.getTags(text);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: i18next.t("permission:Resource type"),
|
title: i18next.t("permission:Resource type"),
|
||||||
dataIndex: "resourceType",
|
dataIndex: "resourceType",
|
||||||
|
@ -164,6 +164,20 @@ class RoleEditPage extends React.Component {
|
|||||||
</Select>
|
</Select>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row style={{marginTop: "20px"}} >
|
||||||
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("role:Sub domains"), i18next.t("role:Sub domains - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<Select virtual={false} mode="tags" style={{width: "100%"}} value={this.state.role.domains} onChange={(value => {
|
||||||
|
this.updateRoleField("domains", value);
|
||||||
|
})}>
|
||||||
|
{
|
||||||
|
this.state.role.domains.map((domain, index) => <Option key={index} value={domain}>{domain}</Option>)
|
||||||
|
}
|
||||||
|
</Select>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||||
{Setting.getLabel(i18next.t("general:Is enabled"), i18next.t("general:Is enabled - Tooltip"))} :
|
{Setting.getLabel(i18next.t("general:Is enabled"), i18next.t("general:Is enabled - Tooltip"))} :
|
||||||
|
@ -31,6 +31,7 @@ class RoleListPage extends BaseListPage {
|
|||||||
displayName: `New Role - ${randomName}`,
|
displayName: `New Role - ${randomName}`,
|
||||||
users: [],
|
users: [],
|
||||||
roles: [],
|
roles: [],
|
||||||
|
domains: [],
|
||||||
isEnabled: true,
|
isEnabled: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -135,6 +136,16 @@ class RoleListPage extends BaseListPage {
|
|||||||
return Setting.getTags(text);
|
return Setting.getTags(text);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: i18next.t("role:Sub domains"),
|
||||||
|
dataIndex: "domains",
|
||||||
|
key: "domains",
|
||||||
|
sorter: true,
|
||||||
|
...this.getColumnSearchProps("domains"),
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return Setting.getTags(text);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: i18next.t("general:Is enabled"),
|
title: i18next.t("general:Is enabled"),
|
||||||
dataIndex: "isEnabled",
|
dataIndex: "isEnabled",
|
||||||
|
Reference in New Issue
Block a user