diff --git a/base/resource.go b/base/resource.go index 13affac..13ad2c8 100644 --- a/base/resource.go +++ b/base/resource.go @@ -2,6 +2,7 @@ package base import ( "database/sql" + "fmt" "log" "reflect" "unicode" @@ -10,6 +11,7 @@ import ( "github.com/samber/lo" "git.fsdpf.net/go/contracts" + "git.fsdpf.net/go/contracts/helper" "git.fsdpf.net/go/contracts/res_type" "git.fsdpf.net/go/db" ) @@ -142,8 +144,6 @@ func (this Resource) GetDBDriver() string { } func (this Resource) GetAuthDBTable(u contracts.User, params ...any) *db.Builder { - // fmt.Println(this.GetRolesCondition(u).ToSql()) - return this.GetDBTable(append(params, u)...) } @@ -180,6 +180,8 @@ func (this Resource) GetDBTable(params ...any) *db.Builder { // 填充保存数据 this.fillSaveValue(data[i], user, db.TYPE_INSERT) } + } else if user != nil { + this.WithRolesCondition(b, t, user.Roles()...) } }) @@ -200,14 +202,98 @@ func (this Resource) GetDBTable(params ...any) *db.Builder { return builder.Table(string(this.GetTable()), alias) } -func (this Resource) WithRolesCondition(b *db.Builder, roles ...string) { +func (this Resource) WithRolesCondition(b *db.Builder, t string, roles ...string) error { + isFullRight := false + isFullNot := false + NewOrmModel := do.MustInvoke[helper.NewOrmModel](this.container) + NewOrmJoin := do.MustInvoke[helper.NewOrmJoin](this.container) + + GetResRelationResource := do.MustInvoke[GetResRelationResource](this.container) + GetResource := do.MustInvoke[contracts.GetResource](this.container) + GetOrmConditionByRes := do.MustInvoke[GetOrmConditionByRes](this.container) + + items := do.MustInvoke[GetResRoles](this.container)(this.GetUuid(), roles...) + + subTables := lo.Reduce(items, func(carry string, item ResRole, _ int) string { + db := this.GetDB().Table(string(this.GetTable()), this.GetCode()).Select(db.Raw("`" + this.GetCode() + "`.*")) + + joins := lo.Filter(GetResRelations(item.Uuid), func(item ResRelation, _ int) bool { + return item.Type == "inner" || item.Type == "left" || item.Type == "right" + }) + + for i := 0; i < len(joins); i++ { + oResource, ok := GetResource(joins[i].ResourceCode) + if !ok { + continue + } + rResource, ok := GetResRelationResource(joins[i]) + if !ok { + continue + } + + join := NewOrmJoin(contracts.RelationType(joins[i].Type), oResource, joins[i].Code, joins[i].RelationResource, joins[i].RelationField, joins[i].RelationForeignKey) + // 关联扩展条件 + join.SetCondition(GetOrmConditionByRes(joins[i].Uuid, "关联扩展条件")) + + join.Inject(db, NewOrmModel(rResource, rResource.GetCode(), rResource.GetName())) + } + + conditions := GetOrmConditionByRes(item.Uuid, "关联扩展条件") + + if len(joins) == 0 && conditions.IsEmpty() { + // 无权限, 直接跳过这个 unoin 语句 + if carry != "" { + return carry + } + // 第一个无权限除外, 避免所有用户所属角色都是无权限 + db.WhereRaw("false") + isFullNot = true + } else if len(joins) == 0 && conditions.IsNotEmpty() && conditions.IsAlwaysRight() /* 1=1 的这种条件*/ { + // 只要有1个满权限, 直接返回单条语句 + isFullRight = true + return db.ToSql() + } else if conditions.IsNotEmpty() { + db.WhereRaw(string(conditions.ToSql(nil))) + + // 如果前面是无权限的sql查看, 这直接返回本次查询 + if isFullNot { + isFullNot = false + return db.ToSql() + } + } + + if carry != "" { + carry += " UNION " + } + + carry += db.ToSql() + + return carry + }, "") + + if isFullRight { + return nil + } + + // select, delete, update + if isFullNot { + b.WhereRaw("false") + } else if subTables != "" { + if t == db.TYPE_SELECT { + b.Table(subTables, b.TableAlias) + } else { + b.WhereRaw(fmt.Sprintf("id in (SELECT temp.id FROM (%s) as temp)", subTables)) + } + } + + return nil } // 获取鉴权条件 func (this Resource) GetRolesCondition(u contracts.User) *db.Builder { - // isFullRight := false - // isFullNot := false + isFullRight := false + isFullNot := false // NewOrmJoin := do.MustInvoke[helper.NewOrmJoin](this.container) // GetResRelations := do.MustInvoke[GetResRelations](this.container) @@ -277,6 +363,17 @@ func (this Resource) GetRolesCondition(u contracts.User) *db.Builder { // } else if subTables != "" { // this.GetDB().Table(subTables, this.GetCode()) // } + // @todo this.GetCode 要换成 alias + + if isFullRight { + return this.Route.GetResource().GetDB().Table(string(this.GetTable()), this.GetCode()) + } else if isFullNot { + return this.Route.GetResource().GetDB().Table(string(this.GetTable()), this.GetCode()).WhereRaw("false") + } else if subTables != "" { + return this.Route.GetResource().GetDB().Table(subTables, this.GetCode()) + } + + return this.Route.GetResource().GetDB().Table(string(this.GetTable()), this.GetCode()) return this.GetDB().Table(string(this.GetTable()), this.GetCode()) } diff --git a/resource.go b/resource.go index 7ad7bd1..ec4c431 100644 --- a/resource.go +++ b/resource.go @@ -54,8 +54,7 @@ type Resource interface { GetStruct(extends ...reflect.StructField) any GetSliceStruct(extends ...reflect.StructField) any - WithRolesCondition(b *db.Builder, roles ...string) - // GetRolesCondition(u User) + WithRolesCondition(b *db.Builder, t string, roles ...string) error // 是否虚拟资源 IsVirtual() bool