@@ -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 ,
@@ -1345,6 +1331,7 @@ type CreateUserRequest struct {
1345
1331
LoginType database.LoginType
1346
1332
SkipNotifications bool
1347
1333
accountCreatorName string
1334
+ RBACRoles []string
1348
1335
}
1349
1336
1350
1337
func (api * API )CreateUser (ctx context.Context ,store database.Store ,req CreateUserRequest ) (database.User ,error ) {
@@ -1354,6 +1341,13 @@ func (api *API) CreateUser(ctx context.Context, store database.Store, req Create
1354
1341
return database.User {},xerrors .Errorf ("invalid username %q: %w" ,req .Username ,usernameValid )
1355
1342
}
1356
1343
1344
+ // If the caller didn't specify rbac roles, default to
1345
+ // a member of the site.
1346
+ rbacRoles := []string {}
1347
+ if req .RBACRoles != nil {
1348
+ rbacRoles = req .RBACRoles
1349
+ }
1350
+
1357
1351
var user database.User
1358
1352
err := store .InTx (func (tx database.Store )error {
1359
1353
orgRoles := make ([]string ,0 )
@@ -1370,10 +1364,9 @@ func (api *API) CreateUser(ctx context.Context, store database.Store, req Create
1370
1364
CreatedAt :dbtime .Now (),
1371
1365
UpdatedAt :dbtime .Now (),
1372
1366
HashedPassword : []byte {},
1373
- // All new users are defaulted to members of the site.
1374
- RBACRoles : []string {},
1375
- LoginType :req .LoginType ,
1376
- Status :status ,
1367
+ RBACRoles :rbacRoles ,
1368
+ LoginType :req .LoginType ,
1369
+ Status :status ,
1377
1370
}
1378
1371
// If a user signs up with OAuth, they can have no password!
1379
1372
if req .Password != "" {
@@ -1431,6 +1424,10 @@ func (api *API) CreateUser(ctx context.Context, store database.Store, req Create
1431
1424
}
1432
1425
1433
1426
for _ ,u := range userAdmins {
1427
+ if u .ID == user .ID {
1428
+ // If the new user is an admin, don't notify them about themselves.
1429
+ continue
1430
+ }
1434
1431
if _ ,err := api .NotificationsEnqueuer .EnqueueWithData (
1435
1432
// nolint:gocritic // Need notifier actor to enqueue notifications
1436
1433
dbauthz .AsNotifier (ctx ),