From 4b0a3e88f01be2fbf91763f44be2d48e69c43aa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Samin?= Date: Wed, 15 Mar 2023 16:22:05 +0100 Subject: [PATCH] feat(api,cli): admin can update username (#6508) --- cli/cdsctl/admin_user.go | 32 ++++++++++++++++++++++++++++++++ engine/api/auth.go | 3 +++ engine/api/user.go | 14 +++++++++++++- engine/api/user_test.go | 38 ++++++++++++++++++++++++++++++++++++-- 4 files changed, 84 insertions(+), 3 deletions(-) diff --git a/cli/cdsctl/admin_user.go b/cli/cdsctl/admin_user.go index fede7667f7..c91225c110 100644 --- a/cli/cdsctl/admin_user.go +++ b/cli/cdsctl/admin_user.go @@ -18,9 +18,41 @@ var adminUsersCmd = cli.Command{ func adminUsers() *cobra.Command { return cli.NewCommand(adminUsersCmd, nil, []*cobra.Command{ cli.NewCommand(adminUserSetOrganizationCmd, adminUserSetOrganizationRun, nil), + cli.NewCommand(adminUserRenameCmd, adminUserRenameRun, nil), }) } +var adminUserRenameCmd = cli.Command{ + Name: "rename", + Short: "Rename a given user", + Args: []cli.Arg{ + { + Name: "username", + }, + { + Name: "new-username", + }, + }, +} + +func adminUserRenameRun(v cli.Values) error { + ctx := context.Background() + username := v.GetString("username") + usernameNew := v.GetString("new-username") + + u, err := client.UserGet(ctx, username) + if err != nil { + return err + } + u.Username = usernameNew + if err := client.UserUpdate(ctx, username, u); err != nil { + return err + } + + fmt.Printf("User %q has been renamed to %q\n", username, usernameNew) + return nil +} + var adminUserSetOrganizationCmd = cli.Command{ Name: "set-organization", Short: "Set organization for given user", diff --git a/engine/api/auth.go b/engine/api/auth.go index 330d012bd1..e3dcf18925 100644 --- a/engine/api/auth.go +++ b/engine/api/auth.go @@ -128,6 +128,9 @@ func (api *API) postAuthSigninHandler() service.Handler { return err } + ctx = context.WithValue(ctx, cdslog.AuthUsername, userInfo.Username) + SetTracker(w, cdslog.AuthUsername, userInfo.Username) + tx, err := api.mustDB().Begin() if err != nil { return sdk.WithStack(err) diff --git a/engine/api/user.go b/engine/api/user.go index 5ad76ac3ce..6d06be3eda 100644 --- a/engine/api/user.go +++ b/engine/api/user.go @@ -83,6 +83,18 @@ func (api *API) putUserHandler() service.Handler { } newUser := *oldUser + + if oldUser.Username != data.Username { + // Only an admin can change the username + if isAdmin(ctx) { + trackSudo(ctx, w) + log.Info(ctx, "putUserHandler> %s change username of user %s from %s to %s", consumer.AuthConsumerUser.AuthentifiedUserID, oldUser.ID, oldUser.Username, data.Username) + newUser.Username = data.Username + } else { + return sdk.WithStack(sdk.ErrForbidden) + } + } + newUser.Fullname = data.Fullname // Only an admin can change the ring of a user @@ -116,7 +128,7 @@ func (api *API) putUserHandler() service.Handler { } newUser.Ring = data.Ring - log.Debug(ctx, "putUserHandler> %s change ring of user %s from %s to %s", consumer.AuthConsumerUser.AuthentifiedUserID, oldUser.ID, oldUser.Ring, newUser.Ring) + log.Info(ctx, "putUserHandler> %s change ring of user %s from %s to %s", consumer.AuthConsumerUser.AuthentifiedUserID, oldUser.ID, oldUser.Ring, newUser.Ring) } if err := user.Update(ctx, tx, &newUser); err != nil { diff --git a/engine/api/user_test.go b/engine/api/user_test.go index 3e8a1286c1..fc5c6a21a8 100644 --- a/engine/api/user_test.go +++ b/engine/api/user_test.go @@ -81,11 +81,11 @@ func Test_putUserHandler(t *testing.T) { ExpectedStatus int }{ { - Name: "A lambda user can't change username but can change fullname", + Name: "A lambda user can change fullname", JWT: jwtInitialRaw, TargetUsername: initial.Username, Data: sdk.AuthentifiedUser{ - Username: sdk.RandomString(10), + Username: initial.Username, Fullname: initialNewFullname, Ring: initial.Ring, }, @@ -97,6 +97,23 @@ func Test_putUserHandler(t *testing.T) { }, ExpectedStatus: http.StatusOK, }, + { + Name: "A lambda user can't change username", + JWT: jwtInitialRaw, + TargetUsername: initial.Username, + Data: sdk.AuthentifiedUser{ + Username: sdk.RandomString(10), + Fullname: initialNewFullname, + Ring: initial.Ring, + }, + Expected: sdk.AuthentifiedUser{ + Username: initial.Username, + Fullname: initialNewFullname, + Ring: initial.Ring, + Organization: "default", + }, + ExpectedStatus: http.StatusForbidden, + }, { Name: "A lambda user can't change its ring", JWT: jwtInitialRaw, @@ -190,6 +207,23 @@ func Test_putUserHandler(t *testing.T) { }, ExpectedStatus: http.StatusForbidden, }, + { + Name: "A admin user can change username", + JWT: jwtAdmin2Raw, + TargetUsername: initial.Username, + Data: sdk.AuthentifiedUser{ + Username: initial.Username + ".updated", + Fullname: initialNewFullname, + Ring: sdk.UserRingMaintainer, + }, + Expected: sdk.AuthentifiedUser{ + Username: initial.Username + ".updated", + Fullname: initialNewFullname, + Ring: sdk.UserRingMaintainer, + Organization: "default", + }, + ExpectedStatus: http.StatusOK, + }, } o := sdk.Organization{Name: "my-org"}