Skip to content

Commit ba8b34e

Browse files
committed
tenancy updates in api
1 parent 56d2e79 commit ba8b34e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+510
-360
lines changed

api/errors/handler.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,20 @@ type ErrDetail struct {
2222
Message string `json:"message"`
2323
}
2424

25+
type ErrorWithCode interface {
26+
error
27+
Status() string
28+
StatusCode() int
29+
}
30+
2531
func CustomHTTPErrorHandler(err error, c echo.Context) {
2632
log.Debug("return error message to client", zap.Error(err))
2733

34+
if errWithCode, ok := err.(ErrorWithCode); ok {
35+
c.JSON(errWithCode.StatusCode(), &ErrorRes{Status: errWithCode.Status(), Message: errWithCode.Error()})
36+
return
37+
}
38+
2839
statusError, ok := err.(*errors.StatusError)
2940
if ok && statusError.Status().Code > 0 {
3041
c.JSON(int(statusError.ErrStatus.Code), &ErrorRes{Status: statusError.ErrStatus.Status, Message: statusError.ErrStatus.Message})

api/go.mod

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ go 1.15
55
require (
66
github.com/casbin/casbin/v2 v2.11.2
77
github.com/coreos/go-oidc v2.2.1+incompatible
8-
github.com/davecgh/go-spew v1.1.1
98
github.com/dgrijalva/jwt-go v3.2.0+incompatible
109
github.com/go-openapi/runtime v0.19.20 // indirect
1110
github.com/go-openapi/spec v0.19.9 // indirect
@@ -20,7 +19,6 @@ require (
2019
github.com/kalmhq/kalm/controller v0.0.0-20200722131031-2336d7eaf4c9
2120
github.com/labstack/echo/v4 v4.1.17
2221
github.com/mattn/go-sqlite3 v2.0.3+incompatible
23-
github.com/opencontainers/image-spec v1.0.1 // indirect
2422
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
2523
github.com/stretchr/testify v1.6.1
2624
github.com/urfave/cli/v2 v2.2.0

api/go.sum

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGi
538538
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
539539
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
540540
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
541+
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
541542
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
542543
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
543544
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
@@ -548,9 +549,6 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
548549
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
549550
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
550551
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
551-
github.com/labstack/echo v1.4.4 h1:1bEiBNeGSUKxcPDGfZ/7IgdhJJZx8wV/pICJh4W2NJI=
552-
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
553-
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
554552
github.com/labstack/echo/v4 v4.1.17 h1:PQIBaRplyRy3OjwILGkPg89JRtH2x5bssi59G2EL3fo=
555553
github.com/labstack/echo/v4 v4.1.17/go.mod h1:Tn2yRQL/UclUalpb5rPdXDevbkJ+lp/2svdyFBg6CHQ=
556554
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
@@ -913,6 +911,7 @@ golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCc
913911
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
914912
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
915913
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
914+
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
916915
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
917916
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
918917
golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1066,6 +1065,7 @@ golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtn
10661065
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
10671066
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f h1:kDxGY2VmgABOe55qheT/TFqUMtcTHnomIPS1iv3G4Ms=
10681067
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
1068+
golang.org/x/tools v0.0.0-20200616133436-c1934b75d054 h1:HHeAlu5H9b71C+Fx0K+1dGgVFN1DM1/wz4aoGOA5qS8=
10691069
golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
10701070
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
10711071
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

api/handler/access_token.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,7 @@ func (h *ApiHandler) handleCreateAccessToken(c echo.Context) error {
4848
accessToken.Name = v1alpha1.GetAccessTokenNameFromToken(accessToken.Token)
4949
accessToken.Tenant = currentUser.Tenant
5050

51-
if !h.clientManager.CanEdit(currentUser, currentUser.Tenant+"/*", "accessTokens/*") {
52-
return resources.InsufficientPermissionsError
53-
}
51+
h.MustCanEdit(currentUser, currentUser.Tenant+"/*", "accessTokens/*")
5452

5553
if !h.clientManager.PermissionsGreaterThanOrEqualToAccessToken(currentUser, accessToken) {
5654
return resources.InsufficientPermissionsError
@@ -90,9 +88,7 @@ func (h *ApiHandler) handleDeleteAccessToken(c echo.Context) error {
9088

9189
token := tokens[0]
9290

93-
if !h.clientManager.CanEdit(currentUser, currentUser.Tenant+"/*", "accessTokens/"+token.Name) {
94-
return resources.InsufficientPermissionsError
95-
}
91+
h.MustCanEdit(currentUser, currentUser.Tenant+"/*", "accessTokens/*")
9692

9793
if !h.clientManager.PermissionsGreaterThanOrEqualToAccessToken(currentUser, &resources.AccessToken{
9894
Name: token.Name, AccessTokenSpec: token.AccessTokenSpec, Tenant: token.Tenant,

api/handler/access_token_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func (suite *AccessTokenTestSuite) TestCreateAndDelete() {
8585
Body: key,
8686
Path: "/v1alpha1/access_tokens",
8787
TestWithoutRoles: func(rec *ResponseRecorder) {
88-
suite.IsMissingRoleError(rec, resources.InsufficientPermissionsError.Error())
88+
suite.IsUnauthorizedError(rec, resources.InsufficientPermissionsError.Error())
8989
},
9090
TestWithRoles: func(rec *ResponseRecorder) {
9191
var res resources.AccessToken
@@ -137,7 +137,7 @@ func (suite *AccessTokenTestSuite) TestCreateAndDelete() {
137137
Path: "/v1alpha1/access_tokens",
138138
Body: key,
139139
TestWithoutRoles: func(rec *ResponseRecorder) {
140-
suite.IsMissingRoleError(rec, resources.InsufficientPermissionsError.Error())
140+
suite.IsUnauthorizedError(rec, resources.InsufficientPermissionsError.Error())
141141
},
142142
TestWithRoles: func(rec *ResponseRecorder) {
143143
suite.Equal(200, rec.Code)

api/handler/acmeserver_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func (suite *ACMEServerHandlerTestSuite) TestGetEmpty() {
3333
Method: http.MethodGet,
3434
Path: "/v1alpha1/acmeserver",
3535
TestWithoutRoles: func(rec *ResponseRecorder) {
36-
suite.IsMissingRoleError(rec, "view", "cluster")
36+
suite.IsUnauthorizedError(rec, "view", "cluster")
3737
},
3838
TestWithRoles: func(rec *ResponseRecorder) {
3939
suite.Equal(200, rec.Code)
@@ -59,7 +59,7 @@ func (suite *ACMEServerHandlerTestSuite) TestCreateGetDelete() {
5959
NSDomain: nsDomain,
6060
},
6161
TestWithoutRoles: func(rec *ResponseRecorder) {
62-
suite.IsMissingRoleError(rec, "editor", "cluster")
62+
suite.IsUnauthorizedError(rec, "editor", "cluster")
6363
},
6464
TestWithRoles: func(rec *ResponseRecorder) {
6565
var res resources.ACMEServer
@@ -79,7 +79,7 @@ func (suite *ACMEServerHandlerTestSuite) TestCreateGetDelete() {
7979
Method: http.MethodGet,
8080
Path: "/v1alpha1/acmeserver",
8181
TestWithoutRoles: func(rec *ResponseRecorder) {
82-
suite.IsMissingRoleError(rec, "viewer", "cluster")
82+
suite.IsUnauthorizedError(rec, "viewer", "cluster")
8383
},
8484
TestWithRoles: func(rec *ResponseRecorder) {
8585
var acmeResp resources.ACMEServerResp
@@ -102,7 +102,7 @@ func (suite *ACMEServerHandlerTestSuite) TestCreateGetDelete() {
102102
Method: http.MethodDelete,
103103
Path: "/v1alpha1/acmeserver",
104104
TestWithoutRoles: func(rec *ResponseRecorder) {
105-
suite.IsMissingRoleError(rec, "editor", "cluster")
105+
suite.IsUnauthorizedError(rec, "editor", "cluster")
106106
},
107107
TestWithRoles: func(rec *ResponseRecorder) {
108108
suite.Equal(200, rec.Code)
@@ -118,7 +118,7 @@ func (suite *ACMEServerHandlerTestSuite) TestCreateGetDelete() {
118118
Method: http.MethodGet,
119119
Path: "/v1alpha1/acmeserver",
120120
TestWithoutRoles: func(rec *ResponseRecorder) {
121-
suite.IsMissingRoleError(rec, "viewer", "cluster")
121+
suite.IsUnauthorizedError(rec, "viewer", "cluster")
122122
},
123123
TestWithRoles: func(rec *ResponseRecorder) {
124124
suite.Equal(200, rec.Code)

api/handler/applications.go

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package handler
22

33
import (
4+
"fmt"
45
"net/http"
56

67
"github.com/kalmhq/kalm/api/errors"
@@ -19,7 +20,7 @@ func (h *ApiHandler) InstallApplicationsHandlers(e *echo.Group) {
1920
e.GET("/applications", h.handleGetApplications)
2021
e.POST("/applications", h.handleCreateApplication)
2122
e.GET("/applications/:name", h.handleGetApplicationDetails, h.setApplicationIntoContext)
22-
e.DELETE("/applications/:name", h.handleDeleteApplication, h.requireIsTenantOwner, h.setApplicationIntoContext)
23+
e.DELETE("/applications/:name", h.handleDeleteApplication, h.setApplicationIntoContext)
2324
}
2425

2526
// middlewares
@@ -74,10 +75,7 @@ func (h *ApiHandler) handleGetApplications(c echo.Context) error {
7475
func (h *ApiHandler) handleGetApplicationDetails(c echo.Context) error {
7576
namespace := h.getApplicationFromContext(c)
7677
currentUser := getCurrentUser(c)
77-
78-
if !h.clientManager.CanViewScope(currentUser, namespace.Name) {
79-
return resources.NoNamespaceViewerRoleError(namespace.Name)
80-
}
78+
h.MustCanView(currentUser, fmt.Sprintf("%s/%s", currentUser.Tenant, namespace.Name), "applications/"+namespace.Name)
8179

8280
res, err := h.resourceManager.BuildApplicationDetails(namespace)
8381

@@ -90,10 +88,7 @@ func (h *ApiHandler) handleGetApplicationDetails(c echo.Context) error {
9088

9189
func (h *ApiHandler) handleCreateApplication(c echo.Context) error {
9290
currentUser := getCurrentUser(c)
93-
94-
if !h.clientManager.Can(currentUser, "create", currentUser.Tenant+"/*", "applications/*") {
95-
panic("TODO: fix this")
96-
}
91+
h.MustCanEdit(currentUser, currentUser.Tenant+"/*", "applications/*")
9792

9893
ns, err := bindKalmNamespaceFromRequestBody(c)
9994

@@ -119,6 +114,9 @@ func (h *ApiHandler) handleCreateApplication(c echo.Context) error {
119114
}
120115

121116
func (h *ApiHandler) handleDeleteApplication(c echo.Context) error {
117+
currentUser := getCurrentUser(c)
118+
h.MustCanEdit(currentUser, currentUser.Tenant+"/*", "applications/*")
119+
122120
namespace := h.getApplicationFromContext(c)
123121

124122
if err := h.resourceManager.DeleteNamespace(namespace); err != nil {

api/handler/applications_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func (suite *ApplicationsHandlerTestSuite) TestCreateEmptyApplication() {
101101
Path: "/v1alpha1/applications",
102102
Body: fmt.Sprintf(`{"name": "%s"}`, name),
103103
TestWithoutRoles: func(rec *ResponseRecorder) {
104-
suite.IsMissingRoleError(rec, "editor", "cluster")
104+
suite.IsUnauthorizedError(rec, "edit")
105105
},
106106
TestWithRoles: func(rec *ResponseRecorder) {
107107
var res resources.ApplicationDetails
@@ -121,7 +121,7 @@ func (suite *ApplicationsHandlerTestSuite) TestCreateEmptyApplication() {
121121
Method: http.MethodGet,
122122
Path: "/v1alpha1/applications/" + name,
123123
TestWithoutRoles: func(rec *ResponseRecorder) {
124-
suite.IsMissingRoleError(rec, "viewer", name)
124+
suite.IsUnauthorizedError(rec, "view", name)
125125
},
126126
TestWithRoles: func(rec *ResponseRecorder) {
127127
var res resources.ApplicationDetails
@@ -172,7 +172,7 @@ func (suite *ApplicationsHandlerTestSuite) TestDeleteApplication() {
172172
Method: http.MethodDelete,
173173
Path: "/v1alpha1/applications/test3",
174174
TestWithoutRoles: func(rec *ResponseRecorder) {
175-
suite.IsMissingRoleError(rec, "editor", "cluster")
175+
suite.IsUnauthorizedError(rec, "edit")
176176
},
177177
TestWithRoles: func(rec *ResponseRecorder) {
178178
suite.Equal(http.StatusNoContent, rec.Code)

api/handler/cluster.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,7 @@ type SetupClusterResponse struct {
200200
}
201201

202202
func (h *ApiHandler) handleInitializeCluster(c echo.Context) error {
203-
204-
if !h.clientManager.CanManageCluster(getCurrentUser(c)) {
205-
return resources.NoClusterOwnerRoleError
206-
}
203+
h.MustCanManageCluster(getCurrentUser(c))
207204

208205
clusterInfo := h.getClusterInfo(c)
209206

@@ -337,9 +334,7 @@ func (h *ApiHandler) handleInitializeCluster(c echo.Context) error {
337334

338335
func (h *ApiHandler) handleResetCluster(c echo.Context) error {
339336

340-
if !h.clientManager.CanManageCluster(getCurrentUser(c)) {
341-
return resources.NoClusterOwnerRoleError
342-
}
337+
h.MustCanManageCluster(getCurrentUser(c))
343338

344339
wg := sync.WaitGroup{}
345340

api/handler/cluster_test.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package handler
22

33
import (
4-
"github.com/kalmhq/kalm/api/resources"
5-
"github.com/stretchr/testify/suite"
64
"net/http"
75
"testing"
6+
7+
"github.com/kalmhq/kalm/api/resources"
8+
"github.com/stretchr/testify/suite"
89
)
910

1011
type ClusterHandlerTestSuite struct {
@@ -26,7 +27,7 @@ func (suite *ClusterHandlerTestSuite) TestClusterInfo() {
2627
Path: "/v1alpha1/initialize",
2728
Body: `{"domain": "kalm.test"}`,
2829
TestWithoutRoles: func(rec *ResponseRecorder) {
29-
suite.IsMissingRoleError(rec, "owner", "cluster")
30+
suite.IsUnauthorizedError(rec)
3031
},
3132
TestWithRoles: func(rec *ResponseRecorder) {
3233
var setupClusterResponse SetupClusterResponse
@@ -45,7 +46,7 @@ func (suite *ClusterHandlerTestSuite) TestClusterInfo() {
4546
Path: "/v1alpha1/cluster",
4647
Body: `{}`,
4748
TestWithoutRoles: func(rec *ResponseRecorder) {
48-
suite.IsMissingRoleError(rec, "viewer", "cluster")
49+
suite.IsUnauthorizedError(rec)
4950
},
5051
TestWithRoles: func(rec *ResponseRecorder) {
5152
var clusterInfo ClusterInfo
@@ -78,7 +79,7 @@ func (suite *ClusterHandlerTestSuite) TestClusterInfo() {
7879
Path: "/v1alpha1/reset",
7980
Body: `{}`,
8081
TestWithoutRoles: func(rec *ResponseRecorder) {
81-
suite.IsMissingRoleError(rec, "owner", "cluster")
82+
suite.IsUnauthorizedError(rec)
8283
},
8384
TestWithRoles: func(rec *ResponseRecorder) {
8485
suite.Equal(200, rec.Code)

0 commit comments

Comments
 (0)