@@ -118,6 +118,8 @@ func (api *API) firstUser(rw http.ResponseWriter, r *http.Request) {
118
118
// @Success 201 {object} codersdk.CreateFirstUserResponse
119
119
// @Router /users/first [post]
120
120
func (api * API ) postFirstUser (rw http.ResponseWriter , r * http.Request ) {
121
+ // The first user can also be created via oidc, so if making changes to the flow,
122
+ // ensure that the oidc flow is also updated.
121
123
ctx := r .Context ()
122
124
var createUser codersdk.CreateFirstUserRequest
123
125
if ! httpapi .Read (ctx , rw , r , & createUser ) {
@@ -198,6 +200,7 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
198
200
OrganizationIDs : []uuid.UUID {defaultOrg .ID },
199
201
},
200
202
LoginType : database .LoginTypePassword ,
203
+ RBACRoles : []string {rbac .RoleOwner ().String ()},
201
204
accountCreatorName : "coder" ,
202
205
})
203
206
if err != nil {
@@ -225,23 +228,6 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
225
228
Users : []telemetry.User {telemetryUser },
226
229
})
227
230
228
- // TODO: @emyrk this currently happens outside the database tx used to create
229
- // the user. Maybe I add this ability to grant roles in the createUser api
230
- // and add some rbac bypass when calling api functions this way??
231
- // Add the admin role to this first user.
232
- //nolint:gocritic // needed to create first user
233
- _ , err = api .Database .UpdateUserRoles (dbauthz .AsSystemRestricted (ctx ), database.UpdateUserRolesParams {
234
- GrantedRoles : []string {rbac .RoleOwner ().String ()},
235
- ID : user .ID ,
236
- })
237
- if err != nil {
238
- httpapi .Write (ctx , rw , http .StatusInternalServerError , codersdk.Response {
239
- Message : "Internal error updating user's roles." ,
240
- Detail : err .Error (),
241
- })
242
- return
243
- }
244
-
245
231
httpapi .Write (ctx , rw , http .StatusCreated , codersdk.CreateFirstUserResponse {
246
232
UserID : user .ID ,
247
233
OrganizationID : defaultOrg .ID ,
@@ -1351,6 +1337,7 @@ type CreateUserRequest struct {
1351
1337
LoginType database.LoginType
1352
1338
SkipNotifications bool
1353
1339
accountCreatorName string
1340
+ RBACRoles []string
1354
1341
}
1355
1342
1356
1343
func (api * API ) CreateUser (ctx context.Context , store database.Store , req CreateUserRequest ) (database.User , error ) {
@@ -1360,6 +1347,13 @@ func (api *API) CreateUser(ctx context.Context, store database.Store, req Create
1360
1347
return database.User {}, xerrors .Errorf ("invalid username %q: %w" , req .Username , usernameValid )
1361
1348
}
1362
1349
1350
+ // If the caller didn't specify rbac roles, default to
1351
+ // a member of the site.
1352
+ rbacRoles := []string {}
1353
+ if req .RBACRoles != nil {
1354
+ rbacRoles = req .RBACRoles
1355
+ }
1356
+
1363
1357
var user database.User
1364
1358
err := store .InTx (func (tx database.Store ) error {
1365
1359
orgRoles := make ([]string , 0 )
@@ -1376,10 +1370,9 @@ func (api *API) CreateUser(ctx context.Context, store database.Store, req Create
1376
1370
CreatedAt : dbtime .Now (),
1377
1371
UpdatedAt : dbtime .Now (),
1378
1372
HashedPassword : []byte {},
1379
- // All new users are defaulted to members of the site.
1380
- RBACRoles : []string {},
1381
- LoginType : req .LoginType ,
1382
- Status : status ,
1373
+ RBACRoles : rbacRoles ,
1374
+ LoginType : req .LoginType ,
1375
+ Status : status ,
1383
1376
}
1384
1377
// If a user signs up with OAuth, they can have no password!
1385
1378
if req .Password != "" {
@@ -1437,6 +1430,10 @@ func (api *API) CreateUser(ctx context.Context, store database.Store, req Create
1437
1430
}
1438
1431
1439
1432
for _ , u := range userAdmins {
1433
+ if u .ID == user .ID {
1434
+ // If the new user is an admin, don't notify them about themselves.
1435
+ continue
1436
+ }
1440
1437
if _ , err := api .NotificationsEnqueuer .EnqueueWithData (
1441
1438
// nolint:gocritic // Need notifier actor to enqueue notifications
1442
1439
dbauthz .AsNotifier (ctx ),
0 commit comments