@@ -186,13 +186,13 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
186
186
}
187
187
188
188
//nolint:gocritic // needed to create first user
189
- user , organizationID , err := api .CreateUser (dbauthz .AsSystemRestricted (ctx ), api .Database , CreateUserRequest {
189
+ user , err := api .CreateUser (dbauthz .AsSystemRestricted (ctx ), api .Database , CreateUserRequest {
190
190
CreateUserRequest : codersdk.CreateUserRequest {
191
- Email : createUser .Email ,
192
- Username : createUser .Username ,
193
- Name : createUser .Name ,
194
- Password : createUser .Password ,
195
- OrganizationID : defaultOrg .ID ,
191
+ Email : createUser .Email ,
192
+ Username : createUser .Username ,
193
+ Name : createUser .Name ,
194
+ Password : createUser .Password ,
195
+ OrganizationIDs : []uuid. UUID { defaultOrg .ID } ,
196
196
},
197
197
LoginType : database .LoginTypePassword ,
198
198
})
@@ -240,7 +240,7 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
240
240
241
241
httpapi .Write (ctx , rw , http .StatusCreated , codersdk.CreateFirstUserResponse {
242
242
UserID : user .ID ,
243
- OrganizationID : organizationID ,
243
+ OrganizationID : defaultOrg . ID ,
244
244
})
245
245
}
246
246
@@ -386,6 +386,20 @@ func (api *API) postUser(rw http.ResponseWriter, r *http.Request) {
386
386
return
387
387
}
388
388
389
+ if len (req .OrganizationIDs ) == 0 {
390
+ httpapi .Write (ctx , rw , http .StatusBadRequest , codersdk.Response {
391
+ Message : fmt .Sprintf ("No organization specified to place the user as a member of. It is required to specify at least one organization id to place the user in." ),
392
+ Detail : fmt .Sprintf ("required at least 1 value for the array 'organization_ids'" ),
393
+ Validations : []codersdk.ValidationError {
394
+ {
395
+ Field : "organization_ids" ,
396
+ Detail : "Missing values, this cannot be empty" ,
397
+ },
398
+ },
399
+ })
400
+ return
401
+ }
402
+
389
403
// TODO: @emyrk Authorize the organization create if the createUser will do that.
390
404
391
405
_ , err := api .Database .GetUserByEmailOrUsername (ctx , database.GetUserByEmailOrUsernameParams {
@@ -406,44 +420,34 @@ func (api *API) postUser(rw http.ResponseWriter, r *http.Request) {
406
420
return
407
421
}
408
422
409
- if req .OrganizationID != uuid .Nil {
410
- // If an organization was provided, make sure it exists.
411
- _ , err := api .Database .GetOrganizationByID (ctx , req .OrganizationID )
412
- if err != nil {
413
- if httpapi .Is404Error (err ) {
423
+ // If an organization was provided, make sure it exists.
424
+ for i , orgID := range req .OrganizationIDs {
425
+ var orgErr error
426
+ if orgID != uuid .Nil {
427
+ _ , orgErr = api .Database .GetOrganizationByID (ctx , orgID )
428
+ } else {
429
+ var defaultOrg database.Organization
430
+ defaultOrg , orgErr = api .Database .GetDefaultOrganization (ctx )
431
+ if orgErr == nil {
432
+ // converts uuid.Nil --> default org.ID
433
+ req .OrganizationIDs [i ] = defaultOrg .ID
434
+ }
435
+ }
436
+ if orgErr != nil {
437
+ if httpapi .Is404Error (orgErr ) {
414
438
httpapi .Write (ctx , rw , http .StatusNotFound , codersdk.Response {
415
- Message : fmt .Sprintf ("Organization does not exist with the provided id %q." , req . OrganizationID ),
439
+ Message : fmt .Sprintf ("Organization does not exist with the provided id %q." , orgID ),
416
440
})
417
441
return
418
442
}
419
443
420
444
httpapi .Write (ctx , rw , http .StatusInternalServerError , codersdk.Response {
421
445
Message : "Internal error fetching organization." ,
422
- Detail : err .Error (),
423
- })
424
- return
425
- }
426
- } else {
427
- // If no organization is provided, add the user to the default
428
- defaultOrg , err := api .Database .GetDefaultOrganization (ctx )
429
- if err != nil {
430
- if httpapi .Is404Error (err ) {
431
- httpapi .Write (ctx , rw , http .StatusNotFound ,
432
- codersdk.Response {
433
- Message : "Resource not found or you do not have access to this resource" ,
434
- Detail : "Organization not found" ,
435
- },
436
- )
437
- return
438
- }
439
- httpapi .Write (ctx , rw , http .StatusInternalServerError , codersdk.Response {
440
- Message : "Internal error fetching orgs." ,
441
- Detail : err .Error (),
446
+ Detail : orgErr .Error (),
442
447
})
443
448
return
444
449
}
445
450
446
- req .OrganizationID = defaultOrg .ID
447
451
}
448
452
449
453
var loginType database.LoginType
@@ -480,7 +484,7 @@ func (api *API) postUser(rw http.ResponseWriter, r *http.Request) {
480
484
return
481
485
}
482
486
483
- user , _ , err := api .CreateUser (ctx , api .Database , CreateUserRequest {
487
+ user , err := api .CreateUser (ctx , api .Database , CreateUserRequest {
484
488
CreateUserRequest : req ,
485
489
LoginType : loginType ,
486
490
})
@@ -505,7 +509,7 @@ func (api *API) postUser(rw http.ResponseWriter, r *http.Request) {
505
509
Users : []telemetry.User {telemetry .ConvertUser (user )},
506
510
})
507
511
508
- httpapi .Write (ctx , rw , http .StatusCreated , db2sdk .User (user , []uuid. UUID { req .OrganizationID } ))
512
+ httpapi .Write (ctx , rw , http .StatusCreated , db2sdk .User (user , req .OrganizationIDs ))
509
513
}
510
514
511
515
// @Summary Delete user
@@ -1285,18 +1289,18 @@ type CreateUserRequest struct {
1285
1289
SkipNotifications bool
1286
1290
}
1287
1291
1288
- func (api * API ) CreateUser (ctx context.Context , store database.Store , req CreateUserRequest ) (database.User , uuid. UUID , error ) {
1292
+ func (api * API ) CreateUser (ctx context.Context , store database.Store , req CreateUserRequest ) (database.User , error ) {
1289
1293
// Ensure the username is valid. It's the caller's responsibility to ensure
1290
1294
// the username is valid and unique.
1291
1295
if usernameValid := httpapi .NameValid (req .Username ); usernameValid != nil {
1292
- return database.User {}, uuid . Nil , xerrors .Errorf ("invalid username %q: %w" , req .Username , usernameValid )
1296
+ return database.User {}, xerrors .Errorf ("invalid username %q: %w" , req .Username , usernameValid )
1293
1297
}
1294
1298
1295
1299
var user database.User
1296
1300
err := store .InTx (func (tx database.Store ) error {
1297
1301
orgRoles := make ([]string , 0 )
1298
1302
// Organization is required to know where to allocate the user.
1299
- if req .OrganizationID == uuid . Nil {
1303
+ if len ( req .OrganizationIDs ) == 0 {
1300
1304
return xerrors .Errorf ("organization ID must be provided" )
1301
1305
}
1302
1306
@@ -1341,26 +1345,30 @@ func (api *API) CreateUser(ctx context.Context, store database.Store, req Create
1341
1345
if err != nil {
1342
1346
return xerrors .Errorf ("insert user gitsshkey: %w" , err )
1343
1347
}
1344
- _ , err = tx .InsertOrganizationMember (ctx , database.InsertOrganizationMemberParams {
1345
- OrganizationID : req .OrganizationID ,
1346
- UserID : user .ID ,
1347
- CreatedAt : dbtime .Now (),
1348
- UpdatedAt : dbtime .Now (),
1349
- // By default give them membership to the organization.
1350
- Roles : orgRoles ,
1351
- })
1352
- if err != nil {
1353
- return xerrors .Errorf ("create organization member: %w" , err )
1348
+
1349
+ for _ , orgID := range req .OrganizationIDs {
1350
+ _ , err = tx .InsertOrganizationMember (ctx , database.InsertOrganizationMemberParams {
1351
+ OrganizationID : orgID ,
1352
+ UserID : user .ID ,
1353
+ CreatedAt : dbtime .Now (),
1354
+ UpdatedAt : dbtime .Now (),
1355
+ // By default give them membership to the organization.
1356
+ Roles : orgRoles ,
1357
+ })
1358
+ if err != nil {
1359
+ return xerrors .Errorf ("create organization member for %q: %w" , orgID .String (), err )
1360
+ }
1354
1361
}
1362
+
1355
1363
return nil
1356
1364
}, nil )
1357
1365
if err != nil || req .SkipNotifications {
1358
- return user , req . OrganizationID , err
1366
+ return user , err
1359
1367
}
1360
1368
1361
1369
userAdmins , err := findUserAdmins (ctx , store )
1362
1370
if err != nil {
1363
- return user , req . OrganizationID , xerrors .Errorf ("find user admins: %w" , err )
1371
+ return user , xerrors .Errorf ("find user admins: %w" , err )
1364
1372
}
1365
1373
1366
1374
for _ , u := range userAdmins {
@@ -1373,7 +1381,7 @@ func (api *API) CreateUser(ctx context.Context, store database.Store, req Create
1373
1381
api .Logger .Warn (ctx , "unable to notify about created user" , slog .F ("created_user" , user .Username ), slog .Error (err ))
1374
1382
}
1375
1383
}
1376
- return user , req . OrganizationID , err
1384
+ return user , err
1377
1385
}
1378
1386
1379
1387
// findUserAdmins fetches all users with user admin permission including owners.
0 commit comments