Skip to content

Commit 809bce8

Browse files
authored
feat: add ConditionToGormQuery() API (#210)
* feat: ConditionToGormQuery * fix: delete local test * fix: import sort
1 parent d7df6d8 commit 809bce8

6 files changed

+121
-3
lines changed

README.md

+75
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,81 @@ func main() {
149149
}
150150
}
151151
```
152+
## ConditionsToGormQuery
153+
154+
`ConditionsToGormQuery()` is a function that converts multiple query conditions into a GORM query statement
155+
You can use the `GetAllowedObjectConditions()` API of Casbin to get conditions,
156+
and choose the way of combining conditions through `combineType`.
157+
158+
`ConditionsToGormQuery()` allows Casbin to be combined with SQL, and you can use it to implement many functions.
159+
### Example: GetAllowedRecordsForUser
160+
* model example: [object_conditions_model.conf](examples/object_conditions_model.conf)
161+
* policy example: [object_conditions_policy.csv](examples/object_conditions_policy.csv)
162+
163+
DataBase example:
164+
165+
|id|title|author|publisher|publish_data|price|category_id|
166+
|--|--|--|--|--|--|--|
167+
|1|book1|author1|publisher1|2023-04-09 16:23:42|10|1|
168+
|2|book2|author1|publisher1|2023-04-09 16:23:44|20|2|
169+
|3|book3|author2|publisher1|2023-04-09 16:23:44|30|1|
170+
|4|book4|author2|publisher2|2023-04-09 16:23:45|10|3|
171+
|5|book5|author3|publisher2|2023-04-09 16:23:45|50|1|
172+
|6|book6|author3|publisher2|2023-04-09 16:23:46|60|2|
173+
174+
175+
```go
176+
type Book struct {
177+
ID int
178+
Title string
179+
Author string
180+
Publisher string
181+
PublishDate time.Time
182+
Price float64
183+
CategoryID int
184+
}
185+
186+
func TestGetAllowedRecordsForUser(t *testing.T) {
187+
e, _ := casbin.NewEnforcer("examples/object_conditions_model.conf", "examples/object_conditions_policy.csv")
188+
189+
conditions, err := e.GetAllowedObjectConditions("alice", "read", "r.obj.")
190+
if err != nil {
191+
panic(err)
192+
}
193+
fmt.Println(conditions)
194+
195+
dsn := "root:root@tcp(127.0.0.1:3307)/test?charset=utf8mb4&parseTime=True&loc=Local"
196+
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
197+
if err != nil {
198+
panic(err)
199+
}
200+
201+
fmt.Println("CombineTypeOr")
202+
rows, err := ConditionsToGormQuery(db, conditions, CombineTypeOr).Model(&Book{}).Rows()
203+
defer rows.Close()
204+
var b Book
205+
for rows.Next() {
206+
err := db.ScanRows(rows, &b)
207+
if err != nil {
208+
panic(err)
209+
}
210+
log.Println(b)
211+
}
212+
213+
fmt.Println("CombineTypeAnd")
214+
rows, err = ConditionsToGormQuery(db, conditions, CombineTypeAnd).Model(&Book{}).Rows()
215+
defer rows.Close()
216+
for rows.Next() {
217+
err := db.ScanRows(rows, &b)
218+
if err != nil {
219+
panic(err)
220+
}
221+
log.Println(b)
222+
}
223+
}
224+
```
225+
226+
152227
## Getting Help
153228

154229
- [Casbin](https://github.com/casbin/casbin)

adapter.go

+24
Original file line numberDiff line numberDiff line change
@@ -977,3 +977,27 @@ func (c *CasbinRule) toStringPolicy() []string {
977977
}
978978
return policy
979979
}
980+
981+
// CombineType represents different types of condition combining strategies
982+
type CombineType uint32
983+
984+
const (
985+
CombineTypeOr CombineType = iota // Combine conditions with OR operator
986+
CombineTypeAnd // Combine conditions with AND operator
987+
)
988+
989+
// ConditionsToGormQuery is a function that converts multiple query conditions into a GORM query statement
990+
// You can use the GetAllowedObjectConditions() API of Casbin to get conditions,
991+
// and choose the way of combining conditions through combineType.
992+
func ConditionsToGormQuery(db *gorm.DB, conditions []string, combineType CombineType) *gorm.DB {
993+
queryDB := db
994+
for _, cond := range conditions {
995+
switch combineType {
996+
case CombineTypeOr:
997+
queryDB = queryDB.Or(cond)
998+
case CombineTypeAnd:
999+
queryDB = queryDB.Where(cond)
1000+
}
1001+
}
1002+
return queryDB
1003+
}

examples/object_conditions_model.conf

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[request_definition]
2+
r = sub, obj, act
3+
4+
[policy_definition]
5+
p = sub, sub_rule, act
6+
7+
[role_definition]
8+
g = _, _
9+
10+
[policy_effect]
11+
e = some(where (p.eft == allow))
12+
13+
[matchers]
14+
m = g(r.sub, p.sub) && eval(p.sub_rule) && r.act == p.act

examples/object_conditions_policy.csv

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
p, alice, r.obj.price < 25, read
2+
p, admin, r.obj.category_id = 2, read
3+
p, bob, r.obj.author = bob, write
4+
5+
g, alice, admin

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/casbin/gorm-adapter/v3
33
go 1.20
44

55
require (
6-
github.com/casbin/casbin/v2 v2.55.1
6+
github.com/casbin/casbin/v2 v2.68.0
77
github.com/glebarez/sqlite v1.7.0
88
github.com/go-sql-driver/mysql v1.6.0
99
github.com/lib/pq v1.10.2

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1
77
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
88
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
99
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
10-
github.com/casbin/casbin/v2 v2.55.1 h1:vaTAHSLkQfielg9UiHdIdvIVK/NAmMjBkDkrOM9iDqI=
11-
github.com/casbin/casbin/v2 v2.55.1/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
10+
github.com/casbin/casbin/v2 v2.68.0 h1:7L4kwNJJw/pzdSEhl4SkeHz+1JzYn8guO+Q422sxzLM=
11+
github.com/casbin/casbin/v2 v2.68.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
1212
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
1313
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
1414
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=

0 commit comments

Comments
 (0)