@@ -241,15 +241,15 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
241241}
242242
243243var (
244- memberData map [uuid.UUID ]database.OrganizationMembersRow
245- groupData map [uuid.UUID ]database.Group
244+ userData map [uuid.UUID ]database.User
245+ groupData map [uuid.UUID ]database.Group
246246)
247247if api .Experiments .Enabled (codersdk .ExperimentWorkspaceSharing ) {
248248var err error
249- memberData ,groupData ,err = findWorkspaceMembersAndGroups (ctx ,api ,workspaces )
249+ userData ,groupData ,err = findWorkspaceUsersAndGroups (ctx ,api ,workspaces )
250250if err != nil {
251251httpapi .Write (ctx ,rw ,http .StatusInternalServerError , codersdk.Response {
252- Message :"Internal error fetchingmembers and groups for workspaces." ,
252+ Message :"Internal error fetchingusers and groups for workspaces." ,
253253Detail :err .Error (),
254254})
255255return
@@ -263,7 +263,7 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
263263apiKey .UserID ,
264264workspaces ,
265265data ,
266- memberData ,
266+ userData ,
267267groupData ,
268268)
269269if err != nil {
@@ -2579,7 +2579,7 @@ func convertWorkspaces(
25792579requesterID uuid.UUID ,
25802580workspaces []database.Workspace ,
25812581data workspaceData ,
2582- memberData map [uuid.UUID ]database.OrganizationMembersRow ,
2582+ userData map [uuid.UUID ]database.User ,
25832583groupData map [uuid.UUID ]database.Group ,
25842584) ([]codersdk.Workspace ,error ) {
25852585buildByWorkspaceID := map [uuid.UUID ]codersdk.WorkspaceBuild {}
@@ -2622,7 +2622,7 @@ func convertWorkspaces(
26222622template ,
26232623data .allowRenames ,
26242624appStatus ,
2625- memberData ,
2625+ userData ,
26262626groupData ,
26272627)
26282628if err != nil {
@@ -2644,7 +2644,7 @@ func convertWorkspace(
26442644template database.Template ,
26452645allowRenames bool ,
26462646latestAppStatus codersdk.WorkspaceAppStatus ,
2647- memberData map [uuid.UUID ]database.OrganizationMembersRow ,
2647+ userData map [uuid.UUID ]database.User ,
26482648groupData map [uuid.UUID ]database.Group ,
26492649) (codersdk.Workspace ,error ) {
26502650if requesterID == uuid .Nil {
@@ -2694,7 +2694,7 @@ func convertWorkspace(
26942694appStatus = nil
26952695}
26962696
2697- sharedWith := sharedWorkspaceActors (ctx ,experiments ,logger ,workspace ,memberData ,groupData )
2697+ sharedWith := sharedWorkspaceActors (ctx ,experiments ,logger ,workspace ,userData ,groupData )
26982698
26992699return codersdk.Workspace {
27002700ID :workspace .ID ,
@@ -2744,7 +2744,7 @@ func sharedWorkspaceActors(
27442744experiments codersdk.Experiments ,
27452745logger slog.Logger ,
27462746workspace database.Workspace ,
2747- memberData map [uuid.UUID ]database.OrganizationMembersRow ,
2747+ userData map [uuid.UUID ]database.User ,
27482748groupData map [uuid.UUID ]database.Group ,
27492749)* []codersdk.SharedWorkspaceActor {
27502750if ! experiments .Enabled (codersdk .ExperimentWorkspaceSharing ) {
@@ -2766,11 +2766,9 @@ func sharedWorkspaceActors(
27662766ActorType :codersdk .SharedWorkspaceActorTypeUser ,
27672767Roles : []codersdk.WorkspaceRole {convertToWorkspaceRole (aclEntry .Permissions )},
27682768}
2769-
2770- // Member data is only available if user has access to it
2771- if member ,ok := memberData [userID ];ok {
2772- actor .Name = member .Name
2773- actor .AvatarURL = member .AvatarURL
2769+ if userData != nil {
2770+ actor .Name = userData [userID ].Name
2771+ actor .AvatarURL = userData [userID ].AvatarURL
27742772}
27752773
27762774out = append (out ,actor )
@@ -2789,11 +2787,9 @@ func sharedWorkspaceActors(
27892787ActorType :codersdk .SharedWorkspaceActorTypeGroup ,
27902788Roles : []codersdk.WorkspaceRole {convertToWorkspaceRole (aclEntry .Permissions )},
27912789}
2792-
2793- // Group data is only available if user has access to it
2794- if group ,ok := groupData [groupID ];ok {
2795- actor .Name = group .Name
2796- actor .AvatarURL = group .AvatarURL
2790+ if groupData != nil {
2791+ actor .Name = groupData [groupID ].Name
2792+ actor .AvatarURL = groupData [groupID ].AvatarURL
27972793}
27982794
27992795out = append (out ,actor )
@@ -2950,76 +2946,80 @@ func convertToWorkspaceRole(actions []policy.Action) codersdk.WorkspaceRole {
29502946return codersdk .WorkspaceRoleDeleted
29512947}
29522948
2953- // findWorkspaceMembersAndGroups fetches all organization members and
2954- // groups present in workspaces' ACLs. All workspaces must belong to
2955- // the same organization.
2956- func findWorkspaceMembersAndGroups (
2949+ // findWorkspaceUsersAndGroups fetches all users and groups present in
2950+ // workspaces' ACLs.
2951+ func findWorkspaceUsersAndGroups (
29572952ctx context.Context ,
29582953api * API ,
29592954workspaces []database.Workspace ,
29602955) (
2961- memberData map [uuid.UUID ]database.OrganizationMembersRow ,
2956+ userData map [uuid.UUID ]database.User ,
29622957groupData map [uuid.UUID ]database.Group ,
29632958err error ,
29642959) {
29652960if len (workspaces )== 0 {
2966- return
2961+ return nil , nil , nil
29672962}
29682963
2969- // Get all the group IDs that we need to fetch.
2970- // TODO(geokat): Implement a way to fetch org members by IDs. For
2971- // now we have to fetch all of them even if we only need one.
2964+ // Get all the user IDs and group IDs that we need to fetch
29722965var (
2973- groupIDs []uuid.UUID
2974- fetchMembers bool
2966+ uids []uuid.UUID
2967+ gids []uuid. UUID
29752968)
29762969for _ ,ws := range workspaces {
2977- if ws .OrganizationID != workspaces [0 ].OrganizationID {
2978- return nil ,nil ,xerrors .New ("all workspaces must belong to the same organization" )
2979- }
2980- if len (ws .UserACL )!= 0 {
2981- fetchMembers = true
2970+ // ws.UserACL is a map[id]...
2971+ for id := range ws .UserACL {
2972+ uid ,err := uuid .Parse (id )
2973+ if err != nil {
2974+ api .Logger .Warn (ctx ,"found invalid user uuid in workspace acl" ,slog .Error (err ),slog .F ("workspace_id" ,ws .ID ))
2975+ continue
2976+ }
2977+ uids = append (uids ,uid )
29822978}
29832979for id := range ws .GroupACL {
2984- groupID ,err := uuid .Parse (id )
2980+ gid ,err := uuid .Parse (id )
29852981if err != nil {
29862982api .Logger .Warn (ctx ,"found invalid group uuid in workspace acl" ,slog .Error (err ),slog .F ("workspace_id" ,ws .ID ))
29872983continue
29882984}
2989- groupIDs = append (groupIDs , groupID )
2985+ gids = append (gids , gid )
29902986}
29912987}
29922988
29932989var eg errgroup.Group
29942990
2995- // Fetchorg members
2996- if fetchMembers {
2991+ // Fetchthe users
2992+ if len ( uids ) > 0 {
29972993eg .Go (func () (err error ) {
2998- params := database.OrganizationMembersParams {
2999- OrganizationID :workspaces [0 ].OrganizationID ,
3000- }
3001- members ,err := api .Database .OrganizationMembers (ctx ,params )
3002- if err != nil && ! httpapi .Is404Error (err ) {
3003- return xerrors .Errorf ("get organization members: %w" ,err )
2994+ uids = slice .Unique (uids )
2995+
2996+ // For context see https://github.com/coder/coder/pull/19375
2997+ // nolint:gocritic
2998+ users ,err := api .Database .GetUsersByIDs (dbauthz .AsSystemRestricted (ctx ),uids )
2999+ if err != nil && ! errors .Is (err ,sql .ErrNoRows ) {
3000+ return xerrors .Errorf ("get users by IDs: %w" ,err )
30043001}
3005- memberData = make (map [uuid.UUID ]database.OrganizationMembersRow ,len (members ))
3006- for _ ,member := range members {
3007- memberData [member .OrganizationMember .UserID ]= member
3002+
3003+ userData = make (map [uuid.UUID ]database.User ,len (users ))
3004+ for _ ,user := range users {
3005+ userData [user .ID ]= user
30083006}
30093007return nil
30103008})
30113009}
30123010// Fetch the groups
3013- if len (groupIDs )> 0 {
3011+ if len (gids )> 0 {
30143012eg .Go (func () (err error ) {
3015- groupIDs = slice .Unique (groupIDs )
3013+ gids = slice .Unique (gids )
30163014
3017- groupRows ,err := api .Database .GetGroups (ctx , database.GetGroupsParams {GroupIds :groupIDs })
3018- if err != nil && ! httpapi .Is404Error (err ) {
3015+ // For context see https://github.com/coder/coder/pull/19375
3016+ // nolint:gocritic
3017+ groupRows ,err := api .Database .GetGroups (dbauthz .AsSystemRestricted (ctx ), database.GetGroupsParams {GroupIds :gids })
3018+ if err != nil && ! errors .Is (err ,sql .ErrNoRows ) {
30193019return xerrors .Errorf ("get groups: %w" ,err )
30203020}
30213021
3022- groupData = make (map [uuid.UUID ]database.Group ,len (groupIDs ))
3022+ groupData = make (map [uuid.UUID ]database.Group ,len (groupRows ))
30233023for _ ,groupRow := range groupRows {
30243024groupData [groupRow .Group .ID ]= groupRow .Group
30253025}
@@ -3030,5 +3030,5 @@ func findWorkspaceMembersAndGroups(
30303030return nil ,nil ,err
30313031}
30323032
3033- return memberData ,groupData ,nil
3033+ return userData ,groupData ,nil
30343034}