From 68538a9ce1646c5210f28243fd4bed665123d53f Mon Sep 17 00:00:00 2001 From: Malik Hadjri <19805673+hadjri@users.noreply.github.com> Date: Fri, 29 Mar 2024 17:50:03 -0400 Subject: [PATCH] DEVPROD-739 Remove hidden projects from permissions response (#7687) --- rest/route/user.go | 29 +++++++++++++- rest/route/user_test.go | 86 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 112 insertions(+), 3 deletions(-) diff --git a/rest/route/user.go b/rest/route/user.go index 6ae1aa4c7a9..412cfe6c905 100644 --- a/rest/route/user.go +++ b/rest/route/user.go @@ -479,14 +479,41 @@ func (h *userPermissionsGetHandler) Run(ctx context.Context) gimlet.Responder { if !h.includeAll { rolesToSearch, _ = utility.StringSliceSymmetricDifference(u.SystemRoles, evergreen.GeneralAccessRoles) } - // filter out the roles that everybody has automatically + // Filter out the roles that everybody has automatically permissions, err := rolemanager.PermissionSummaryForRoles(ctx, rolesToSearch, h.rm) if err != nil { return gimlet.NewJSONInternalErrorResponse(errors.Wrapf(err, "getting permissions for user '%s'", h.userID)) } + // Hidden projects are not meant to be exposed to the user, so we remove them from the response here. + if err = removeHiddenProjects(permissions); err != nil { + return gimlet.MakeJSONInternalErrorResponder(err) + } return gimlet.NewJSONResponse(permissions) } +func removeHiddenProjects(permissions []rolemanager.PermissionSummary) error { + var projectIDs []string + var projectResourceIndex int + for i, permission := range permissions { + if permission.Type == evergreen.ProjectResourceType { + projectResourceIndex = i + for projectID := range permission.Permissions { + projectIDs = append(projectIDs, projectID) + } + } + } + projectRefs, err := serviceModel.FindProjectRefsByIds(projectIDs...) + if err != nil { + return errors.Wrapf(err, "getting projects") + } + for _, projectRef := range projectRefs { + if utility.FromBoolPtr(projectRef.Hidden) { + delete(permissions[projectResourceIndex].Permissions, projectRef.Id) + } + } + return nil +} + type rolesPostRequest struct { // the list of roles to add for the user Roles []string `json:"roles"` diff --git a/rest/route/user_test.go b/rest/route/user_test.go index bf22cfa8fc5..80c48c79e6c 100644 --- a/rest/route/user_test.go +++ b/rest/route/user_test.go @@ -312,16 +312,36 @@ func TestGetUserPermissions(t *testing.T) { defer cancel() env := testutil.NewEnvironment(ctx, t) - require.NoError(t, db.ClearCollections(user.Collection, evergreen.ScopeCollection, evergreen.RoleCollection)) + require.NoError(t, db.ClearCollections(user.Collection, evergreen.ScopeCollection, evergreen.RoleCollection, model.ProjectRefCollection)) rm := env.RoleManager() require.NoError(t, db.CreateCollections(evergreen.ScopeCollection)) u := user.DBUser{ Id: "user", - SystemRoles: []string{"role1", evergreen.BasicProjectAccessRole, evergreen.BasicDistroAccessRole}, + SystemRoles: []string{"role1", "role2", "role3", evergreen.BasicProjectAccessRole, evergreen.BasicDistroAccessRole}, + } + projectRefs := []model.ProjectRef{ + { + Id: "resource1", + }, + { + Id: "resource2", + Hidden: utility.TruePtr(), + }, + { + Id: "resource3", + }, + } + for _, projectRef := range projectRefs { + require.NoError(t, projectRef.Upsert()) } require.NoError(t, u.Insert()) require.NoError(t, rm.AddScope(gimlet.Scope{ID: "scope1", Resources: []string{"resource1"}, Type: "project"})) + require.NoError(t, rm.AddScope(gimlet.Scope{ID: "scope2", Resources: []string{"resource2"}, Type: "project"})) + require.NoError(t, rm.AddScope(gimlet.Scope{ID: "scope3", Resources: []string{"resource3"}, Type: "project"})) require.NoError(t, rm.UpdateRole(gimlet.Role{ID: "role1", Scope: "scope1", Permissions: gimlet.Permissions{evergreen.PermissionProjectSettings: evergreen.ProjectSettingsEdit.Value}})) + require.NoError(t, rm.UpdateRole(gimlet.Role{ID: "role2", Scope: "scope2", Permissions: gimlet.Permissions{evergreen.PermissionProjectSettings: evergreen.ProjectSettingsEdit.Value}})) + require.NoError(t, rm.UpdateRole(gimlet.Role{ID: "role3", Scope: "scope3", Permissions: gimlet.Permissions{evergreen.PermissionProjectSettings: evergreen.ProjectSettingsEdit.Value}})) + handler := userPermissionsGetHandler{rm: rm, userID: u.Id} resp := handler.Run(context.Background()) @@ -329,7 +349,10 @@ func TestGetUserPermissions(t *testing.T) { data := resp.Data().([]rolemanager.PermissionSummary) assert.Len(t, data, 1) assert.Equal(t, "project", data[0].Type) + require.Len(t, data[0].Permissions, 2) assert.Equal(t, evergreen.ProjectSettingsEdit.Value, data[0].Permissions["resource1"][evergreen.PermissionProjectSettings]) + assert.Nil(t, data[0].Permissions["resource2"]) + assert.Equal(t, evergreen.ProjectSettingsEdit.Value, data[0].Permissions["resource3"][evergreen.PermissionProjectSettings]) } func TestPostUserRoles(t *testing.T) { @@ -491,6 +514,65 @@ func TestGetUsersForRole(t *testing.T) { assert.Contains(t, utility.FromStringPtr(usersWithRole.Users[1]), u2.Id) } +func TestRemoveHiddenProjects(t *testing.T) { + require.NoError(t, db.ClearCollections(model.ProjectRefCollection)) + projectRefs := []model.ProjectRef{ + { + Id: "project1", + Hidden: utility.TruePtr(), + }, + { + Id: "project2", + }, + { + Id: "project3", + Hidden: utility.TruePtr(), + }, + { + Id: "project4", + }, + } + for _, projectRef := range projectRefs { + require.NoError(t, projectRef.Upsert()) + } + + permissions := []rolemanager.PermissionSummary{ + { + Type: evergreen.ProjectResourceType, + Permissions: rolemanager.PermissionsForResources{ + "project1": gimlet.Permissions{ + "project_settings": 10, + }, + "project2": gimlet.Permissions{ + "project_settings": 10, + }, + "project3": gimlet.Permissions{ + "project_settings": 10, + }, + "project4": gimlet.Permissions{ + "project_settings": 10, + }, + }, + }, + { + Type: evergreen.DistroResourceType, + Permissions: rolemanager.PermissionsForResources{ + "distro1": gimlet.Permissions{ + "distro_settings": 10, + }, + }, + }, + } + + assert.NoError(t, removeHiddenProjects(permissions)) + require.Len(t, permissions, 2) + require.Len(t, permissions[0].Permissions, 2) + require.Nil(t, permissions[0].Permissions["project1"]) + require.NotNil(t, permissions[0].Permissions["project2"]) + require.Nil(t, permissions[0].Permissions["project3"]) + require.NotNil(t, permissions[0].Permissions["project4"]) +} + func TestGetUsersForResourceId(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel()