Skip to content

Commit d4ad5d9

Browse files
authored
Merge pull request #73 from Despire/custom_table
add custom table support
2 parents 7f6a211 + dcb03ce commit d4ad5d9

File tree

3 files changed

+123
-3
lines changed

3 files changed

+123
-3
lines changed

README.md

+46
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,52 @@ func main() {
6363
}
6464
```
6565

66+
## Customize table columns example
67+
You can change the gorm struct tags, but the table structure must stay the same.
68+
```go
69+
package main
70+
71+
import (
72+
"github.com/casbin/casbin/v2"
73+
gormadapter "github.com/casbin/gorm-adapter/v3"
74+
"gorm.io/gorm"
75+
)
76+
77+
func main() {
78+
// Increase the column size to 512.
79+
type CasbinRule struct {
80+
ID uint `gorm:"primaryKey;autoIncrement"`
81+
Ptype string `gorm:"size:512;uniqueIndex:unique_index"`
82+
V0 string `gorm:"size:512;uniqueIndex:unique_index"`
83+
V1 string `gorm:"size:512;uniqueIndex:unique_index"`
84+
V2 string `gorm:"size:512;uniqueIndex:unique_index"`
85+
V3 string `gorm:"size:512;uniqueIndex:unique_index"`
86+
V4 string `gorm:"size:512;uniqueIndex:unique_index"`
87+
V5 string `gorm:"size:512;uniqueIndex:unique_index"`
88+
}
89+
90+
db, _ := gorm.Open(...)
91+
92+
// Initialize a Gorm adapter and use it in a Casbin enforcer:
93+
// The adapter will use an existing gorm.DB instnace.
94+
a, _ := gormadapter.NewAdapterByDBWithCustomTable(db, &CasbinRule{})
95+
e, _ := casbin.NewEnforcer("examples/rbac_model.conf", a)
96+
97+
// Load the policy from DB.
98+
e.LoadPolicy()
99+
100+
// Check the permission.
101+
e.Enforce("alice", "data1", "read")
102+
103+
// Modify the policy.
104+
// e.AddPolicy(...)
105+
// e.RemovePolicy(...)
106+
107+
// Save the policy back to DB.
108+
e.SavePolicy()
109+
}
110+
```
111+
66112
## Getting Help
67113

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

adapter.go

+27-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package gormadapter
1616

1717
import (
18+
"context"
1819
"errors"
1920
"runtime"
2021
"strings"
@@ -33,6 +34,8 @@ const (
3334
defaultTableName = "casbin_rule"
3435
)
3536

37+
type customTableKey struct{}
38+
3639
type CasbinRule struct {
3740
ID uint `gorm:"primaryKey;autoIncrement"`
3841
Ptype string `gorm:"size:100;uniqueIndex:unique_index"`
@@ -164,7 +167,7 @@ func NewAdapterByDBUseTableName(db *gorm.DB, prefix string, tableName string) (*
164167
tableName: tableName,
165168
}
166169

167-
a.db = db.Scopes(a.casbinRuleTable()).Session(&gorm.Session{})
170+
a.db = db.Scopes(a.casbinRuleTable()).Session(&gorm.Session{Context: db.Statement.Context})
168171
err := a.createTable()
169172
if err != nil {
170173
return nil, err
@@ -189,6 +192,17 @@ func NewAdapterByDB(db *gorm.DB) (*Adapter, error) {
189192
return NewAdapterByDBUseTableName(db, "", defaultTableName)
190193
}
191194

195+
func NewAdapterByDBWithCustomTable(db *gorm.DB, t interface{}) (*Adapter, error) {
196+
ctx := db.Statement.Context
197+
if ctx == nil {
198+
ctx = context.Background()
199+
}
200+
201+
ctx = context.WithValue(ctx, customTableKey{}, t)
202+
203+
return NewAdapterByDBUseTableName(db.WithContext(ctx), "", defaultTableName)
204+
}
205+
192206
func openDBConnection(driverName, dataSourceName string) (*gorm.DB, error) {
193207
var err error
194208
var db *gorm.DB
@@ -280,11 +294,21 @@ func (a *Adapter) casbinRuleTable() func(db *gorm.DB) *gorm.DB {
280294
}
281295

282296
func (a *Adapter) createTable() error {
283-
return a.db.AutoMigrate(a.getTableInstance())
297+
t := a.db.Statement.Context.Value(customTableKey{})
298+
if t == nil {
299+
return a.db.AutoMigrate(a.getTableInstance())
300+
}
301+
302+
return a.db.AutoMigrate(t)
284303
}
285304

286305
func (a *Adapter) dropTable() error {
287-
return a.db.Migrator().DropTable(a.getTableInstance())
306+
t := a.db.Statement.Context.Value(customTableKey{})
307+
if t == nil {
308+
return a.db.Migrator().DropTable(a.getTableInstance())
309+
}
310+
311+
return a.db.Migrator().DropTable(t)
288312
}
289313

290314
func loadPolicyLine(line CasbinRule, model model.Model) {

adapter_test.go

+50
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package gormadapter
1616

1717
import (
18+
"github.com/jackc/pgconn"
1819
"log"
1920
"testing"
2021

@@ -107,6 +108,29 @@ func initAdapterWithGormInstance(t *testing.T, db *gorm.DB) *Adapter {
107108
return a
108109
}
109110

111+
func initAdapterWithGormInstanceAndCustomTable(t *testing.T, db *gorm.DB) *Adapter {
112+
type CasbinRule struct {
113+
ID uint `gorm:"primaryKey;autoIncrement"`
114+
Ptype string `gorm:"size:128;uniqueIndex:unique_index"`
115+
V0 string `gorm:"size:128;uniqueIndex:unique_index"`
116+
V1 string `gorm:"size:128;uniqueIndex:unique_index"`
117+
V2 string `gorm:"size:128;uniqueIndex:unique_index"`
118+
V3 string `gorm:"size:128;uniqueIndex:unique_index"`
119+
V4 string `gorm:"size:128;uniqueIndex:unique_index"`
120+
V5 string `gorm:"size:128;uniqueIndex:unique_index"`
121+
}
122+
123+
// Create an adapter
124+
a, _ := NewAdapterByDBWithCustomTable(db, &CasbinRule{})
125+
// Initialize some policy in DB.
126+
initPolicy(t, a)
127+
// Now the DB has policy, so we can provide a normal use case.
128+
// Note: you don't need to look at the above code
129+
// if you already have a working DB with policy inside.
130+
131+
return a
132+
}
133+
110134
func initAdapterWithGormInstanceByName(t *testing.T, db *gorm.DB, name string) *Adapter {
111135
//Create an Adapter
112136
a, _ := NewAdapterByDBUseTableName(db, "", name)
@@ -210,6 +234,32 @@ func testUpdatePolicy(t *testing.T, a *Adapter) {
210234
testGetPolicy(t, e, [][]string{{"alice", "data1", "write"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})
211235
}
212236

237+
func TestAdapterWithCustomTable(t *testing.T) {
238+
db, err := gorm.Open(postgres.Open("user=postgres host=127.0.0.1 port=5432 sslmode=disable"), &gorm.Config{})
239+
if err != nil {
240+
panic(err)
241+
}
242+
243+
if err = db.Exec("CREATE DATABASE casbin_custom_table").Error; err != nil {
244+
// 42P04 is duplicate_database
245+
if err.(*pgconn.PgError).Code != "42P04" {
246+
panic(err)
247+
}
248+
}
249+
250+
db, err = gorm.Open(postgres.Open("user=postgres host=127.0.0.1 port=5432 sslmode=disable dbname=casbin_custom_table"), &gorm.Config{})
251+
if err != nil {
252+
panic(err)
253+
}
254+
255+
a := initAdapterWithGormInstanceAndCustomTable(t, db)
256+
testAutoSave(t, a)
257+
testSaveLoad(t, a)
258+
259+
a = initAdapterWithGormInstanceAndCustomTable(t, db)
260+
testFilteredPolicy(t, a)
261+
}
262+
213263
func TestAdapters(t *testing.T) {
214264
a := initAdapter(t, "mysql", "root:@tcp(127.0.0.1:3306)/", "casbin", "casbin_rule")
215265
testAutoSave(t, a)

0 commit comments

Comments
 (0)