|
1 | 1 | package coderd
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | +"context" |
4 | 5 | "net/http"
|
5 | 6 |
|
6 | 7 | "github.com/google/uuid"
|
7 |
| - |
8 |
| -"github.com/coder/coder/v2/coderd/database/db2sdk" |
9 |
| -"github.com/coder/coder/v2/coderd/rbac" |
| 8 | +"golang.org/x/xerrors" |
10 | 9 |
|
11 | 10 | "github.com/coder/coder/v2/coderd/database"
|
| 11 | +"github.com/coder/coder/v2/coderd/database/db2sdk" |
12 | 12 | "github.com/coder/coder/v2/coderd/httpapi"
|
13 | 13 | "github.com/coder/coder/v2/coderd/httpmw"
|
| 14 | +"github.com/coder/coder/v2/coderd/rbac" |
14 | 15 | "github.com/coder/coder/v2/codersdk"
|
15 | 16 | )
|
16 | 17 |
|
@@ -41,7 +42,13 @@ func (api *API) listMembers(rw http.ResponseWriter, r *http.Request) {
|
41 | 42 | return
|
42 | 43 | }
|
43 | 44 |
|
44 |
| -httpapi.Write(ctx,rw,http.StatusOK,db2sdk.List(members,convertOrganizationMemberRow)) |
| 45 | +resp,err:=convertOrganizationMemberRows(ctx,api.Database,members) |
| 46 | +iferr!=nil { |
| 47 | +httpapi.InternalServerError(rw,err) |
| 48 | +return |
| 49 | +} |
| 50 | + |
| 51 | +httpapi.Write(ctx,rw,http.StatusOK,resp) |
45 | 52 | }
|
46 | 53 |
|
47 | 54 | // @Summary Assign role to organization member
|
@@ -87,30 +94,94 @@ func (api *API) putMemberRoles(rw http.ResponseWriter, r *http.Request) {
|
87 | 94 | return
|
88 | 95 | }
|
89 | 96 |
|
90 |
| -httpapi.Write(ctx,rw,http.StatusOK,convertOrganizationMember(updatedUser)) |
| 97 | +resp:=convertOrganizationMembers(ctx,api.Database, []database.OrganizationMember{updatedUser}) |
| 98 | +iflen(resp)!=1 { |
| 99 | +httpapi.InternalServerError(rw,xerrors.Errorf("failed to serialize member to response, update still succeeded")) |
| 100 | +return |
| 101 | +} |
| 102 | +httpapi.Write(ctx,rw,http.StatusOK,resp[0]) |
91 | 103 | }
|
92 | 104 |
|
93 |
| -funcconvertOrganizationMember(mem database.OrganizationMember) codersdk.OrganizationMember { |
94 |
| -convertedMember:= codersdk.OrganizationMember{ |
95 |
| -UserID:mem.UserID, |
96 |
| -OrganizationID:mem.OrganizationID, |
97 |
| -CreatedAt:mem.CreatedAt, |
98 |
| -UpdatedAt:mem.UpdatedAt, |
99 |
| -Roles:make([]codersdk.SlimRole,0,len(mem.Roles)), |
| 105 | +// convertOrganizationMembers batches the role lookup to make only 1 sql call |
| 106 | +// We |
| 107 | +funcconvertOrganizationMembers(ctx context.Context,db database.Store,mems []database.OrganizationMember) []codersdk.OrganizationMember { |
| 108 | +converted:=make([]codersdk.OrganizationMember,0,len(mems)) |
| 109 | +roleLookup:=make([]database.NameOrganizationPair,0) |
| 110 | + |
| 111 | +for_,m:=rangemems { |
| 112 | +converted=append(converted, codersdk.OrganizationMember{ |
| 113 | +UserID:m.UserID, |
| 114 | +OrganizationID:m.OrganizationID, |
| 115 | +CreatedAt:m.CreatedAt, |
| 116 | +UpdatedAt:m.UpdatedAt, |
| 117 | +Roles:db2sdk.List(m.Roles,func(rstring) codersdk.SlimRole { |
| 118 | +// If it is a built-in role, no lookups are needed. |
| 119 | +rbacRole,err:=rbac.RoleByName(rbac.RoleIdentifier{Name:r,OrganizationID:m.OrganizationID}) |
| 120 | +iferr==nil { |
| 121 | +returndb2sdk.SlimRole(rbacRole) |
| 122 | +} |
| 123 | + |
| 124 | +// We know the role name and the organization ID. We are missing the |
| 125 | +// display name. Append the lookup parameter, so we can get the display name |
| 126 | +roleLookup=append(roleLookup, database.NameOrganizationPair{ |
| 127 | +Name:r, |
| 128 | +OrganizationID:m.OrganizationID, |
| 129 | +}) |
| 130 | +return codersdk.SlimRole{ |
| 131 | +Name:r, |
| 132 | +DisplayName:"", |
| 133 | +OrganizationID:m.OrganizationID.String(), |
| 134 | +} |
| 135 | +}), |
| 136 | +}) |
100 | 137 | }
|
101 | 138 |
|
102 |
| -for_,roleName:=rangemem.Roles { |
103 |
| -rbacRole,_:=rbac.RoleByName(rbac.RoleIdentifier{Name:roleName,OrganizationID:mem.OrganizationID}) |
104 |
| -convertedMember.Roles=append(convertedMember.Roles,db2sdk.SlimRole(rbacRole)) |
| 139 | +customRoles,err:=db.CustomRoles(ctx, database.CustomRolesParams{ |
| 140 | +LookupRoles:roleLookup, |
| 141 | +ExcludeOrgRoles:false, |
| 142 | +OrganizationID: uuid.UUID{}, |
| 143 | +}) |
| 144 | +iferr!=nil { |
| 145 | +// We are missing the display names, but that is not absolutely required. So just |
| 146 | +// return the converted and the names will be used instead of the display names. |
| 147 | +returnconverted |
| 148 | +} |
| 149 | + |
| 150 | +// Now map the customRoles back to the slimRoles for their display name. |
| 151 | +customRolesMap:=make(map[string]database.CustomRole) |
| 152 | +for_,role:=rangecustomRoles { |
| 153 | +customRolesMap[role.RoleIdentifier().UniqueName()]=role |
| 154 | +} |
| 155 | + |
| 156 | +fori:=rangeconverted { |
| 157 | +forj,role:=rangeconverted[i].Roles { |
| 158 | +ifcr,ok:=customRolesMap[role.UniqueName()];ok { |
| 159 | +converted[i].Roles[j].DisplayName=cr.DisplayName |
| 160 | +} |
| 161 | +} |
105 | 162 | }
|
106 |
| -returnconvertedMember |
| 163 | + |
| 164 | +returnconverted |
107 | 165 | }
|
108 | 166 |
|
109 |
| -funcconvertOrganizationMemberRow(row database.OrganizationMembersRow) codersdk.OrganizationMemberWithName { |
110 |
| -convertedMember:= codersdk.OrganizationMemberWithName{ |
111 |
| -Username:row.Username, |
112 |
| -OrganizationMember:convertOrganizationMember(row.OrganizationMember), |
| 167 | +funcconvertOrganizationMemberRows(ctx context.Context,db database.Store,rows []database.OrganizationMembersRow) ([]codersdk.OrganizationMemberWithName,error) { |
| 168 | +members:=make([]database.OrganizationMember,0) |
| 169 | +for_,row:=rangerows { |
| 170 | +members=append(members,row.OrganizationMember) |
| 171 | +} |
| 172 | + |
| 173 | +convertedMembers:=convertOrganizationMembers(ctx,db,members) |
| 174 | +iflen(convertedMembers)!=len(rows) { |
| 175 | +returnnil,xerrors.Errorf("conversion failed, mismatch slice lengths") |
| 176 | +} |
| 177 | + |
| 178 | +converted:=make([]codersdk.OrganizationMemberWithName,0) |
| 179 | +fori:=rangeconvertedMembers { |
| 180 | +converted=append(converted, codersdk.OrganizationMemberWithName{ |
| 181 | +Username:rows[i].Username, |
| 182 | +OrganizationMember:convertedMembers[i], |
| 183 | +}) |
113 | 184 | }
|
114 | 185 |
|
115 |
| -returnconvertedMember |
| 186 | +returnconverted,nil |
116 | 187 | }
|