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:
Yixiang Zhao 2022-08-15 10:24:26 +08:00 committed by GitHub
parent ba732b3075
commit dfbf7753c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 104 additions and 9 deletions

View File

@ -29,6 +29,7 @@ type Permission struct {
Users []string `xorm:"mediumtext" json:"users"`
Roles []string `xorm:"mediumtext" json:"roles"`
Domains []string `xorm:"mediumtext" json:"domains"`
Model string `xorm:"varchar(100)" json:"model"`
ResourceType string `xorm:"varchar(100)" json:"resourceType"`

View File

@ -37,11 +37,14 @@ r = sub, obj, act
[policy_definition]
p = permission, sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[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)
if permissionModel != nil {
modelText = permissionModel.ModelText
@ -56,11 +59,6 @@ m = r.sub == p.sub && r.obj == p.obj && r.act == p.act`
panic(err)
}
err = enforcer.LoadFilteredPolicy(xormadapter.Filter{V0: []string{permission.GetId()}})
if err != nil {
panic(err)
}
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 {
permission := GetPermission(permissionRule.V0)
enforcer := getEnforcer(permission)

View File

@ -29,6 +29,7 @@ type Role struct {
Users []string `xorm:"mediumtext" json:"users"`
Roles []string `xorm:"mediumtext" json:"roles"`
Domains []string `xorm:"mediumtext" json:"domains"`
IsEnabled bool `json:"isEnabled"`
}
@ -88,7 +89,8 @@ func GetRole(id string) *Role {
func UpdateRole(id string, role *Role) bool {
owner, name := util.GetOwnerAndNameFromId(id)
if getRole(owner, name) == nil {
oldRole := getRole(owner, name)
if oldRole == nil {
return false
}
@ -97,6 +99,11 @@ func UpdateRole(id string, role *Role) bool {
panic(err)
}
if affected != 0 {
removeGroupingPolicies(oldRole)
addGroupingPolicies(role)
}
return affected != 0
}
@ -106,6 +113,10 @@ func AddRole(role *Role) bool {
panic(err)
}
if affected != 0 {
addGroupingPolicies(role)
}
return affected != 0
}
@ -115,6 +126,10 @@ func DeleteRole(role *Role) bool {
panic(err)
}
if affected != 0 {
removeGroupingPolicies(role)
}
return affected != 0
}

View File

@ -210,6 +210,20 @@ class PermissionEditPage extends React.Component {
</Select>
</Col>
</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"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("permission:Resource type"), i18next.t("permission:Resource type - Tooltip"))} :

View File

@ -31,6 +31,7 @@ class PermissionListPage extends BaseListPage {
displayName: `New Permission - ${randomName}`,
users: [],
roles: [],
domains: [],
resourceType: "Application",
resources: ["app-built-in"],
actions: ["Read"],
@ -139,6 +140,16 @@ class PermissionListPage extends BaseListPage {
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"),
dataIndex: "resourceType",

View File

@ -164,6 +164,20 @@ class RoleEditPage extends React.Component {
</Select>
</Col>
</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"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
{Setting.getLabel(i18next.t("general:Is enabled"), i18next.t("general:Is enabled - Tooltip"))} :

View File

@ -31,6 +31,7 @@ class RoleListPage extends BaseListPage {
displayName: `New Role - ${randomName}`,
users: [],
roles: [],
domains: [],
isEnabled: true,
};
}
@ -135,6 +136,16 @@ class RoleListPage extends BaseListPage {
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"),
dataIndex: "isEnabled",