Git Product home page Git Product logo

casbin-gorm-adapter's Introduction

Gorm Adapter

In v3.0.3, method NewAdapterByDB creates table named casbin_rules,
we fix it to casbin_rule after that.
If you used v3.0.3 and less, and you want to update it,
you might need to migrate data manually. Find out more at: casbin#78

Go Report Card Go Coverage Status Godoc Release Discord Sourcegraph

Gorm Adapter is the Gorm adapter for Casbin. With this library, Casbin can load policy from Gorm supported database or save policy to it.

Based on Officially Supported Databases, The current supported databases are:

  • MySQL
  • PostgreSQL
  • SQL Server
  • Sqlite3

gorm-adapter use github.com/glebarez/sqlite instead of gorm official sqlite driver gorm.io/driver/sqlite because the latter needs cgo support. But there is almost no difference between the two driver. If there is a difference in use, please submit an issue.

  • other 3rd-party supported DBs in Gorm website or other places.

Installation

go get github.com/casbin/gorm-adapter/v3

Simple Example

package main

import (
	"github.com/casbin/casbin/v2"
	gormadapter "github.com/casbin/gorm-adapter/v3"
	_ "github.com/go-sql-driver/mysql"
)

func main() {
	// Initialize a Gorm adapter and use it in a Casbin enforcer:
	// The adapter will use the MySQL database named "casbin".
	// If it doesn't exist, the adapter will create it automatically.
	// You can also use an already existing gorm instance with gormadapter.NewAdapterByDB(gormInstance)
	a, _ := gormadapter.NewAdapter("mysql", "mysql_username:mysql_password@tcp(127.0.0.1:3306)/") // Your driver and data source.
	e, _ := casbin.NewEnforcer("examples/rbac_model.conf", a)
	
	// Or you can use an existing DB "abc" like this:
	// The adapter will use the table named "casbin_rule".
	// If it doesn't exist, the adapter will create it automatically.
	// a := gormadapter.NewAdapter("mysql", "mysql_username:mysql_password@tcp(127.0.0.1:3306)/abc", true)

	// Load the policy from DB.
	e.LoadPolicy()
	
	// Check the permission.
	e.Enforce("alice", "data1", "read")
	
	// Modify the policy.
	// e.AddPolicy(...)
	// e.RemovePolicy(...)
	
	// Save the policy back to DB.
	e.SavePolicy()
}

Turn off AutoMigrate

New an adapter will use AutoMigrate by default for create table, if you want to turn it off, please use API TurnOffAutoMigrate(db *gorm.DB) *gorm.DB. See example:

db, err := gorm.Open(mysql.Open("root:@tcp(127.0.0.1:3306)/casbin"), &gorm.Config{})
TurnOffAutoMigrate(db)
// a,_ := NewAdapterByDB(...)
// a,_ := NewAdapterByDBUseTableName(...)
a,_ := NewAdapterByDBWithCustomTable(...)

Find out more details at gorm-adapter#162

Customize table columns example

You can change the gorm struct tags, but the table structure must stay the same.

package main

import (
	"github.com/casbin/casbin/v2"
	gormadapter "github.com/casbin/gorm-adapter/v3"
	"gorm.io/gorm"
)

func main() {
	// Increase the column size to 512.
	type CasbinRule struct {
		ID    uint   `gorm:"primaryKey;autoIncrement"`
		Ptype string `gorm:"size:512;uniqueIndex:unique_index"`
		V0    string `gorm:"size:512;uniqueIndex:unique_index"`
		V1    string `gorm:"size:512;uniqueIndex:unique_index"`
		V2    string `gorm:"size:512;uniqueIndex:unique_index"`
		V3    string `gorm:"size:512;uniqueIndex:unique_index"`
		V4    string `gorm:"size:512;uniqueIndex:unique_index"`
		V5    string `gorm:"size:512;uniqueIndex:unique_index"`
	}

	db, _ := gorm.Open(...)

	// Initialize a Gorm adapter and use it in a Casbin enforcer:
	// The adapter will use an existing gorm.DB instnace.
	a, _ := gormadapter.NewAdapterByDBWithCustomTable(db, &CasbinRule{}) 
	e, _ := casbin.NewEnforcer("examples/rbac_model.conf", a)
	
	// Load the policy from DB.
	e.LoadPolicy()
	
	// Check the permission.
	e.Enforce("alice", "data1", "read")
	
	// Modify the policy.
	// e.AddPolicy(...)
	// e.RemovePolicy(...)
	
	// Save the policy back to DB.
	e.SavePolicy()
}

Transaction

You can modify policies within a transaction.See example:

package main

func main() {
	a, err := NewAdapterByDB(db)
	e, _ := casbin.NewEnforcer("examples/rbac_model.conf", a)
	err = e.GetAdapter().(*Adapter).Transaction(e, func(e casbin.IEnforcer) error {
		_, err := e.AddPolicy("jack", "data1", "write")
		if err != nil {
			return err
		}
		_, err = e.AddPolicy("jack", "data2", "write")
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		// handle if transaction failed
		return
	}
}

ConditionsToGormQuery

ConditionsToGormQuery() is a function that converts multiple query conditions into a GORM query statement You can use the GetAllowedObjectConditions() API of Casbin to get conditions, and choose the way of combining conditions through combineType.

ConditionsToGormQuery() allows Casbin to be combined with SQL, and you can use it to implement many functions.

Example: GetAllowedRecordsForUser

DataBase example:

id title author publisher publish_data price category_id
1 book1 author1 publisher1 2023-04-09 16:23:42 10 1
2 book2 author1 publisher1 2023-04-09 16:23:44 20 2
3 book3 author2 publisher1 2023-04-09 16:23:44 30 1
4 book4 author2 publisher2 2023-04-09 16:23:45 10 3
5 book5 author3 publisher2 2023-04-09 16:23:45 50 1
6 book6 author3 publisher2 2023-04-09 16:23:46 60 2
type Book struct {
    ID          int
    Title       string
    Author      string
    Publisher   string
    PublishDate time.Time
    Price       float64
    CategoryID  int
}

func TestGetAllowedRecordsForUser(t *testing.T) {
	e, _ := casbin.NewEnforcer("examples/object_conditions_model.conf", "examples/object_conditions_policy.csv")

	conditions, err := e.GetAllowedObjectConditions("alice", "read", "r.obj.")
	if err != nil {
		panic(err)
	}
	fmt.Println(conditions)

	dsn := "root:root@tcp(127.0.0.1:3307)/test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic(err)
	}

	fmt.Println("CombineTypeOr")
	rows, err := ConditionsToGormQuery(db, conditions, CombineTypeOr).Model(&Book{}).Rows()
	defer rows.Close()
	var b Book
	for rows.Next() {
		err := db.ScanRows(rows, &b)
		if err != nil {
			panic(err)
		}
		log.Println(b)
	}

	fmt.Println("CombineTypeAnd")
	rows, err = ConditionsToGormQuery(db, conditions, CombineTypeAnd).Model(&Book{}).Rows()
	defer rows.Close()
	for rows.Next() {
		err := db.ScanRows(rows, &b)
		if err != nil {
			panic(err)
		}
		log.Println(b)
	}
}

Context Adapter

gormadapter supports adapter with context, the following is a timeout control implemented using context

ca, _ := NewContextAdapter("mysql", "root:@tcp(127.0.0.1:3306)/", "casbin")
// Limited time 300s
ctx, cancel := context.WithTimeout(context.Background(), 300*time.Microsecond)
defer cancel()
err := ca.AddPolicyCtx(ctx, "p", "p", []string{"alice", "data1", "read"})
if err != nil {
    panic(err)
}

Getting Help

License

This project is under Apache 2.0 License. See the LICENSE file for the full license text.

casbin-gorm-adapter's People

Contributors

00lt00 avatar abingcbc avatar dallen42 avatar despire avatar dirablue avatar dsuket avatar hanshengzhao avatar helloshaohua avatar hiteshsethi avatar hsluoyz avatar huangkuan123 avatar jalinwang avatar jleeh avatar kilosonc avatar l1ghtman2k avatar maocaicai avatar miaolz123 avatar nodece avatar nonchan7720 avatar pokisemaine avatar selflocking avatar snyh avatar stijndehaes avatar tangyang9464 avatar uran0sh avatar vanelord67 avatar warnerwu avatar weloe avatar wuzhican avatar xiao-niu-ren avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.