优化
This commit is contained in:
+53
-21
@@ -2,6 +2,7 @@ package data
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"log/slog"
|
||||
"reflect"
|
||||
"strings"
|
||||
@@ -18,6 +19,11 @@ import (
|
||||
// Casbin, while ownership columns on business tables are row-level scope.
|
||||
type dataScopeAuditEnqueue func(dataAccessLogPO)
|
||||
|
||||
var (
|
||||
errDataScopeRequired = errors.New("受控表访问缺少数据权限上下文")
|
||||
errInvalidDataScope = errors.New("数据权限范围不合法")
|
||||
)
|
||||
|
||||
func registerDataScopeCallbacks(db *gorm.DB, enqueue dataScopeAuditEnqueue) {
|
||||
if db == nil {
|
||||
return
|
||||
@@ -40,7 +46,7 @@ func registerDataScopeCallbacks(db *gorm.DB, enqueue dataScopeAuditEnqueue) {
|
||||
}
|
||||
c := db.Callback().Create()
|
||||
if c.Get("data_scope:stamp") == nil {
|
||||
_ = c.Before("gorm:create").Register("data_scope:stamp", stampOwnership)
|
||||
_ = c.Before("gorm:create").Register("data_scope:stamp", stampOwnership(enqueue))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +58,16 @@ func isControlledTable(db *gorm.DB) bool {
|
||||
return db.Statement.Schema != nil && !strings.HasPrefix(db.Statement.Table, "sys_") && (hasScopeField(db, "dept_id") || hasScopeField(db, "created_by"))
|
||||
}
|
||||
|
||||
func skipDataScope(db *gorm.DB) bool {
|
||||
skip, ok := db.Get("data_scope:skip")
|
||||
value, _ := skip.(bool)
|
||||
return ok && value
|
||||
}
|
||||
|
||||
func validDataScope(scope biz.DataScope) bool {
|
||||
return scope.UserID != 0 && scope.AuthorityID != 0 && scope.Scope >= 1 && scope.Scope <= 5 && scope.All == (scope.Scope == 1)
|
||||
}
|
||||
|
||||
func applyDataScope(operation string, enqueue dataScopeAuditEnqueue) func(*gorm.DB) {
|
||||
return func(db *gorm.DB) {
|
||||
if !isControlledTable(db) {
|
||||
@@ -60,15 +76,19 @@ func applyDataScope(operation string, enqueue dataScopeAuditEnqueue) func(*gorm.
|
||||
if _, done := db.Statement.Clauses["data_scope:applied"]; done {
|
||||
return
|
||||
}
|
||||
if skip, ok := db.Get("data_scope:skip"); ok {
|
||||
if value, _ := skip.(bool); value {
|
||||
return
|
||||
}
|
||||
if skipDataScope(db) {
|
||||
return
|
||||
}
|
||||
scope, ok := biz.DataScopeFromContext(db.Statement.Context)
|
||||
if !ok {
|
||||
slog.WarnContext(db.Statement.Context, "数据权限: 业务表访问无身份上下文, 已放行(待补 ctx / 或使用系统上下文)", "mod", "data-scope", "table", db.Statement.Table)
|
||||
recordDataScopeEvent(db, enqueue, "no_identity", operation, "无身份上下文访问受控表, 已放行", biz.DataScope{})
|
||||
slog.WarnContext(db.Statement.Context, "数据权限: 业务表访问无身份上下文, 已拒绝", "mod", "data-scope", "table", db.Statement.Table)
|
||||
recordDataScopeEvent(db, enqueue, "no_identity", operation, "无身份上下文访问受控表, 已拒绝", biz.DataScope{})
|
||||
_ = db.AddError(errDataScopeRequired)
|
||||
return
|
||||
}
|
||||
if !validDataScope(scope) {
|
||||
recordDataScopeEvent(db, enqueue, "invalid_scope", operation, "数据权限上下文不合法, 已拒绝", scope)
|
||||
_ = db.AddError(errInvalidDataScope)
|
||||
return
|
||||
}
|
||||
if (operation == "update" || operation == "delete") && !db.AllowGlobalUpdate && !hasWriteConditions(db) {
|
||||
@@ -86,10 +106,13 @@ func applyDataScope(operation string, enqueue dataScopeAuditEnqueue) func(*gorm.
|
||||
if hasScopeField(db, "dept_id") {
|
||||
ids := scope.DepartmentIDs
|
||||
if len(ids) == 0 {
|
||||
ids = []uint{0}
|
||||
db.Where("1 = 0")
|
||||
return
|
||||
}
|
||||
db.Where(table+".dept_id IN ?", ids)
|
||||
return
|
||||
}
|
||||
db.Where("1 = 0")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,19 +134,28 @@ func auditBlockedWrite(operation string, enqueue dataScopeAuditEnqueue) func(*go
|
||||
}
|
||||
}
|
||||
|
||||
func stampOwnership(db *gorm.DB) {
|
||||
if !isControlledTable(db) {
|
||||
return
|
||||
}
|
||||
scope, ok := biz.DataScopeFromContext(db.Statement.Context)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if hasScopeField(db, "created_by") && scope.UserID != 0 {
|
||||
db.Statement.SetColumn("created_by", scope.UserID, true)
|
||||
}
|
||||
if hasScopeField(db, "dept_id") && scope.PrimaryDeptID != 0 {
|
||||
db.Statement.SetColumn("dept_id", scope.PrimaryDeptID, true)
|
||||
func stampOwnership(enqueue dataScopeAuditEnqueue) func(*gorm.DB) {
|
||||
return func(db *gorm.DB) {
|
||||
if !isControlledTable(db) || skipDataScope(db) {
|
||||
return
|
||||
}
|
||||
scope, ok := biz.DataScopeFromContext(db.Statement.Context)
|
||||
if !ok {
|
||||
recordDataScopeEvent(db, enqueue, "no_identity", "create", "无身份上下文访问受控表, 已拒绝", biz.DataScope{})
|
||||
_ = db.AddError(errDataScopeRequired)
|
||||
return
|
||||
}
|
||||
if !validDataScope(scope) {
|
||||
recordDataScopeEvent(db, enqueue, "invalid_scope", "create", "数据权限上下文不合法, 已拒绝", scope)
|
||||
_ = db.AddError(errInvalidDataScope)
|
||||
return
|
||||
}
|
||||
if hasScopeField(db, "created_by") {
|
||||
db.Statement.SetColumn("created_by", scope.UserID, true)
|
||||
}
|
||||
if hasScopeField(db, "dept_id") {
|
||||
db.Statement.SetColumn("dept_id", scope.PrimaryDeptID, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user