@@ -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
@@ -1237,18 +1241,18 @@ type CreateUserRequest struct {
1237
1241
SkipNotifications bool
1238
1242
}
1239
1243
1240
- func (api * API ) CreateUser (ctx context.Context , store database.Store , req CreateUserRequest ) (database.User , uuid. UUID , error ) {
1244
+ func (api * API ) CreateUser (ctx context.Context , store database.Store , req CreateUserRequest ) (database.User , error ) {
1241
1245
// Ensure the username is valid. It's the caller's responsibility to ensure
1242
1246
// the username is valid and unique.
1243
1247
if usernameValid := httpapi .NameValid (req .Username ); usernameValid != nil {
1244
- return database.User {}, uuid . Nil , xerrors .Errorf ("invalid username %q: %w" , req .Username , usernameValid )
1248
+ return database.User {}, xerrors .Errorf ("invalid username %q: %w" , req .Username , usernameValid )
1245
1249
}
1246
1250
1247
1251
var user database.User
1248
1252
err := store .InTx (func (tx database.Store ) error {
1249
1253
orgRoles := make ([]string , 0 )
1250
1254
// Organization is required to know where to allocate the user.
1251
- if req .OrganizationID == uuid . Nil {
1255
+ if len ( req .OrganizationIDs ) == 0 {
1252
1256
return xerrors .Errorf ("organization ID must be provided" )
1253
1257
}
1254
1258
@@ -1293,26 +1297,30 @@ func (api *API) CreateUser(ctx context.Context, store database.Store, req Create
1293
1297
if err != nil {
1294
1298
return xerrors .Errorf ("insert user gitsshkey: %w" , err )
1295
1299
}
1296
- _ , err = tx .InsertOrganizationMember (ctx , database.InsertOrganizationMemberParams {
1297
- OrganizationID : req .OrganizationID ,
1298
- UserID : user .ID ,
1299
- CreatedAt : dbtime .Now (),
1300
- UpdatedAt : dbtime .Now (),
1301
- // By default give them membership to the organization.
1302
- Roles : orgRoles ,
1303
- })
1304
- if err != nil {
1305
- return xerrors .Errorf ("create organization member: %w" , err )
1300
+
1301
+ for _ , orgID := range req .OrganizationIDs {
1302
+ _ , err = tx .InsertOrganizationMember (ctx , database.InsertOrganizationMemberParams {
1303
+ OrganizationID : orgID ,
1304
+ UserID : user .ID ,
1305
+ CreatedAt : dbtime .Now (),
1306
+ UpdatedAt : dbtime .Now (),
1307
+ // By default give them membership to the organization.
1308
+ Roles : orgRoles ,
1309
+ })
1310
+ if err != nil {
1311
+ return xerrors .Errorf ("create organization member for %q: %w" , orgID .String (), err )
1312
+ }
1306
1313
}
1314
+
1307
1315
return nil
1308
1316
}, nil )
1309
1317
if err != nil || req .SkipNotifications {
1310
- return user , req . OrganizationID , err
1318
+ return user , err
1311
1319
}
1312
1320
1313
1321
userAdmins , err := findUserAdmins (ctx , store )
1314
1322
if err != nil {
1315
- return user , req . OrganizationID , xerrors .Errorf ("find user admins: %w" , err )
1323
+ return user , xerrors .Errorf ("find user admins: %w" , err )
1316
1324
}
1317
1325
1318
1326
for _ , u := range userAdmins {
@@ -1325,7 +1333,7 @@ func (api *API) CreateUser(ctx context.Context, store database.Store, req Create
1325
1333
api .Logger .Warn (ctx , "unable to notify about created user" , slog .F ("created_user" , user .Username ), slog .Error (err ))
1326
1334
}
1327
1335
}
1328
- return user , req . OrganizationID , err
1336
+ return user , err
1329
1337
}
1330
1338
1331
1339
// findUserAdmins fetches all users with user admin permission including owners.
0 commit comments