Skip to content

Latest commit

 

History

31 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ent Adapter

Lint Build Coverage Status Godoc Release Discord

Ent Adapter is the Ent adapter for Casbin. With this library, Casbin can load policy from Ent-supported databases or save policy to them.

Based on Ent Supported Drivers, the current supported databases are:

  • MySQL
  • PostgreSQL
  • SQLite
  • Gremlin

Installation

go get github.com/apache/casbin-ent-adapter

Simple MySQL Example

package main

import (
	"github.com/casbin/casbin/v3"
	entadapter "github.com/apache/casbin-ent-adapter"
	_ "github.com/go-sql-driver/mysql"
)

func main() {
	// Initialize an Ent adapter and use it in a Casbin enforcer:
	// The adapter will use the MySQL database named "casbin".
	// The database should be created manually before using the adapter.
	a, _ := entadapter.NewAdapter("mysql", "root:@tcp(127.0.0.1:3306)/casbin") // Your driver and data source.
	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()
}

Simple PostgreSQL Example

package main

import (
	"github.com/casbin/casbin/v3"
	entadapter "github.com/apache/casbin-ent-adapter"
	_ "github.com/lib/pq"
)

func main() {
	// Initialize an Ent adapter and use it in a Casbin enforcer:
	// The adapter will use the PostgreSQL database named "casbin".
	// The database should be created manually before using the adapter.
	a, _ := entadapter.NewAdapter("postgres", "user=postgres password=postgres host=127.0.0.1 port=5432 sslmode=disable dbname=casbin") // Your driver and data source.
	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()
}

Use NewAdapterWithClient

You can also create an adapter with an existing Ent client instance:

package main

import (
	"github.com/casbin/casbin/v3"
	entadapter "github.com/apache/casbin-ent-adapter"
	"github.com/apache/casbin-ent-adapter/ent"
)

func main() {
	// Create an Ent client
	client, _ := ent.Open("mysql", "root:@tcp(127.0.0.1:3306)/casbin")
	
	// Initialize an Ent adapter with the client
	a, _ := entadapter.NewAdapterWithClient(client)
	e, _ := casbin.NewEnforcer("examples/rbac_model.conf", a)
	
	// Load the policy from DB.
	e.LoadPolicy()
	
	// Check the permission.
	e.Enforce("alice", "data1", "read")
	
	// Save the policy back to DB.
	e.SavePolicy()
}

Database Configuration

The database used in the adapter should be created manually before calling NewAdapter. The adapter will automatically create the casbin_rule table if it doesn't exist.

Upgrading an existing database

A policy rule is now unique on (ptype, v0, v1, v2, v3, v4, v5), and the seven columns are varchar(100) so that the index fits within the 3072-byte key limit InnoDB enforces. Both are enforced by the automatic migration that runs inside NewAdapter and NewAdapterWithClient, so a database written by an earlier version needs a look before the first start on this version. A fresh database needs nothing.

Check for rules that no longer fit. The adapter runs this check itself and refuses to migrate while it returns anything, because a MySQL server running without strict mode would truncate the values rather than reject them:

SELECT * FROM casbin_rules
WHERE CHAR_LENGTH(ptype) > 100 OR CHAR_LENGTH(v0) > 100 OR CHAR_LENGTH(v1) > 100
   OR CHAR_LENGTH(v2) > 100 OR CHAR_LENGTH(v3) > 100 OR CHAR_LENGTH(v4) > 100
   OR CHAR_LENGTH(v5) > 100;

Check for rules stored more than once. Nothing enforced uniqueness before, so duplicates may have accumulated, and the index cannot be built while they exist:

SELECT ptype, v0, v1, v2, v3, v4, v5, COUNT(*) AS copies
FROM casbin_rules GROUP BY ptype, v0, v1, v2, v3, v4, v5 HAVING COUNT(*) > 1;

Duplicates are redundant by definition — casbin evaluates a rule the same way whether it is stored once or ten times — so keeping the lowest id of each group is safe:

DELETE c FROM casbin_rules c
JOIN (
  SELECT MIN(id) AS keep_id, ptype, v0, v1, v2, v3, v4, v5
  FROM casbin_rules GROUP BY ptype, v0, v1, v2, v3, v4, v5 HAVING COUNT(*) > 1
) d ON c.ptype = d.ptype AND c.v0 = d.v0 AND c.v1 = d.v1 AND c.v2 = d.v2
   AND c.v3 = d.v3 AND c.v4 = d.v4 AND c.v5 = d.v5
WHERE c.id > d.keep_id;

On PostgreSQL, use DELETE FROM casbin_rules WHERE id NOT IN (SELECT MIN(id) FROM casbin_rules GROUP BY ptype, v0, v1, v2, v3, v4, v5); instead.

Adding a rule that is already stored stays a successful no-op rather than becoming an error, so replicas whose in-memory model has fallen behind another writer keep working.

Getting Help

License

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

Releases

Packages

Used by

Contributors

Languages