feat: better admin permissions (#5755)
* feat: add casbin admin permissions * feat: improve audit logging to associate logs with actual operators and target users * feat: enhance admin permissions and UI interactions for sensitive actions * Refactor authz RBAC and tighten channel permissions * Split channel authz field policy * Address channel authz review findings
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
package authz
|
||||
|
||||
import "github.com/casbin/casbin/v2"
|
||||
|
||||
// Can reports whether the subject may perform the permission. A superuser role
|
||||
// short-circuits to allow. Otherwise a per-user override wins, then the union of
|
||||
// the subject's role baselines applies.
|
||||
func Can(userID int, systemRole int, permission Permission) bool {
|
||||
roles := resolveSubjectRoles(userID, systemRole)
|
||||
if len(roles) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, role := range roles {
|
||||
if isSuperuserRole(role) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if !isKnownPermission(permission) {
|
||||
return false
|
||||
}
|
||||
|
||||
e := currentEnforcer()
|
||||
if e == nil {
|
||||
return false
|
||||
}
|
||||
if effect, ok := explicitSubjectEffect(e, UserSubject(userID), permission); ok {
|
||||
return effect == EffectAllow
|
||||
}
|
||||
for _, role := range roles {
|
||||
if roleBaselineAllows(e, role, permission) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Capabilities returns the full resource/action matrix the subject is allowed.
|
||||
func Capabilities(userID int, systemRole int) PermissionsMap {
|
||||
result := make(PermissionsMap, len(registry))
|
||||
for _, resource := range registry {
|
||||
actions := make(map[string]bool, len(resource.Actions))
|
||||
for _, action := range resource.Actions {
|
||||
actions[action.Action] = Can(userID, systemRole, Permission{
|
||||
Resource: resource.Resource,
|
||||
Action: action.Action,
|
||||
})
|
||||
}
|
||||
result[resource.Resource] = actions
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func roleBaselineAllows(e *casbin.SyncedEnforcer, roleKey string, permission Permission) bool {
|
||||
effect, ok := explicitSubjectEffect(e, RoleSubject(roleKey), permission)
|
||||
return ok && effect == EffectAllow
|
||||
}
|
||||
|
||||
func explicitSubjectEffect(e *casbin.SyncedEnforcer, subject string, permission Permission) (string, bool) {
|
||||
policies, err := e.GetFilteredPolicy(0, subject, permission.Resource, permission.Action)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
hasAllow := false
|
||||
for _, policy := range policies {
|
||||
switch policyEffect(policy) {
|
||||
case EffectDeny:
|
||||
return EffectDeny, true
|
||||
case EffectAllow:
|
||||
hasAllow = true
|
||||
}
|
||||
}
|
||||
if hasAllow {
|
||||
return EffectAllow, true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func policyEffect(policy []string) string {
|
||||
if len(policy) < 4 || policy[3] == "" {
|
||||
return EffectAllow
|
||||
}
|
||||
return policy[3]
|
||||
}
|
||||
Reference in New Issue
Block a user