Skip to content

Commit

Permalink
Merge pull request #1 from ali-shokoohi/feature/add-gin-handler
Browse files Browse the repository at this point in the history
Feature/add gin handler
  • Loading branch information
ali-shokoohi authored Sep 20, 2024
2 parents 9c5bdf3 + a858ce4 commit f55a86a
Show file tree
Hide file tree
Showing 9 changed files with 358 additions and 34 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ casbin-server

.idea/
*.iml

# Environment Variables
.env
13 changes: 13 additions & 0 deletions dto/enforce.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package dto

import (
pb "github.com/casbin/casbin-server/proto"
)

type EnforceRequest struct {
pb.EnforceRequest
}

type EnforceResponse struct {
pb.BoolReply
}
24 changes: 18 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,23 @@ go 1.19
require (
github.com/casbin/casbin/v2 v2.60.0
github.com/casbin/gorm-adapter/v3 v3.14.0
github.com/stretchr/testify v1.8.0
github.com/gin-gonic/gin v1.8.2
github.com/stretchr/testify v1.8.1
google.golang.org/grpc v1.42.0
google.golang.org/protobuf v1.27.1
google.golang.org/protobuf v1.28.1
)

require (
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/glebarez/go-sqlite v1.19.1 // indirect
github.com/glebarez/sqlite v1.5.0 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.11.1 // indirect
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/goccy/go-json v0.9.11 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/golang/protobuf v1.5.0 // indirect
Expand All @@ -30,16 +36,22 @@ require (
github.com/jackc/pgx/v4 v4.17.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/microsoft/go-mssqldb v0.17.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/ugorji/go/codec v1.2.7 // indirect
golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b // indirect
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/net v0.4.0 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/text v0.5.0 // indirect
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/driver/mysql v1.4.1 // indirect
gorm.io/driver/postgres v1.4.4 // indirect
Expand Down
57 changes: 49 additions & 8 deletions go.sum

Large diffs are not rendered by default.

92 changes: 92 additions & 0 deletions handler/gin/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package gin

import (
"context"
"log"
"net/http"

"github.com/casbin/casbin-server/dto"
"github.com/casbin/casbin-server/handler"
"github.com/casbin/casbin-server/proto"
server "github.com/casbin/casbin-server/server"
"github.com/gin-gonic/gin"
)

type GinContext struct {
Ctx *gin.Context
}

func (g *GinContext) Bind(v interface{}) error {
return g.Ctx.Bind(v)
}

func (g *GinContext) ShouldBind(v interface{}) error {
return g.Ctx.ShouldBind(v)
}

func (g *GinContext) JSON(statusCode int, v interface{}) error {
g.Ctx.JSON(statusCode, v)
return nil
}

func (g *GinContext) Param(key string) string {
return g.Ctx.Param(key)
}

func (g *GinContext) QueryParam(key string) string {
return g.Ctx.Query(key)
}

type httpHandler struct {
server *server.Server
}

func NewHttpHandler(
server *server.Server,
) handler.HttpHandler {
return &httpHandler{
server: server,
}
}

func (h *httpHandler) Enforce(c handler.Context) {
var response dto.EnforceResponse
var request dto.EnforceRequest
ctx := context.Background()
err := c.ShouldBind(&request)
if err != nil {
c.JSON(http.StatusBadRequest, response)
return
}
// Create New Enforcer if input handler == -1
if request.GetEnforcerHandler() == -1 {
e, err := h.server.NewEnforcer(ctx, &proto.NewEnforcerRequest{AdapterHandle: -1})
if err != nil {
log.Println("Error at calling NewEnforcer in Enforce handler:", err.Error())
c.JSON(http.StatusInternalServerError, response)
return
}
request.EnforcerHandler = e.GetHandler()
}
allowed, err := h.server.Enforce(
ctx,
&proto.EnforceRequest{
EnforcerHandler: request.EnforcerHandler,
Params: request.Params,
},
)
if err != nil {
log.Println("Error at calling Enforce in Enforce handler:", err.Error())
c.JSON(http.StatusInternalServerError, response)
return
}
response.BoolReply = *allowed

if response.GetRes() {
c.JSON(http.StatusOK, response)
return
} else {
c.JSON(http.StatusForbidden, response)
return
}
}
13 changes: 13 additions & 0 deletions handler/handler_interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package handler

type HttpHandler interface {
Enforce(c Context)
}

type Context interface {
Bind(interface{}) error
ShouldBind(interface{}) error
JSON(int, interface{}) error
Param(string) string
QueryParam(string) string
}
83 changes: 63 additions & 20 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,75 @@ import (
"fmt"
"log"
"net"
"sync"

ginHandler "github.com/casbin/casbin-server/handler/gin"
pb "github.com/casbin/casbin-server/proto"
"github.com/casbin/casbin-server/router"
ginRouter "github.com/casbin/casbin-server/router/gin"
"github.com/casbin/casbin-server/server"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)

func main() {
var port int
flag.IntVar(&port, "port", 50051, "listening port")
flag.Parse()

if port < 1 || port > 65535 {
panic(fmt.Sprintf("invalid port number: %d", port))
}

lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterCasbinServer(s, server.NewServer())
// Register reflection service on gRPC server.
reflection.Register(s)
log.Println("Listening on", port)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
var port int
flag.IntVar(&port, "port", 50051, "gRPC listening port")
flag.Parse()

if port < 1 || port > 65535 {
panic(fmt.Sprintf("invalid gRPC port number: %d", port))
}

lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterCasbinServer(s, server.NewServer())
// Register reflection service on gRPC server.
reflection.Register(s)
log.Println("gRPC listening on", port)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to gRPC serve: %v", err)
}
}()
wg.Add(1)
go func() {
defer wg.Done()
var port int
flag.IntVar(&port, "http-port", 8585, "http listening port")
flag.Parse()
if port < 1 || port > 65535 {
panic(fmt.Sprintf("invalid http port number: %d", port))
}
var r router.Router
r = ginRouter.New() // or echoRouter.New()
server := server.NewServer()
// Define handlers
h := ginHandler.NewHttpHandler(server)
api := r.Group("/api")
{
v1 := api.Group("/v1")
{
enforce := v1.Group("/enforce")
{
enforce.POST("", h.Enforce)
}
}
}

// Start the server
httpAddr := fmt.Sprintf(":%d", port)
log.Println("http listening on", httpAddr)
if err := r.Serve(httpAddr); err != nil {
log.Fatalf("failed to http serve: %v", err)
}

}()
wg.Wait()
}
88 changes: 88 additions & 0 deletions router/gin/router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package gin

import (
ginHandler "github.com/casbin/casbin-server/handler/gin"
"github.com/casbin/casbin-server/router"
"github.com/gin-gonic/gin"
)

type GinRouter struct {
engine *gin.Engine
}

func New() *GinRouter {
return &GinRouter{engine: gin.Default()}
}

type GinRouterGroup struct {
routerGroup *gin.RouterGroup
}

func NewGroup(routerGroup *gin.RouterGroup) *GinRouterGroup {
return &GinRouterGroup{routerGroup: routerGroup}
}

func (r *GinRouter) GET(path string, handler router.HandlerFunc) {
r.engine.GET(path, func(c *gin.Context) {
handler(&ginHandler.GinContext{Ctx: c}) // Convert gin.Context to your custom Context
})
}

func (r *GinRouter) POST(path string, handler router.HandlerFunc) {
r.engine.POST(path, func(c *gin.Context) {
handler(&ginHandler.GinContext{Ctx: c})
})
}
func (r *GinRouter) PUT(path string, handler router.HandlerFunc) {
r.engine.PUT(path, func(c *gin.Context) {
handler(&ginHandler.GinContext{Ctx: c})
})
}
func (r *GinRouter) DELETE(path string, handler router.HandlerFunc) {
r.engine.DELETE(path, func(c *gin.Context) {
handler(&ginHandler.GinContext{Ctx: c})
})
}
func (r *GinRouter) OPTIONS(path string, handler router.HandlerFunc) {
r.engine.OPTIONS(path, func(c *gin.Context) {
handler(&ginHandler.GinContext{Ctx: c})
})
}
func (r *GinRouter) Serve(addr string) error {
return r.engine.Run(addr)
}

func (r *GinRouter) Group(relativePath string, handlers ...router.HandlerFunc) router.RouterGroup {
return NewGroup(r.engine.Group(relativePath))
}

func (r *GinRouterGroup) GET(path string, handler router.HandlerFunc) {
r.routerGroup.GET(path, func(c *gin.Context) {
handler(&ginHandler.GinContext{Ctx: c})
})
}

func (r *GinRouterGroup) POST(path string, handler router.HandlerFunc) {
r.routerGroup.POST(path, func(c *gin.Context) {
handler(&ginHandler.GinContext{Ctx: c})
})
}
func (r *GinRouterGroup) PUT(path string, handler router.HandlerFunc) {
r.routerGroup.PUT(path, func(c *gin.Context) {
handler(&ginHandler.GinContext{Ctx: c})
})
}
func (r *GinRouterGroup) DELETE(path string, handler router.HandlerFunc) {
r.routerGroup.DELETE(path, func(c *gin.Context) {
handler(&ginHandler.GinContext{Ctx: c})
})
}
func (r *GinRouterGroup) OPTIONS(path string, handler router.HandlerFunc) {
r.routerGroup.OPTIONS(path, func(c *gin.Context) {
handler(&ginHandler.GinContext{Ctx: c})
})
}

func (r *GinRouterGroup) Group(relativePath string, handlers ...router.HandlerFunc) router.RouterGroup {
return NewGroup(r.routerGroup.Group(relativePath))
}
19 changes: 19 additions & 0 deletions router/router_interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package router

import "github.com/casbin/casbin-server/handler"

type RouterGroup interface {
GET(path string, handler HandlerFunc)
POST(path string, handler HandlerFunc)
PUT(path string, handler HandlerFunc)
DELETE(path string, handler HandlerFunc)
OPTIONS(path string, handler HandlerFunc)
Group(relativePath string, handlers ...HandlerFunc) RouterGroup
}

type Router interface {
RouterGroup
Serve(addr string) error
}

type HandlerFunc func(handler.Context)

0 comments on commit f55a86a

Please sign in to comment.