Skip to content

Commit 36efcef

Browse files
authored
Merge branch 'main' into margins/presleyp/978
2 parents 8f55513 + 021e4cd commit 36efcef

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1419
-361
lines changed

coderd/audit/table.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ var AuditableResources = auditMap(map[any]map[string]Action{
4242
"created_at": ActionIgnore, // Never changes.
4343
"updated_at": ActionIgnore, // Changes, but is implicit and not helpful in a diff.
4444
"status": ActionTrack, // A user can update another user status
45+
"rbac_roles": ActionTrack, // A user's roles are mutable
4546
},
4647
&database.Workspace{}: {
4748
"id": ActionIgnore, // Never changes.

coderd/coderd.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,14 @@ func New(options *Options) (http.Handler, func()) {
120120
r.Get("/", api.workspacesByOwner)
121121
})
122122
})
123+
r.Route("/members", func(r chi.Router) {
124+
r.Route("/{user}", func(r chi.Router) {
125+
r.Use(
126+
httpmw.ExtractUserParam(options.Database),
127+
)
128+
r.Put("/roles", api.putMemberRoles)
129+
})
130+
})
123131
})
124132
r.Route("/parameters/{scope}/{id}", func(r chi.Router) {
125133
r.Use(apiKeyMiddleware)
@@ -183,6 +191,10 @@ func New(options *Options) (http.Handler, func()) {
183191
r.Get("/", api.userByName)
184192
r.Put("/profile", api.putUserProfile)
185193
r.Put("/suspend", api.putUserSuspend)
194+
// TODO: @emyrk Might want to move these to a /roles group instead of /user.
195+
// As we include more roles like org roles, it makes less sense to scope these here.
196+
r.Put("/roles", api.putUserRoles)
197+
r.Get("/roles", api.userRoles)
186198
r.Get("/organizations", api.organizationsByUser)
187199
r.Post("/organizations", api.postOrganizationsByUser)
188200
r.Post("/keys", api.postAPIKey)

coderd/database/databasefake/databasefake.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,16 @@ func (q *fakeQuerier) GetUsers(_ context.Context, params database.GetUsersParams
212212
users = tmp
213213
}
214214

215+
if params.Status != "" {
216+
usersFilteredByStatus := make([]database.User, 0, len(users))
217+
for i, user := range users {
218+
if params.Status == string(user.Status) {
219+
usersFilteredByStatus = append(usersFilteredByStatus, users[i])
220+
}
221+
}
222+
users = usersFilteredByStatus
223+
}
224+
215225
if params.OffsetOpt > 0 {
216226
if int(params.OffsetOpt) > len(users)-1 {
217227
return []database.User{}, nil
@@ -225,6 +235,7 @@ func (q *fakeQuerier) GetUsers(_ context.Context, params database.GetUsersParams
225235
}
226236
users = users[:params.LimitOpt]
227237
}
238+
228239
tmp := make([]database.User, len(users))
229240
copy(tmp, users)
230241

@@ -732,6 +743,43 @@ func (q *fakeQuerier) GetOrganizationIDsByMemberIDs(_ context.Context, ids []uui
732743
return getOrganizationIDsByMemberIDRows, nil
733744
}
734745

746+
func (q *fakeQuerier) GetOrganizationMembershipsByUserID(_ context.Context, userID uuid.UUID) ([]database.OrganizationMember, error) {
747+
q.mutex.RLock()
748+
defer q.mutex.RUnlock()
749+
750+
var memberships []database.OrganizationMember
751+
for _, organizationMember := range q.organizationMembers {
752+
mem := organizationMember
753+
if mem.UserID != userID {
754+
continue
755+
}
756+
memberships = append(memberships, mem)
757+
}
758+
return memberships, nil
759+
}
760+
761+
func (q *fakeQuerier) UpdateMemberRoles(_ context.Context, arg database.UpdateMemberRolesParams) (database.OrganizationMember, error) {
762+
for i, mem := range q.organizationMembers {
763+
if mem.UserID == arg.UserID && mem.OrganizationID == arg.OrgID {
764+
uniqueRoles := make([]string, 0, len(arg.GrantedRoles))
765+
exist := make(map[string]struct{})
766+
for _, r := range arg.GrantedRoles {
767+
if _, ok := exist[r]; ok {
768+
continue
769+
}
770+
exist[r] = struct{}{}
771+
uniqueRoles = append(uniqueRoles, r)
772+
}
773+
sort.Strings(uniqueRoles)
774+
775+
mem.Roles = uniqueRoles
776+
q.organizationMembers[i] = mem
777+
return mem, nil
778+
}
779+
}
780+
return database.OrganizationMember{}, sql.ErrNoRows
781+
}
782+
735783
func (q *fakeQuerier) GetProvisionerDaemons(_ context.Context) ([]database.ProvisionerDaemon, error) {
736784
q.mutex.RLock()
737785
defer q.mutex.RUnlock()
@@ -1162,11 +1210,42 @@ func (q *fakeQuerier) InsertUser(_ context.Context, arg database.InsertUserParam
11621210
UpdatedAt: arg.UpdatedAt,
11631211
Username: arg.Username,
11641212
Status: database.UserStatusActive,
1213+
RBACRoles: arg.RBACRoles,
11651214
}
11661215
q.users = append(q.users, user)
11671216
return user, nil
11681217
}
11691218

1219+
func (q *fakeQuerier) UpdateUserRoles(_ context.Context, arg database.UpdateUserRolesParams) (database.User, error) {
1220+
q.mutex.Lock()
1221+
defer q.mutex.Unlock()
1222+
1223+
for index, user := range q.users {
1224+
if user.ID != arg.ID {
1225+
continue
1226+
}
1227+
1228+
// Set new roles
1229+
user.RBACRoles = arg.GrantedRoles
1230+
// Remove duplicates and sort
1231+
uniqueRoles := make([]string, 0, len(user.RBACRoles))
1232+
exist := make(map[string]struct{})
1233+
for _, r := range user.RBACRoles {
1234+
if _, ok := exist[r]; ok {
1235+
continue
1236+
}
1237+
exist[r] = struct{}{}
1238+
uniqueRoles = append(uniqueRoles, r)
1239+
}
1240+
sort.Strings(uniqueRoles)
1241+
user.RBACRoles = uniqueRoles
1242+
1243+
q.users[index] = user
1244+
return user, nil
1245+
}
1246+
return database.User{}, sql.ErrNoRows
1247+
}
1248+
11701249
func (q *fakeQuerier) UpdateUserProfile(_ context.Context, arg database.UpdateUserProfileParams) (database.User, error) {
11711250
q.mutex.Lock()
11721251
defer q.mutex.Unlock()

coderd/database/dump.sql

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE ONLY users
2+
DROP COLUMN IF EXISTS rbac_roles;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
ALTER TABLE ONLY users
2+
ADD COLUMN IF NOT EXISTS rbac_roles text[] DEFAULT '{}' NOT NULL;
3+
4+
-- All users are site members. So give them the standard role.
5+
-- Also give them membership to the first org we retrieve. We should only have
6+
-- 1 organization at this point in the product.
7+
UPDATE
8+
users
9+
SET
10+
rbac_roles = ARRAY ['member', 'organization-member:' || (SELECT id FROM organizations LIMIT 1)];
11+
12+
-- Give the first user created the admin role
13+
UPDATE
14+
users
15+
SET
16+
rbac_roles = rbac_roles || ARRAY ['admin']
17+
WHERE
18+
id = (SELECT id FROM users ORDER BY created_at ASC LIMIT 1)

coderd/database/models.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/querier.go

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy