@@ -121,6 +121,8 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
121121data .templates [0 ],
122122api .Options .AllowWorkspaceRenames ,
123123appStatus ,
124+ nil ,
125+ nil ,
124126)
125127if err != nil {
126128httpapi .Write (ctx ,rw ,http .StatusInternalServerError , codersdk.Response {
@@ -169,7 +171,6 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
169171filter .OwnerUsername = ""
170172}
171173
172- // Workspaces do not have ACL columns.
173174prepared ,err := api .HTTPAuth .AuthorizeSQLFilter (r ,policy .ActionRead ,rbac .ResourceWorkspace .Type )
174175if err != nil {
175176httpapi .Write (ctx ,rw ,http .StatusInternalServerError , codersdk.Response {
@@ -237,7 +238,30 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
237238return
238239}
239240
240- wss ,err := convertWorkspaces (api .Experiments ,apiKey .UserID ,workspaces ,data )
241+ var (
242+ userData map [string ]database.User
243+ groupData map [string ]database.Group
244+ )
245+ if api .Experiments .Enabled (codersdk .ExperimentWorkspaceSharing ) {
246+ var err error
247+ userData ,groupData ,err = findWorkspaceUsersAndGroups (ctx ,api ,workspaces )
248+ if err != nil {
249+ httpapi .Write (ctx ,rw ,http .StatusInternalServerError , codersdk.Response {
250+ Message :"Internal error fetching users and groups for workspaces." ,
251+ Detail :err .Error (),
252+ })
253+ return
254+ }
255+ }
256+
257+ wss ,err := convertWorkspaces (
258+ api .Experiments ,
259+ apiKey .UserID ,
260+ workspaces ,
261+ data ,
262+ userData ,
263+ groupData ,
264+ )
241265if err != nil {
242266httpapi .Write (ctx ,rw ,http .StatusInternalServerError , codersdk.Response {
243267Message :"Internal error converting workspaces." ,
@@ -334,6 +358,8 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
334358data .templates [0 ],
335359api .Options .AllowWorkspaceRenames ,
336360appStatus ,
361+ nil ,
362+ nil ,
337363)
338364if err != nil {
339365httpapi .Write (ctx ,rw ,http .StatusInternalServerError , codersdk.Response {
@@ -863,6 +889,8 @@ func createWorkspace(
863889template ,
864890api .Options .AllowWorkspaceRenames ,
865891codersdk.WorkspaceAppStatus {},
892+ nil ,
893+ nil ,
866894)
867895if err != nil {
868896return codersdk.Workspace {},httperror .NewResponseError (http .StatusInternalServerError , codersdk.Response {
@@ -1507,6 +1535,8 @@ func (api *API) putWorkspaceDormant(rw http.ResponseWriter, r *http.Request) {
15071535data .templates [0 ],
15081536api .Options .AllowWorkspaceRenames ,
15091537appStatus ,
1538+ nil ,
1539+ nil ,
15101540)
15111541if err != nil {
15121542httpapi .Write (ctx ,rw ,http .StatusInternalServerError , codersdk.Response {
@@ -2085,6 +2115,8 @@ func (api *API) watchWorkspace(
20852115data .templates [0 ],
20862116api .Options .AllowWorkspaceRenames ,
20872117appStatus ,
2118+ nil ,
2119+ nil ,
20882120)
20892121if err != nil {
20902122_ = sendEvent (codersdk.ServerSentEvent {
@@ -2533,6 +2565,8 @@ func convertWorkspaces(
25332565requesterID uuid.UUID ,
25342566workspaces []database.Workspace ,
25352567data workspaceData ,
2568+ userData map [string ]database.User ,
2569+ groupData map [string ]database.Group ,
25362570) ([]codersdk.Workspace ,error ) {
25372571buildByWorkspaceID := map [uuid.UUID ]codersdk.WorkspaceBuild {}
25382572for _ ,workspaceBuild := range data .builds {
@@ -2572,6 +2606,8 @@ func convertWorkspaces(
25722606template ,
25732607data .allowRenames ,
25742608appStatus ,
2609+ userData ,
2610+ groupData ,
25752611)
25762612if err != nil {
25772613return nil ,xerrors .Errorf ("convert workspace: %w" ,err )
@@ -2590,6 +2626,8 @@ func convertWorkspace(
25902626template database.Template ,
25912627allowRenames bool ,
25922628latestAppStatus codersdk.WorkspaceAppStatus ,
2629+ userData map [string ]database.User ,
2630+ groupData map [string ]database.Group ,
25932631) (codersdk.Workspace ,error ) {
25942632if requesterID == uuid .Nil {
25952633return codersdk.Workspace {},xerrors .Errorf ("developer error: requesterID cannot be uuid.Nil!" )
@@ -2832,3 +2870,72 @@ func convertToWorkspaceRole(actions []policy.Action) codersdk.WorkspaceRole {
28322870
28332871return codersdk .WorkspaceRoleDeleted
28342872}
2873+
2874+ // findWorkspaceUsersAndGroups fetches all users and groups present in
2875+ // workspaces' ACLs.
2876+ func findWorkspaceUsersAndGroups (
2877+ ctx context.Context ,
2878+ api * API ,
2879+ workspaces []database.Workspace ,
2880+ ) (
2881+ userData map [string ]database.User ,
2882+ groupData map [string ]database.Group ,
2883+ err error ,
2884+ ) {
2885+ // Get all the user IDs and group IDs that we need to fetch
2886+ var (
2887+ uids []uuid.UUID
2888+ gids []uuid.UUID
2889+ )
2890+ for _ ,ws := range workspaces {
2891+ // ws.UserACL is a map[id]...
2892+ for id := range ws .UserACL {
2893+ uid ,err := uuid .Parse (id )
2894+ if err != nil {
2895+ api .Logger .Warn (ctx ,"found invalid user uuid in workspace acl" ,slog .Error (err ),slog .F ("workspace_id" ,ws .ID ))
2896+ continue
2897+ }
2898+ uids = append (uids ,uid )
2899+ }
2900+ for id := range ws .GroupACL {
2901+ gid ,err := uuid .Parse (id )
2902+ if err != nil {
2903+ api .Logger .Warn (ctx ,"found invalid group uuid in workspace acl" ,slog .Error (err ),slog .F ("workspace_id" ,ws .ID ))
2904+ continue
2905+ }
2906+ gids = append (gids ,gid )
2907+ }
2908+ }
2909+
2910+ // Fetch the users
2911+ if uids != nil {
2912+ uids = slice .Unique (uids )
2913+
2914+ users ,err := api .Database .GetUsersByIDs (ctx ,uids )
2915+ if err != nil && ! errors .Is (err ,sql .ErrNoRows ) {
2916+ return nil ,nil ,xerrors .Errorf ("get users by IDs: %w" ,err )
2917+ }
2918+
2919+ userData = make (map [string ]database.User ,len (uids ))
2920+ for _ ,user := range users {
2921+ userData [user .ID .String ()]= user
2922+ }
2923+ }
2924+
2925+ // Fetch the groups
2926+ if gids != nil {
2927+ gids = slice .Unique (gids )
2928+
2929+ groupRows ,err := api .Database .GetGroups (ctx , database.GetGroupsParams {GroupIds :gids })
2930+ if err != nil && ! errors .Is (err ,sql .ErrNoRows ) {
2931+ return nil ,nil ,xerrors .Errorf ("get groups: %w" ,err )
2932+ }
2933+
2934+ groupData = make (map [string ]database.Group ,len (gids ))
2935+ for _ ,groupRow := range groupRows {
2936+ groupData [groupRow .Group .ID .String ()]= groupRow .Group
2937+ }
2938+ }
2939+
2940+ return userData ,groupData ,nil
2941+ }