Skip to content

Commit 16afb59

Browse files
committed
Echo V5 support
1 parent 6c28e2b commit 16afb59

File tree

20 files changed

+250
-943
lines changed

20 files changed

+250
-943
lines changed

.github/workflows/echo-contrib.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
# Echo CORE tests with last four major releases (unless there are pressing vulnerabilities)
2626
# As we depend on MANY DIFFERENT libraries which of SOME support last 2 Go releases we could have situations when
2727
# we derive from last four major releases promise.
28-
go: ["1.24", "1.25"]
28+
go: ["1.25"]
2929
name: ${{ matrix.os }} @ Go ${{ matrix.go }}
3030
runs-on: ${{ matrix.os }}
3131
steps:

casbin/casbin.go

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Simple example:
99
1010
import (
1111
"github.com/casbin/casbin/v2"
12-
"github.com/labstack/echo/v4"
12+
"github.com/labstack/echo/v5"
1313
casbin_mw "github.com/labstack/echo-contrib/casbin"
1414
)
1515
@@ -28,7 +28,7 @@ Advanced example:
2828
2929
import (
3030
"github.com/casbin/casbin/v2"
31-
"github.com/labstack/echo/v4"
31+
"github.com/labstack/echo/v5"
3232
casbin_mw "github.com/labstack/echo-contrib/casbin"
3333
)
3434
@@ -49,10 +49,11 @@ package casbin
4949

5050
import (
5151
"errors"
52-
"github.com/casbin/casbin/v2"
53-
"github.com/labstack/echo/v4"
54-
"github.com/labstack/echo/v4/middleware"
5552
"net/http"
53+
54+
"github.com/casbin/casbin/v2"
55+
"github.com/labstack/echo/v5"
56+
"github.com/labstack/echo/v5/middleware"
5657
)
5758

5859
type (
@@ -67,28 +68,26 @@ type (
6768

6869
// EnforceHandler is custom callback to handle enforcing.
6970
// One of Enforcer or EnforceHandler fields is required.
70-
EnforceHandler func(c echo.Context, user string) (bool, error)
71+
EnforceHandler func(c *echo.Context, user string) (bool, error)
7172

7273
// Method to get the username - defaults to using basic auth
73-
UserGetter func(c echo.Context) (string, error)
74+
UserGetter func(c *echo.Context) (string, error)
7475

7576
// Method to handle errors
76-
ErrorHandler func(c echo.Context, internal error, proposedStatus int) error
77+
ErrorHandler func(c *echo.Context, internal error, proposedStatus int) error
7778
}
7879
)
7980

8081
var (
8182
// DefaultConfig is the default CasbinAuth middleware config.
8283
DefaultConfig = Config{
8384
Skipper: middleware.DefaultSkipper,
84-
UserGetter: func(c echo.Context) (string, error) {
85+
UserGetter: func(c *echo.Context) (string, error) {
8586
username, _, _ := c.Request().BasicAuth()
8687
return username, nil
8788
},
88-
ErrorHandler: func(c echo.Context, internal error, proposedStatus int) error {
89-
err := echo.NewHTTPError(proposedStatus, internal.Error())
90-
err.Internal = internal
91-
return err
89+
ErrorHandler: func(c *echo.Context, internal error, proposedStatus int) error {
90+
return echo.NewHTTPError(proposedStatus, internal.Error()).Wrap(internal)
9291
},
9392
}
9493
)
@@ -119,13 +118,13 @@ func MiddlewareWithConfig(config Config) echo.MiddlewareFunc {
119118
config.ErrorHandler = DefaultConfig.ErrorHandler
120119
}
121120
if config.EnforceHandler == nil {
122-
config.EnforceHandler = func(c echo.Context, user string) (bool, error) {
121+
config.EnforceHandler = func(c *echo.Context, user string) (bool, error) {
123122
return config.Enforcer.Enforce(user, c.Request().URL.Path, c.Request().Method)
124123
}
125124
}
126125

127126
return func(next echo.HandlerFunc) echo.HandlerFunc {
128-
return func(c echo.Context) error {
127+
return func(c *echo.Context) error {
129128
if config.Skipper(c) {
130129
return next(c)
131130
}

casbin/casbin_test.go

Lines changed: 59 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@ package casbin
55

66
import (
77
"errors"
8-
"github.com/stretchr/testify/assert"
98
"net/http"
109
"net/http/httptest"
1110
"strings"
1211
"testing"
1312

13+
"github.com/stretchr/testify/assert"
14+
1415
"github.com/casbin/casbin/v2"
15-
"github.com/labstack/echo/v4"
16-
"github.com/labstack/echo/v4/middleware"
16+
"github.com/labstack/echo/v5"
17+
"github.com/labstack/echo/v5/middleware"
1718
)
1819

1920
func testRequest(t *testing.T, h echo.HandlerFunc, user string, path string, method string, code int) {
@@ -33,107 +34,111 @@ func testRequest(t *testing.T, h echo.HandlerFunc, user string, path string, met
3334
}
3435
}
3536
} else {
36-
if c.Response().Status != code {
37-
t.Errorf("%s, %s, %s: %d, supposed to be %d", user, path, method, c.Response().Status, code)
37+
status := 0
38+
if eResp, uErr := echo.UnwrapResponse(c.Response()); uErr == nil {
39+
status = eResp.Status
40+
}
41+
if status != code {
42+
t.Errorf("%s, %s, %s: %d, supposed to be %d", user, path, method, status, code)
3843
}
3944
}
4045
}
4146

4247
func TestAuth(t *testing.T) {
4348
ce, _ := casbin.NewEnforcer("auth_model.conf", "auth_policy.csv")
44-
h := Middleware(ce)(func(c echo.Context) error {
49+
h := Middleware(ce)(func(c *echo.Context) error {
4550
return c.String(http.StatusOK, "test")
4651
})
4752

48-
testRequest(t, h, "alice", "/dataset1/resource1", echo.GET, http.StatusOK)
49-
testRequest(t, h, "alice", "/dataset1/resource1", echo.POST, http.StatusOK)
50-
testRequest(t, h, "alice", "/dataset1/resource2", echo.GET, http.StatusOK)
51-
testRequest(t, h, "alice", "/dataset1/resource2", echo.POST, http.StatusForbidden)
53+
testRequest(t, h, "alice", "/dataset1/resource1", http.MethodGet, http.StatusOK)
54+
testRequest(t, h, "alice", "/dataset1/resource1", http.MethodPost, http.StatusOK)
55+
testRequest(t, h, "alice", "/dataset1/resource2", http.MethodGet, http.StatusOK)
56+
testRequest(t, h, "alice", "/dataset1/resource2", http.MethodPost, http.StatusForbidden)
5257
}
5358

5459
func TestPathWildcard(t *testing.T) {
5560
ce, _ := casbin.NewEnforcer("auth_model.conf", "auth_policy.csv")
56-
h := Middleware(ce)(func(c echo.Context) error {
61+
h := Middleware(ce)(func(c *echo.Context) error {
5762
return c.String(http.StatusOK, "test")
5863
})
5964

60-
testRequest(t, h, "bob", "/dataset2/resource1", echo.GET, http.StatusOK)
61-
testRequest(t, h, "bob", "/dataset2/resource1", echo.POST, http.StatusOK)
62-
testRequest(t, h, "bob", "/dataset2/resource1", echo.DELETE, http.StatusOK)
63-
testRequest(t, h, "bob", "/dataset2/resource2", echo.GET, http.StatusOK)
64-
testRequest(t, h, "bob", "/dataset2/resource2", echo.POST, http.StatusForbidden)
65-
testRequest(t, h, "bob", "/dataset2/resource2", echo.DELETE, http.StatusForbidden)
66-
67-
testRequest(t, h, "bob", "/dataset2/folder1/item1", echo.GET, http.StatusForbidden)
68-
testRequest(t, h, "bob", "/dataset2/folder1/item1", echo.POST, http.StatusOK)
69-
testRequest(t, h, "bob", "/dataset2/folder1/item1", echo.DELETE, http.StatusForbidden)
70-
testRequest(t, h, "bob", "/dataset2/folder1/item2", echo.GET, http.StatusForbidden)
71-
testRequest(t, h, "bob", "/dataset2/folder1/item2", echo.POST, http.StatusOK)
72-
testRequest(t, h, "bob", "/dataset2/folder1/item2", echo.DELETE, http.StatusForbidden)
65+
testRequest(t, h, "bob", "/dataset2/resource1", http.MethodGet, http.StatusOK)
66+
testRequest(t, h, "bob", "/dataset2/resource1", http.MethodPost, http.StatusOK)
67+
testRequest(t, h, "bob", "/dataset2/resource1", http.MethodDelete, http.StatusOK)
68+
testRequest(t, h, "bob", "/dataset2/resource2", http.MethodGet, http.StatusOK)
69+
testRequest(t, h, "bob", "/dataset2/resource2", http.MethodPost, http.StatusForbidden)
70+
testRequest(t, h, "bob", "/dataset2/resource2", http.MethodDelete, http.StatusForbidden)
71+
72+
testRequest(t, h, "bob", "/dataset2/folder1/item1", http.MethodGet, http.StatusForbidden)
73+
testRequest(t, h, "bob", "/dataset2/folder1/item1", http.MethodPost, http.StatusOK)
74+
testRequest(t, h, "bob", "/dataset2/folder1/item1", http.MethodDelete, http.StatusForbidden)
75+
testRequest(t, h, "bob", "/dataset2/folder1/item2", http.MethodGet, http.StatusForbidden)
76+
testRequest(t, h, "bob", "/dataset2/folder1/item2", http.MethodPost, http.StatusOK)
77+
testRequest(t, h, "bob", "/dataset2/folder1/item2", http.MethodDelete, http.StatusForbidden)
7378
}
7479

7580
func TestRBAC(t *testing.T) {
7681
ce, _ := casbin.NewEnforcer("auth_model.conf", "auth_policy.csv")
77-
h := Middleware(ce)(func(c echo.Context) error {
82+
h := Middleware(ce)(func(c *echo.Context) error {
7883
return c.String(http.StatusOK, "test")
7984
})
8085

8186
// cathy can access all /dataset1/* resources via all methods because it has the dataset1_admin role.
82-
testRequest(t, h, "cathy", "/dataset1/item", echo.GET, http.StatusOK)
83-
testRequest(t, h, "cathy", "/dataset1/item", echo.POST, http.StatusOK)
84-
testRequest(t, h, "cathy", "/dataset1/item", echo.DELETE, http.StatusOK)
85-
testRequest(t, h, "cathy", "/dataset2/item", echo.GET, http.StatusForbidden)
86-
testRequest(t, h, "cathy", "/dataset2/item", echo.POST, http.StatusForbidden)
87-
testRequest(t, h, "cathy", "/dataset2/item", echo.DELETE, http.StatusForbidden)
87+
testRequest(t, h, "cathy", "/dataset1/item", http.MethodGet, http.StatusOK)
88+
testRequest(t, h, "cathy", "/dataset1/item", http.MethodPost, http.StatusOK)
89+
testRequest(t, h, "cathy", "/dataset1/item", http.MethodDelete, http.StatusOK)
90+
testRequest(t, h, "cathy", "/dataset2/item", http.MethodGet, http.StatusForbidden)
91+
testRequest(t, h, "cathy", "/dataset2/item", http.MethodPost, http.StatusForbidden)
92+
testRequest(t, h, "cathy", "/dataset2/item", http.MethodDelete, http.StatusForbidden)
8893

8994
// delete all roles on user cathy, so cathy cannot access any resources now.
9095
ce.DeleteRolesForUser("cathy")
9196

92-
testRequest(t, h, "cathy", "/dataset1/item", echo.GET, http.StatusForbidden)
93-
testRequest(t, h, "cathy", "/dataset1/item", echo.POST, http.StatusForbidden)
94-
testRequest(t, h, "cathy", "/dataset1/item", echo.DELETE, http.StatusForbidden)
95-
testRequest(t, h, "cathy", "/dataset2/item", echo.GET, http.StatusForbidden)
96-
testRequest(t, h, "cathy", "/dataset2/item", echo.POST, http.StatusForbidden)
97-
testRequest(t, h, "cathy", "/dataset2/item", echo.DELETE, http.StatusForbidden)
97+
testRequest(t, h, "cathy", "/dataset1/item", http.MethodGet, http.StatusForbidden)
98+
testRequest(t, h, "cathy", "/dataset1/item", http.MethodPost, http.StatusForbidden)
99+
testRequest(t, h, "cathy", "/dataset1/item", http.MethodDelete, http.StatusForbidden)
100+
testRequest(t, h, "cathy", "/dataset2/item", http.MethodGet, http.StatusForbidden)
101+
testRequest(t, h, "cathy", "/dataset2/item", http.MethodPost, http.StatusForbidden)
102+
testRequest(t, h, "cathy", "/dataset2/item", http.MethodDelete, http.StatusForbidden)
98103
}
99104

100105
func TestEnforceError(t *testing.T) {
101106
ce, _ := casbin.NewEnforcer("broken_auth_model.conf", "auth_policy.csv")
102-
h := Middleware(ce)(func(c echo.Context) error {
107+
h := Middleware(ce)(func(c *echo.Context) error {
103108
return c.String(http.StatusOK, "test")
104109
})
105110

106-
testRequest(t, h, "cathy", "/dataset1/item", echo.GET, http.StatusInternalServerError)
111+
testRequest(t, h, "cathy", "/dataset1/item", http.MethodGet, http.StatusInternalServerError)
107112
}
108113

109114
func TestCustomUserGetter(t *testing.T) {
110115
ce, _ := casbin.NewEnforcer("auth_model.conf", "auth_policy.csv")
111116
cnf := Config{
112117
Skipper: middleware.DefaultSkipper,
113118
Enforcer: ce,
114-
UserGetter: func(c echo.Context) (string, error) {
119+
UserGetter: func(c *echo.Context) (string, error) {
115120
return "not_cathy_at_all", nil
116121
},
117122
}
118-
h := MiddlewareWithConfig(cnf)(func(c echo.Context) error {
123+
h := MiddlewareWithConfig(cnf)(func(c *echo.Context) error {
119124
return c.String(http.StatusOK, "test")
120125
})
121-
testRequest(t, h, "cathy", "/dataset1/item", echo.GET, http.StatusForbidden)
126+
testRequest(t, h, "cathy", "/dataset1/item", http.MethodGet, http.StatusForbidden)
122127
}
123128

124129
func TestUserGetterError(t *testing.T) {
125130
ce, _ := casbin.NewEnforcer("auth_model.conf", "auth_policy.csv")
126131
cnf := Config{
127132
Skipper: middleware.DefaultSkipper,
128133
Enforcer: ce,
129-
UserGetter: func(c echo.Context) (string, error) {
134+
UserGetter: func(c *echo.Context) (string, error) {
130135
return "", errors.New("no idea who you are")
131136
},
132137
}
133-
h := MiddlewareWithConfig(cnf)(func(c echo.Context) error {
138+
h := MiddlewareWithConfig(cnf)(func(c *echo.Context) error {
134139
return c.String(http.StatusOK, "test")
135140
})
136-
testRequest(t, h, "cathy", "/dataset1/item", echo.GET, http.StatusForbidden)
141+
testRequest(t, h, "cathy", "/dataset1/item", http.MethodGet, http.StatusForbidden)
137142
}
138143

139144
func TestCustomEnforceHandler(t *testing.T) {
@@ -144,33 +149,33 @@ func TestCustomEnforceHandler(t *testing.T) {
144149
assert.NoError(t, err)
145150

146151
cnf := Config{
147-
EnforceHandler: func(c echo.Context, user string) (bool, error) {
152+
EnforceHandler: func(c *echo.Context, user string) (bool, error) {
148153
method := c.Request().Method
149154
if strings.HasPrefix(c.Request().URL.Path, "/user/bob") {
150155
method += "_SELF"
151156
}
152157
return ce.Enforce(user, c.Request().URL.Path, method)
153158
},
154159
}
155-
h := MiddlewareWithConfig(cnf)(func(c echo.Context) error {
160+
h := MiddlewareWithConfig(cnf)(func(c *echo.Context) error {
156161
return c.String(http.StatusOK, "test")
157162
})
158-
testRequest(t, h, "bob", "/dataset2/resource1", echo.GET, http.StatusOK)
159-
testRequest(t, h, "bob", "/user/alice", echo.PATCH, http.StatusForbidden)
160-
testRequest(t, h, "bob", "/user/bob", echo.PATCH, http.StatusOK)
163+
testRequest(t, h, "bob", "/dataset2/resource1", http.MethodGet, http.StatusOK)
164+
testRequest(t, h, "bob", "/user/alice", http.MethodPatch, http.StatusForbidden)
165+
testRequest(t, h, "bob", "/user/bob", http.MethodPatch, http.StatusOK)
161166
}
162167

163168
func TestCustomSkipper(t *testing.T) {
164169
ce, _ := casbin.NewEnforcer("auth_model.conf", "auth_policy.csv")
165170
cnf := Config{
166-
Skipper: func(c echo.Context) bool {
171+
Skipper: func(c *echo.Context) bool {
167172
return c.Request().URL.Path == "/dataset1/resource1"
168173
},
169174
Enforcer: ce,
170175
}
171-
h := MiddlewareWithConfig(cnf)(func(c echo.Context) error {
176+
h := MiddlewareWithConfig(cnf)(func(c *echo.Context) error {
172177
return c.String(http.StatusOK, "test")
173178
})
174-
testRequest(t, h, "alice", "/dataset1/resource1", echo.GET, http.StatusOK)
175-
testRequest(t, h, "alice", "/dataset1/resource2", echo.POST, http.StatusForbidden)
179+
testRequest(t, h, "alice", "/dataset1/resource1", http.MethodGet, http.StatusOK)
180+
testRequest(t, h, "alice", "/dataset1/resource2", http.MethodPost, http.StatusForbidden)
176181
}

0 commit comments

Comments
 (0)