Skip to main content

Adapters

In Casbin, the policy storage is implemented as an adapter (aka middleware for Casbin). A Casbin user can use an adapter to load policy rules from a storage (aka LoadPolicy()), or save policy rules to it (aka SavePolicy()). To keep light-weight, we don't put adapter code in the main library.

Supported adapters​

A complete list of Casbin adapters is provided as below. Any 3rd-party contribution on a new adapter is welcomed, please inform us and we will put it in this list:)

AdapterTypeAuthorAutoSaveDescription
File Adapter (built-in)FileCasbin❌For .CSV (Comma-Separated Values) files
Filtered File Adapter (built-in)File@faceless-saint❌For .CSV (Comma-Separated Values) files with policy subset loading support
SQL AdapterSQL@Blank-Xuβœ…MySQL, PostgreSQL, SQL Server, SQLite3 are supported in master branch and Oracle is supported in oracle branch by database/sql
Xorm AdapterORMCasbinβœ…MySQL, PostgreSQL, TiDB, SQLite, SQL Server, Oracle are supported by Xorm
GORM AdapterORMCasbinβœ…MySQL, PostgreSQL, Sqlite3, SQL Server are supported by GORM
GORM Adapter ExORMCasbinβœ…MySQL, PostgreSQL, Sqlite3, SQL Server are supported by GORM
Ent AdapterORMCasbinβœ…MySQL, MariaDB, PostgreSQL, SQLite, Gremlin-based graph databases are supported by ent ORM
Beego ORM AdapterORMCasbinβœ…MySQL, PostgreSQL, Sqlite3 are supported by Beego ORM
SQLX AdapterORM@memweyβœ…MySQL, PostgreSQL, SQLite, Oracle are supported by SQLX
Sqlx AdapterORM@Blank-Xuβœ…MySQL, PostgreSQL, SQL Server, SQLite3 are supported in master branch and Oracle is supported in oracle branch by sqlx
GF ORM AdapterORM@vance-liuβœ…MySQL, SQLite, PostgreSQL, Oracle, SQL Server are supported by GoFrame ORM
GoFrame ORM AdapterORM@kotlin2018βœ…MySQL, SQLite, PostgreSQL, Oracle, SQL Server are supported by GoFrame ORM
gf-adapterORM@zcycβœ…MySQL, SQLite, PostgreSQL, Oracle, SQL Server are supported by GoFrame ORM
Gdb AdapterORM@jxo-meβœ…MySQL, SQLite, PostgreSQL, Oracle, SQL Server are supported by GoFrame ORM
GoFrame V2 AdapterORM@hailazβœ…MySQL, SQLite, PostgreSQL, Oracle, SQL Server are supported by GoFrame ORM
Filtered PostgreSQL AdapterSQLCasbinβœ…For PostgreSQL
Filtered pgx AdapterSQL@pckhoiβœ…PostgreSQL is supported by pgx
PostgreSQL AdapterSQL@cychiuaeβœ…For PostgreSQL
RQLite AdapterSQLEDOMO Systemsβœ…For RQLite
MongoDB AdapterNoSQLCasbinβœ…For MongoDB based on MongoDB Go Driver
RethinkDB AdapterNoSQL@adityapandey9βœ…For RethinkDB
Cassandra AdapterNoSQLCasbin❌For Apache Cassandra DB
DynamoDB AdapterNoSQLHOOQ❌For Amazon DynamoDB
DynacasbinNoSQLNewbMiaoβœ…For Amazon DynamoDB
ArangoDB AdapterNoSQL@adamwasilaβœ…For ArangoDB
Amazon S3 AdapterCloudSoluto❌For Minio and Amazon S3
Go CDK AdapterCloud@bartventerβœ…Adapter based on Go Cloud Dev Kit that supports: Amazon DynamoDB, Azure CosmosDB, GCP Firestore, MongoDB, In-Memory
Azure Cosmos DB AdapterCloud@spacycoderβœ…For Microsoft Azure Cosmos DB
GCP Firestore AdapterCloud@reedom❌For Google Cloud Platform Firestore
GCP Cloud Storage AdapterCloudqurami❌For Google Cloud Platform Cloud Storage
GCP Cloud Spanner AdapterCloud@flowerinthenightβœ…For Google Cloud Platform Cloud Spanner
Consul AdapterKV store@ankitm123❌For HashiCorp Consul
Redis Adapter (Redigo)KV storeCasbinβœ…For Redis
Redis Adapter (go-redis)KV store@mlsenβœ…For Redis
Etcd AdapterKV store@sebastianliu❌For etcd
BoltDB AdapterKV store@spezaβœ…For Bolt
Bolt AdapterKV store@wirepair❌For Bolt
BadgerDB AdapterKV store@initsβœ…For BadgerDB
Protobuf AdapterStreamCasbin❌For Google Protocol Buffers
JSON AdapterStringCasbin❌For JSON
String AdapterString@qiangmzsx❌For String
HTTP File AdapterHTTP@h4ckedneko❌For http.FileSystem
FileSystem AdapterFile@naucon❌For fs.FS and embed.FS
note
  1. If casbin.NewEnforcer() is called with an explicit or implicit adapter, the policy will be loaded automatically.
  2. You can call e.LoadPolicy() to reload the policy rules from the storage.
  3. If the adapter does not support the Auto-Save feature, The policy rules cannot be automatically saved back to the storage when you add or remove policies. You have to call SavePolicy() manually to save all policy rules.

Examples​

Here we provide several examples:

File adapter (built-in)​

Below shows how to initialize an enforcer from the built-in file adapter:

import "github.com/casbin/casbin"

e := casbin.NewEnforcer("examples/basic_model.conf", "examples/basic_policy.csv")

This is the same with:

import (
"github.com/casbin/casbin"
"github.com/casbin/casbin/file-adapter"
)

a := fileadapter.NewAdapter("examples/basic_policy.csv")
e := casbin.NewEnforcer("examples/basic_model.conf", a)

MySQL adapter​

Below shows how to initialize an enforcer from MySQL database. it connects to a MySQL DB on 127.0.0.1:3306 with root and blank password.

import (
"github.com/casbin/casbin"
"github.com/casbin/mysql-adapter"
)

a := mysqladapter.NewAdapter("mysql", "root:@tcp(127.0.0.1:3306)/")
e := casbin.NewEnforcer("examples/basic_model.conf", a)

Use your own storage adapter​

You can use your own adapter like below:

import (
"github.com/casbin/casbin"
"github.com/your-username/your-repo"
)

a := yourpackage.NewAdapter(params)
e := casbin.NewEnforcer("examples/basic_model.conf", a)

Migrate/Convert between different adapter​

If you want to convert adapter from A to B, you can do like this:

  1. Load policy from A to memory

    e, _ := NewEnforcer(m, A)

    or

    e.SetAdapter(A)
    e.LoadPolicy()
  2. convert your adapter from A to B

    e.SetAdapter(B)
  3. Save policy from memory to B

    e.SavePolicy()

Load/Save at run-time​

You may also want to reload the model, reload the policy or save the policy after initialization:

// Reload the model from the model CONF file.
e.LoadModel()

// Reload the policy from file/database.
e.LoadPolicy()

// Save the current policy (usually after changed with Casbin API) back to file/database.
e.SavePolicy()

AutoSave​

There is a feature called Auto-Save for adapters. When an adapter supports Auto-Save, it means it can support adding a single policy rule to the storage, or removing a single policy rule from the storage. This is unlike SavePolicy(), because the latter will delete all policy rules in the storage and save all policy rules from Casbin enforcer to the storage. So it may suffer performance issue when the number of policy rules is large.

When the adapter supports Auto-Save, you can switch this option via Enforcer.EnableAutoSave() function. The option is enabled by default (if the adapter supports it).

note
  1. The Auto-Save feature is optional. An adapter can choose to implement it or not.
  2. Auto-Save only works for a Casbin enforcer when the adapter the enforcer uses supports it.
  3. See the AutoSave column in the above adapter list to see if Auto-Save is supported by an adapter.

Here's an example about how to use Auto-Save:

import (
"github.com/casbin/casbin"
"github.com/casbin/xorm-adapter"
_ "github.com/go-sql-driver/mysql"
)

// By default, the AutoSave option is enabled for an enforcer.
a := xormadapter.NewAdapter("mysql", "mysql_username:mysql_password@tcp(127.0.0.1:3306)/")
e := casbin.NewEnforcer("examples/basic_model.conf", a)

// Disable the AutoSave option.
e.EnableAutoSave(false)

// Because AutoSave is disabled, the policy change only affects the policy in Casbin enforcer,
// it doesn't affect the policy in the storage.
e.AddPolicy(...)
e.RemovePolicy(...)

// Enable the AutoSave option.
e.EnableAutoSave(true)

// Because AutoSave is enabled, the policy change not only affects the policy in Casbin enforcer,
// but also affects the policy in the storage.
e.AddPolicy(...)
e.RemovePolicy(...)

For more examples, please see: https://github.com/casbin/xorm-adapter/blob/master/adapter_test.go

How to write an adapter​

All adapters should implement the Adapter interface by providing at least two mandatory methods:LoadPolicy(model model.Model) error and SavePolicy(model model.Model) error.

The other three functions are optional. They should be implemented if the adapter supports the Auto-Save feature.

MethodTypeDescription
LoadPolicy()mandatoryLoad all policy rules from the storage
SavePolicy()mandatorySave all policy rules to the storage
AddPolicy()optionalAdd a policy rule to the storage
RemovePolicy()optionalRemove a policy rule from the storage
RemoveFilteredPolicy()optionalRemove policy rules that match the filter from the storage
note

If an adapter doesn't support Auto-Save, it should provide an empty implementation for the three optional functions. Here's an example for Golang:

// AddPolicy adds a policy rule to the storage.
func (a *Adapter) AddPolicy(sec string, ptype string, rule []string) error {
return errors.New("not implemented")
}

// RemovePolicy removes a policy rule from the storage.
func (a *Adapter) RemovePolicy(sec string, ptype string, rule []string) error {
return errors.New("not implemented")
}

// RemoveFilteredPolicy removes policy rules that match the filter from the storage.
func (a *Adapter) RemoveFilteredPolicy(sec string, ptype string, fieldIndex int, fieldValues ...string) error {
return errors.New("not implemented")
}

Casbin enforcer will ignore the not implemented error when calling these three optional functions.

There're details about how to write an adapter.

  • Data Structure. Adapter should support reading at least six columns.

  • Database Name. The default database name should be casbin.

  • Table Name. The default table name should be casbin_rule.

  • Ptype Column. Name of this column should be ptype instead of p_type or Ptype.

  • Table definition should be (id int primary key, ptype varchar, v0 varchar, v1 varchar, v2 varchar, v3 varchar, v4 varchar, v5 varchar).

  • The unique key index should be built on columns ptype,v0,v1,v2,v3,v4,v5.

  • LoadFilteredPolicy requires a filter as parameter. The filter should be something like this.

    {
    "p":[ [ "alice" ], [ "bob" ] ],
    "g":[ [ "", "book_group" ], [ "", "pen_group" ] ],
    "g2":[ [ "alice" ] ]
    }

Who is responsible to create the DB?​

As a convention, the adapter should be able to automatically create a database named casbin if it doesn't exist and use it for policy storage. Please use the Xorm adapter as a reference implementation: https://github.com/casbin/xorm-adapter

Context Adapter​

ContextAdapter provides a context-aware interface for Casbin adapters.

Through context, you can implement features such as timeout control for the Adapter API

Example​

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)
}

How to write an context adapter​

ContextAdapter API only has an extra layer of context processing than ordinary Adapter API, and on the basis of implementing ordinary Adapter API, you can encapsulate your own processing logic for context

A simple reference to the gormadapter: context_adapter.go