Skip to content

Commit

Permalink
Merge pull request #289 from linkernetworks/johnlin/deployment-auth
Browse files Browse the repository at this point in the history
[Task] add auth for deployment
  • Loading branch information
Hung-Wei Chiu authored Aug 28, 2018
2 parents 0da5f51 + 83a577a commit 2b98a36
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 7 deletions.
2 changes: 2 additions & 0 deletions src/entity/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type DeploymentVolume struct {
// Deployment is the structure for deployment info
type Deployment struct {
ID bson.ObjectId `bson:"_id,omitempty" json:"id" validate:"-"`
OwnerID bson.ObjectId `bson:"ownerID,omitempty" json:"ownerID" validate:"-"`
Name string `bson:"name" json:"name" validate:"required,k8sname"`
Namespace string `bson:"namespace" json:"namespace" validate:"required"`
Labels map[string]string `bson:"labels,omitempty" json:"labels" validate:"required,dive,keys,printascii,endkeys,required,printascii"`
Expand All @@ -63,6 +64,7 @@ type Deployment struct {
Capability bool `bson:"capability" json:"capability" validate:"-"`
NetworkType string `bson:"networkType" json:"networkType" validate:"required,eq=host|eq=cluster|eq=custom"`
NodeAffinity []string `bson:"nodeAffinity" json:"nodeAffinity" validate:"required"`
CreatedBy User `json:"createdBy" validate:"-"`
CreatedAt *time.Time `bson:"createdAt,omitempty" json:"createdAt,omitempty" validate:"-"`

Replicas int32 `bson:"replicas" json:"replicas" validate:"required"`
Expand Down
15 changes: 15 additions & 0 deletions src/server/handler_deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/linkernetworks/vortex/src/entity"
response "github.com/linkernetworks/vortex/src/net/http"
"github.com/linkernetworks/vortex/src/net/http/query"
"github.com/linkernetworks/vortex/src/server/backend"
"github.com/linkernetworks/vortex/src/web"
"k8s.io/apimachinery/pkg/api/errors"

Expand All @@ -20,6 +21,11 @@ import (

func createDeploymentHandler(ctx *web.Context) {
sp, req, resp := ctx.ServiceProvider, ctx.Request, ctx.Response
userID, ok := req.Attribute("UserID").(string)
if !ok {
response.Unauthorized(req.Request, resp.ResponseWriter, fmt.Errorf("Unauthorized: User ID is empty"))
return
}

p := entity.Deployment{}
if err := req.ReadEntity(&p); err != nil {
Expand Down Expand Up @@ -55,6 +61,7 @@ func createDeploymentHandler(ctx *web.Context) {
}
return
}
p.OwnerID = bson.ObjectIdHex(userID)
if err := session.Insert(entity.DeploymentCollectionName, &p); err != nil {
if mgo.IsDup(err) {
response.Conflict(req.Request, resp.ResponseWriter, fmt.Errorf("Deployment Name: %s already existed", p.Name))
Expand All @@ -63,6 +70,8 @@ func createDeploymentHandler(ctx *web.Context) {
}
return
}
// find owner in user entity
p.CreatedBy, _ = backend.FindUserByID(session, p.OwnerID)
resp.WriteHeaderAndEntity(http.StatusCreated, p)
}

Expand Down Expand Up @@ -144,6 +153,11 @@ func listDeploymentHandler(ctx *web.Context) {
}
}

// insert users entity
for _, deployment := range deployments {
// find owner in user entity
deployment.CreatedBy, _ = backend.FindUserByID(session, deployment.OwnerID)
}
count, err := session.Count(entity.DeploymentCollectionName, bson.M{})
if err != nil {
response.InternalServerError(req.Request, resp.ResponseWriter, err)
Expand Down Expand Up @@ -175,5 +189,6 @@ func getDeploymentHandler(ctx *web.Context) {
return
}
}
deployment.CreatedBy, _ = backend.FindUserByID(session, deployment.OwnerID)
resp.WriteEntity(deployment)
}
34 changes: 27 additions & 7 deletions src/server/handler_deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,31 @@ func init() {

type DeploymentTestSuite struct {
suite.Suite
sp *serviceprovider.Container
wc *restful.Container
session *mongo.Session
sp *serviceprovider.Container
wc *restful.Container
session *mongo.Session
JWTBearer string
}

func (suite *DeploymentTestSuite) SetupSuite() {
cf := config.MustRead("../../config/testing.json")
sp := serviceprovider.NewForTesting(cf)

suite.sp = sp
//init session
// init session
suite.session = sp.Mongo.NewSession()
//init restful container
// init restful container
suite.wc = restful.NewContainer()
service := newDeploymentService(suite.sp)
suite.wc.Add(service)

deploymentService := newDeploymentService(suite.sp)
userService := newUserService(suite.sp)

suite.wc.Add(deploymentService)
suite.wc.Add(userService)

token, _ := loginGetToken(suite.wc)
suite.NotEmpty(token)
suite.JWTBearer = "Bearer " + token
}

func (suite *DeploymentTestSuite) TearDownSuite() {}
Expand Down Expand Up @@ -81,6 +90,7 @@ func (suite *DeploymentTestSuite) TestCreateDeployment() {
suite.NoError(err)

httpRequest.Header.Add("Content-Type", "application/json")
httpRequest.Header.Add("Authorization", suite.JWTBearer)
httpWriter := httptest.NewRecorder()
suite.wc.Dispatch(httpWriter, httpRequest)
assertResponseCode(suite.T(), http.StatusCreated, httpWriter)
Expand All @@ -103,6 +113,7 @@ func (suite *DeploymentTestSuite) TestCreateDeployment() {
httpRequest, err = http.NewRequest("POST", "http://localhost:7890/v1/deployments", bodyReader)
suite.NoError(err)
httpRequest.Header.Add("Content-Type", "application/json")
httpRequest.Header.Add("Authorization", suite.JWTBearer)
httpWriter = httptest.NewRecorder()
suite.wc.Dispatch(httpWriter, httpRequest)
assertResponseCode(suite.T(), http.StatusConflict, httpWriter)
Expand Down Expand Up @@ -138,6 +149,7 @@ func (suite *DeploymentTestSuite) TestCreateDeploymentFail() {
suite.NoError(err)

httpRequest.Header.Add("Content-Type", "application/json")
httpRequest.Header.Add("Authorization", suite.JWTBearer)
httpWriter := httptest.NewRecorder()
suite.wc.Dispatch(httpWriter, httpRequest)
assertResponseCode(suite.T(), http.StatusBadRequest, httpWriter)
Expand Down Expand Up @@ -178,6 +190,7 @@ func (suite *DeploymentTestSuite) TestDeleteDeployment() {
suite.NoError(err)

httpRequest.Header.Add("Content-Type", "application/json")
httpRequest.Header.Add("Authorization", suite.JWTBearer)
httpWriter := httptest.NewRecorder()
suite.wc.Dispatch(httpWriter, httpRequest)
assertResponseCode(suite.T(), http.StatusOK, httpWriter)
Expand All @@ -192,6 +205,7 @@ func (suite *DeploymentTestSuite) TestDeleteDeploymentWithInvalidID() {
suite.NoError(err)

httpRequest.Header.Add("Content-Type", "application/json")
httpRequest.Header.Add("Authorization", suite.JWTBearer)
httpWriter := httptest.NewRecorder()
suite.wc.Dispatch(httpWriter, httpRequest)
assertResponseCode(suite.T(), http.StatusBadRequest, httpWriter)
Expand Down Expand Up @@ -222,6 +236,7 @@ func (suite *DeploymentTestSuite) TestGetDeployment() {
httpRequest, err := http.NewRequest("GET", "http://localhost:7890/v1/deployments/"+deploy.ID.Hex(), nil)
suite.NoError(err)

httpRequest.Header.Add("Authorization", suite.JWTBearer)
httpWriter := httptest.NewRecorder()
suite.wc.Dispatch(httpWriter, httpRequest)
assertResponseCode(suite.T(), http.StatusOK, httpWriter)
Expand All @@ -238,6 +253,7 @@ func (suite *DeploymentTestSuite) TestGetDeploymentWithInvalidID() {
httpRequest, err := http.NewRequest("GET", "http://localhost:7890/v1/deployments/"+bson.NewObjectId().Hex(), nil)
suite.NoError(err)

httpRequest.Header.Add("Authorization", suite.JWTBearer)
httpWriter := httptest.NewRecorder()
suite.wc.Dispatch(httpWriter, httpRequest)
assertResponseCode(suite.T(), http.StatusNotFound, httpWriter)
Expand Down Expand Up @@ -290,6 +306,7 @@ func (suite *DeploymentTestSuite) TestListDeployment() {
httpRequest, err := http.NewRequest("GET", url, nil)
suite.NoError(err)

httpRequest.Header.Add("Authorization", suite.JWTBearer)
httpWriter := httptest.NewRecorder()
suite.wc.Dispatch(httpWriter, httpRequest)
assertResponseCode(suite.T(), http.StatusOK, httpWriter)
Expand All @@ -311,20 +328,23 @@ func (suite *DeploymentTestSuite) TestListDeploymentWithInvalidPage() {
httpRequest, err := http.NewRequest("GET", "http://localhost:7890/v1/deployments?page=asdd", nil)
suite.NoError(err)

httpRequest.Header.Add("Authorization", suite.JWTBearer)
httpWriter := httptest.NewRecorder()
suite.wc.Dispatch(httpWriter, httpRequest)
assertResponseCode(suite.T(), http.StatusBadRequest, httpWriter)

httpRequest, err = http.NewRequest("GET", "http://localhost:7890/v1/deployments?page_size=asdd", nil)
suite.NoError(err)

httpRequest.Header.Add("Authorization", suite.JWTBearer)
httpWriter = httptest.NewRecorder()
suite.wc.Dispatch(httpWriter, httpRequest)
assertResponseCode(suite.T(), http.StatusBadRequest, httpWriter)

httpRequest, err = http.NewRequest("GET", "http://localhost:7890/v1/deployments?page=-1", nil)
suite.NoError(err)

httpRequest.Header.Add("Authorization", suite.JWTBearer)
httpWriter = httptest.NewRecorder()
suite.wc.Dispatch(httpWriter, httpRequest)
assertResponseCode(suite.T(), http.StatusInternalServerError, httpWriter)
Expand Down
1 change: 1 addition & 0 deletions src/server/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ func newPodService(sp *serviceprovider.Container) *restful.WebService {

func newDeploymentService(sp *serviceprovider.Container) *restful.WebService {
webService := new(restful.WebService)
webService.Filter(validateTokenMiddleware)
webService.Path("/v1/deployments").Consumes(restful.MIME_JSON, restful.MIME_JSON).Produces(restful.MIME_JSON, restful.MIME_JSON)
webService.Route(webService.POST("/").To(handler.RESTfulServiceHandler(sp, createDeploymentHandler)))
webService.Route(webService.DELETE("/{id}").To(handler.RESTfulServiceHandler(sp, deleteDeploymentHandler)))
Expand Down

0 comments on commit 2b98a36

Please sign in to comment.