diff --git a/handlers/workspaces.go b/handlers/workspaces.go index 7069e56c1..bdcb0ae77 100644 --- a/handlers/workspaces.go +++ b/handlers/workspaces.go @@ -338,7 +338,7 @@ func GetBountyRoles(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(roles) } -func AddUserRoles(w http.ResponseWriter, r *http.Request) { +func (oh *workspaceHandler) AddUserRoles(w http.ResponseWriter, r *http.Request) { ctx := r.Context() pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string) uuid := chi.URLParam(r, "uuid") @@ -376,7 +376,7 @@ func AddUserRoles(w http.ResponseWriter, r *http.Request) { } // if not the orgnization admin - hasRole := db.UserHasAccess(pubKeyFromAuth, uuid, db.AddRoles) + hasRole := oh.userHasAccess(pubKeyFromAuth, uuid, db.AddRoles) isUser := db.CheckUser(roles, pubKeyFromAuth) if isUser { @@ -415,7 +415,7 @@ func AddUserRoles(w http.ResponseWriter, r *http.Request) { } // check if the user has the role he his trying to add to another user - okUser := db.UserHasAccess(pubKeyFromAuth, uuid, role.Role) + okUser := oh.userHasAccess(pubKeyFromAuth, uuid, role.Role) // if the user does not have any of the roles he wants to add return an error if !okUser { w.WriteHeader(http.StatusUnauthorized) @@ -429,7 +429,7 @@ func AddUserRoles(w http.ResponseWriter, r *http.Request) { } // check if user already exists - userExists := db.DB.GetWorkspaceUser(user, uuid) + userExists := oh.db.GetWorkspaceUser(user, uuid) // if not the workspace admin if userExists.OwnerPubKey != user || userExists.WorkspaceUuid != uuid { @@ -438,7 +438,7 @@ func AddUserRoles(w http.ResponseWriter, r *http.Request) { return } - db.DB.CreateUserRoles(insertRoles, uuid, user) + oh.db.CreateUserRoles(insertRoles, uuid, user) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(insertRoles) diff --git a/handlers/workspaces_test.go b/handlers/workspaces_test.go index cfaa6448d..62cf77536 100644 --- a/handlers/workspaces_test.go +++ b/handlers/workspaces_test.go @@ -650,6 +650,209 @@ func TestGetWorkspaceBountiesCount(t *testing.T) { func TestAddUserRoles(t *testing.T) { + teardownSuite := SetupSuite(t) + defer teardownSuite(t) + + oHandler := NewWorkspaceHandler(db.TestDB) + + person := db.Person{ + Uuid: uuid.New().String(), + OwnerAlias: "alias", + UniqueName: "unique_name", + OwnerPubKey: "pubkey", + PriceToMeet: 0, + Description: "description", + } + + person2 := db.Person{ + Uuid: uuid.New().String(), + OwnerAlias: "alias2", + UniqueName: "unique_name2", + OwnerPubKey: "pubkey2", + PriceToMeet: 0, + Description: "description2", + } + db.TestDB.CreateOrEditPerson(person) + db.TestDB.CreateOrEditPerson(person2) + + workspace := db.Workspace{ + Uuid: uuid.New().String(), + Name: "workspace_name", + OwnerPubKey: person2.OwnerPubKey, + Github: "gtihub", + Website: "website", + Description: "description", + } + db.TestDB.CreateOrEditWorkspace(workspace) + + userRoles := []db.WorkspaceUserRoles{ + db.WorkspaceUserRoles{ + WorkspaceUuid: workspace.Uuid, + OwnerPubKey: person2.OwnerPubKey, + Role: "ADD BOUNTY", + }, + } + + workspaceUser := db.WorkspaceUsers{ + OwnerPubKey: person2.OwnerPubKey, + OrgUuid: workspace.Uuid, + WorkspaceUuid: workspace.Uuid, + } + + db.TestDB.CreateWorkspaceUser(workspaceUser) + + t.Run("Should test that when the right conditions are met a user can be added to a workspace", func(t *testing.T) { + handlerUserHasAccess := func(pubKeyFromAuth string, uuid string, role string) bool { + return true + } + oHandler.userHasAccess = handlerUserHasAccess + + ctx := context.WithValue(context.Background(), auth.ContextKey, "pub-key") + + requestBody, _ := json.Marshal(userRoles) + rctx := chi.NewRouteContext() + rctx.URLParams.Add("uuid", workspace.Uuid) + rctx.URLParams.Add("user", person2.OwnerPubKey) + req, err := http.NewRequestWithContext(context.WithValue(ctx, chi.RouteCtxKey, rctx), http.MethodPost, "/users/role/"+workspace.Uuid+"/"+person2.OwnerPubKey, bytes.NewReader(requestBody)) + if err != nil { + t.Fatal(err) + } + + fetchedWorkspaceUser := db.TestDB.GetWorkspaceUser(person2.OwnerPubKey, workspace.Uuid) + + rr := httptest.NewRecorder() + http.HandlerFunc(oHandler.AddUserRoles).ServeHTTP(rr, req) + + fetchedUserRole := db.TestDB.GetUserRoles(workspace.Uuid, person2.OwnerPubKey) + assert.Equal(t, http.StatusOK, rr.Code) + assert.Equal(t, person2.OwnerPubKey, fetchedWorkspaceUser.OwnerPubKey) + assert.Equal(t, userRoles[0].Role, fetchedUserRole[0].Role) + + }) + + t.Run("Should test that when an unauthorized user hits the endpoint it returns a 401 error", func(t *testing.T) { + workspaceUUID := workspace.Uuid + + requestBody, _ := json.Marshal(userRoles) + rctx := chi.NewRouteContext() + rctx.URLParams.Add("uuid", workspaceUUID) + rctx.URLParams.Add("user", person2.OwnerPubKey) + req, err := http.NewRequestWithContext(context.WithValue(context.Background(), chi.RouteCtxKey, rctx), http.MethodPost, "/users/role/"+workspaceUUID+"/"+person2.OwnerPubKey, bytes.NewReader(requestBody)) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + http.HandlerFunc(oHandler.AddUserRoles).ServeHTTP(rr, req) + + assert.Equal(t, http.StatusUnauthorized, rr.Code) + }) + + t.Run("Should test that if a user or uuid parameters are not passed it returns a 401 error", func(t *testing.T) { + + requestBody, _ := json.Marshal(userRoles) + rctx := chi.NewRouteContext() + rctx.URLParams.Add("uuid", "") + rctx.URLParams.Add("user", "") + req, err := http.NewRequestWithContext(context.WithValue(context.Background(), chi.RouteCtxKey, rctx), http.MethodPost, "/users/role/"+""+"/"+"", bytes.NewReader(requestBody)) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + http.HandlerFunc(oHandler.AddUserRoles).ServeHTTP(rr, req) + + assert.Equal(t, http.StatusUnauthorized, rr.Code) + }) + + t.Run("Should test that when a wrong body data is sent to the endpoint it returns a 406 error", func(t *testing.T) { + workspaceUUID := workspace.Uuid + + InvalidJson := []byte(`{"key": "value"`) + requestBody, _ := json.Marshal(InvalidJson) + rctx := chi.NewRouteContext() + rctx.URLParams.Add("uuid", workspaceUUID) + rctx.URLParams.Add("user", person2.OwnerPubKey) + req, err := http.NewRequestWithContext(context.WithValue(context.Background(), chi.RouteCtxKey, rctx), http.MethodPost, "/users/role/"+workspaceUUID+"/"+person2.OwnerPubKey, bytes.NewReader(requestBody)) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + http.HandlerFunc(oHandler.AddUserRoles).ServeHTTP(rr, req) + + assert.Equal(t, http.StatusNotAcceptable, rr.Code) + }) + + t.Run("Should test that if a user is not the creator of the workspace or does not have an ADD USER ROLE it returns a 401 error", func(t *testing.T) { + workspaceUUID := workspace.Uuid + + handlerUserHasAccess := func(pubKeyFromAuth string, uuid string, role string) bool { + return false + } + oHandler.userHasAccess = handlerUserHasAccess + userRoles[0].OwnerPubKey = person.OwnerPubKey + requestBody, _ := json.Marshal(userRoles) + rctx := chi.NewRouteContext() + rctx.URLParams.Add("uuid", workspaceUUID) + rctx.URLParams.Add("user", person.OwnerPubKey) + req, err := http.NewRequestWithContext(context.WithValue(context.Background(), chi.RouteCtxKey, rctx), http.MethodPost, "/users/role/"+workspaceUUID+"/"+person.OwnerPubKey, bytes.NewReader(requestBody)) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + http.HandlerFunc(oHandler.AddUserRoles).ServeHTTP(rr, req) + + assert.Equal(t, http.StatusUnauthorized, rr.Code) + }) + + t.Run("Should test that when the pubkey from URL param does not match the pubkey from JWT AUTH claims it returns a 401 error", func(t *testing.T) { + workspaceUUID := workspace.Uuid + + ctx := context.WithValue(context.Background(), auth.ContextKey, "mismatching_pubkey") + + requestBody, _ := json.Marshal(userRoles) + rctx := chi.NewRouteContext() + rctx.URLParams.Add("uuid", workspaceUUID) + rctx.URLParams.Add("user", person2.OwnerPubKey) + req, err := http.NewRequestWithContext(context.WithValue(ctx, chi.RouteCtxKey, rctx), http.MethodPost, "/users/role/"+workspaceUUID+"/"+person2.OwnerPubKey, bytes.NewReader(requestBody)) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + http.HandlerFunc(oHandler.AddUserRoles).ServeHTTP(rr, req) + + assert.Equal(t, http.StatusUnauthorized, rr.Code) + }) + + t.Run("Should test that if user doesn't exists in workspace it returns a 401 error", func(t *testing.T) { + workspaceUUID := workspace.Uuid + + handlerUserHasAccess := func(pubKeyFromAuth string, uuid string, role string) bool { + return true + } + oHandler.userHasAccess = handlerUserHasAccess + ctx := context.WithValue(context.Background(), auth.ContextKey, workspace.OwnerPubKey) + + userRoles[0].OwnerPubKey = person.OwnerPubKey + requestBody, _ := json.Marshal(userRoles) + rctx := chi.NewRouteContext() + rctx.URLParams.Add("uuid", workspaceUUID) + rctx.URLParams.Add("user", person.OwnerPubKey) + + req, err := http.NewRequestWithContext(context.WithValue(ctx, chi.RouteCtxKey, rctx), http.MethodPost, "/users/role/"+workspaceUUID+"/"+person.OwnerPubKey, bytes.NewReader(requestBody)) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + http.HandlerFunc(oHandler.AddUserRoles).ServeHTTP(rr, req) + + assert.Equal(t, http.StatusUnauthorized, rr.Code) + }) + } func TestGetUserRoles(t *testing.T) { diff --git a/routes/workspaces.go b/routes/workspaces.go index 8a6753c60..bc24aa056 100644 --- a/routes/workspaces.go +++ b/routes/workspaces.go @@ -27,7 +27,7 @@ func WorkspaceRoutes() chi.Router { r.Post("/", workspaceHandlers.CreateOrEditWorkspace) r.Post("/users/{uuid}", workspaceHandlers.CreateWorkspaceUser) r.Delete("/users/{uuid}", handlers.DeleteWorkspaceUser) - r.Post("/users/role/{uuid}/{user}", handlers.AddUserRoles) + r.Post("/users/role/{uuid}/{user}", workspaceHandlers.AddUserRoles) r.Get("/foruser/{uuid}", handlers.GetWorkspaceUser) r.Get("/bounty/roles", handlers.GetBountyRoles)