Skip to content

prongbang/fiber-casbinrest

Repository files navigation

Casbin RESTful Adapter on Fiber Web Framework

Casbin RESTful adapter for Casbin https://github.com/casbin/casbin

Build Status Codecov Go Report Card

"Buy Me A Coffee"

Install

go get github.com/prongbang/fiber-casbinrest

Config

  • model.conf
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && (keyMatch(r.obj, p.obj) || keyMatch2(r.obj, p.obj)) && (r.act == p.act || regexMatch(r.act, p.act))
  • support policy
p, admin, /user/*, (GET)|(POST)
p, anonymous, /login, (GET)
p, admin, /admin/user/:id, (GET)|(POST)

JWT

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJyb2xlcyI6WyJBRE1JTiJdfQ.oW8uC8uyL4nZSjcDGRkW3ZHoEoHShPD7ft0cppgvQe4
  • payload
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  "roles": [
    "ADMIN"
  ]
}

Usage with File and JWT

import (
	"github.com/casbin/casbin/v2"
	"github.com/gofiber/fiber/v2"
	fibercasbinrest "github.com/prongbang/fiber-casbinrest"
	"log"
)

func main() {
    e, _ := casbin.NewEnforcer("example/auth_model.conf", "example/policy.csv")
    
    app := fiber.New()
    app.Use(fibercasbinrest.NewDefault(e, "secret"))
    
    app.Post("/admin", func(c *fiber.Ctx) error {
        return c.SendString("Hello, World 👋!")
    })
    
    app.Get("/admin/user/:id", func(c *fiber.Ctx) error {
        return c.SendString("Hello, User 👋!")
    })
    
    app.Get("/manage/:id", func(c *fiber.Ctx) error {
        return c.SendString("Hello, Manage 👋!")
    })
    
    app.Get("/login", func(c *fiber.Ctx) error {
        return c.SendString("Hello, login 👋!")
    })
    
    log.Fatal(app.Listen(":3000"))
}

Usage with Custom adapter and JWT

import (
	"github.com/casbin/casbin/v2"
	"github.com/gofiber/fiber/v2"
	fibercasbinrest "github.com/prongbang/fiber-casbinrest"
	"log"
)

type redisAdapter struct {
}

func NewRedisAdapter() fibercasbinrest.Adapter {
	return &redisAdapter{}
}

const mockAdminToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

func (r *redisAdapter) GetRoleByToken(reqToken string) ([]string, error) {
    // Validate example not use on production
	role := "anonymous"
	if reqToken == mockAdminToken {
		role = "admin"
	} else if reqToken == "TOKEN_DBA" {
		role = "dba"
	}
	return []string{role}, nil
}

func main() {
    adapter := NewRedisAdapter()
    e, _ := casbin.NewEnforcer("example/auth_model.conf", "example/policy.csv")
    
    app := fiber.New()
    app.Use(fibercasbinrest.New(e, adapter))
    
    app.Post("/admin", func(c *fiber.Ctx) error {
        return c.SendString("Hello, World 👋!")
    })
    
    app.Get("/admin/user/:id", func(c *fiber.Ctx) error {
        return c.SendString("Hello, User 👋!")
    })
    
    app.Get("/manage/:id", func(c *fiber.Ctx) error {
        return c.SendString("Hello, Manage 👋!")
    })
    
    app.Get("/login", func(c *fiber.Ctx) error {
        return c.SendString("Hello, login 👋!")
    })
    
    log.Fatal(app.Listen(":3000"))
}

Usage with MongoDB

import (
	"github.com/casbin/casbin/v2"
	mongodbadapter "github.com/casbin/mongodb-adapter/v3"
	"github.com/gofiber/fiber/v2"
	fibercasbinrest "github.com/prongbang/fiber-casbinrest"
	"log"
)

func main() {
    a, _ := mongodbadapter.NewAdapter("127.0.0.1:27017")
    e, _ := casbin.NewEnforcer("model.conf", a)
    
    // Modify the policy.
    _, _ = e.AddPolicy("anonymous", "/login", "GET")
    _, _ = e.AddPolicy("admin", "/admin", "(GET)|(POST)")
    _, _ = e.AddPolicy("admin", "/admin/user/:id", "GET")
    _, _ = e.AddPolicy("admin", "/manage/*", "GET")
    
    // Save the policy back to DB.
    _ = e.SavePolicy()
    
    // Load the policy from DB.
    _ = e.LoadPolicy()
    
    app := fiber.New()
    app.Use(fibercasbinrest.NewDefault(e, "secret"))
    
    app.Post("/admin", func(c *fiber.Ctx) error {
        return c.SendString("Hello, World 👋!")
    })
    
    app.Get("/admin/user/:id", func(c *fiber.Ctx) error {
        return c.SendString("Hello, User 👋!")
    })
    
    app.Get("/manage/:id", func(c *fiber.Ctx) error {
        return c.SendString("Hello, Manage 👋!")
    })
    
    app.Get("/login", func(c *fiber.Ctx) error {
        return c.SendString("Hello, login 👋!")
    })
    
    log.Fatal(app.Listen(":3000"))
}

Functions in matchers

Editor