fix: allow users with workspace:create for any owner to list users (#21947)

## Summary

Custom roles that can create workspaces on behalf of other users need to
be able to list users to populate the owner dropdown in the workspace
creation UI. Previously, this required a separate `user:read`
permission, causing the dropdown to fail for custom roles.

## Changes

- Modified `GetUsers` in `dbauthz` to check if the user can create
workspaces for any owner (`workspace:create` with `owner_id: *`)
- If the user has this permission, they can list all users without
needing explicit `user:read` permission
- Added tests to verify the new behavior

## Testing

- Updated mock tests to assert the new authorization check
- Added integration tests for both positive and negative cases

Fixes #18203
This commit is contained in:
Garrett Delfosse
2026-02-19 13:04:53 -05:00
committed by GitHub
parent 911d734df9
commit e8d6016807
13 changed files with 388 additions and 16 deletions
+48
View File
@@ -5625,6 +5625,54 @@ func TestWorkspaceSharingDisabled(t *testing.T) {
})
}
func TestWorkspaceAvailableUsers(t *testing.T) {
t.Parallel()
t.Run("OrgAdminCanListUsers", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
owner := coderdtest.CreateFirstUser(t, client)
ctx := testutil.Context(t, testutil.WaitMedium)
// Create an org admin and additional users
orgAdminClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.ScopedRoleOrgAdmin(owner.OrganizationID))
_, user1 := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
_, user2 := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
// Org admin should be able to list available users
users, err := orgAdminClient.WorkspaceAvailableUsers(ctx, owner.OrganizationID, "me")
require.NoError(t, err)
require.GreaterOrEqual(t, len(users), 4) // owner + orgAdmin + 2 users
// Verify the users we created are in the list
usernames := make([]string, 0, len(users))
for _, u := range users {
usernames = append(usernames, u.Username)
}
require.Contains(t, usernames, user1.Username)
require.Contains(t, usernames, user2.Username)
})
t.Run("MemberCannotListUsers", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
owner := coderdtest.CreateFirstUser(t, client)
ctx := testutil.Context(t, testutil.WaitMedium)
// Create a regular member
memberClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
// Regular member should not be able to list available users
_, err := memberClient.WorkspaceAvailableUsers(ctx, owner.OrganizationID, "me")
require.Error(t, err)
var apiErr *codersdk.Error
require.ErrorAs(t, err, &apiErr)
require.Equal(t, http.StatusForbidden, apiErr.StatusCode())
})
}
func TestWorkspaceCreateWithImplicitPreset(t *testing.T) {
t.Parallel()