From 363a51ee2f5489f0874944c48211dcb7cce3ba13 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Mon, 6 Feb 2023 14:54:00 -0500 Subject: [PATCH 01/21] add user rename endpoint to admin api --- modules/structs/user.go | 9 ++++ routers/api/v1/admin/user.go | 83 ++++++++++++++++++++++++++++++++++++ routers/api/v1/api.go | 1 + 3 files changed, 93 insertions(+) diff --git a/modules/structs/user.go b/modules/structs/user.go index c5e96f335690..fde62ae85796 100644 --- a/modules/structs/user.go +++ b/modules/structs/user.go @@ -93,3 +93,12 @@ type UserSettingsOptions struct { HideEmail *bool `json:"hide_email"` HideActivity *bool `json:"hide_activity"` } + +// CreateKeyOption options when creating a key +type RenameUserOption struct { + // New username + // + // required: true + // unique: true + NewName string `json:"new_username" binding:"Required"` +} diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index 6b48ce4a9d4d..3a9bdf158123 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -14,6 +14,7 @@ import ( asymkey_model "code.gitea.io/gitea/models/asymkey" "code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/db" + repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" @@ -24,9 +25,11 @@ import ( "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/user" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/agit" asymkey_service "code.gitea.io/gitea/services/asymkey" "code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/mailer" + container_service "code.gitea.io/gitea/services/packages/container" user_service "code.gitea.io/gitea/services/user" ) @@ -448,3 +451,83 @@ func GetAllUsers(ctx *context.APIContext) { ctx.SetTotalCountHeader(maxResults) ctx.JSON(http.StatusOK, &results) } + +// RenameUser api for renaming a user +func RenameUser(ctx *context.APIContext) { + // swagger:operation POST /admin/users/{username} admin adminRenameUser + // --- + // summary: Rename a user + // produces: + // - application/json + // parameters: + // - name: username + // in: path + // description: existing username of user + // type: string + // required: true + // - name: body + // in: body + // required: true + // schema: + // "$ref": "#/definitions/RenameUserOption" + // responses: + // "204": + // "$ref": "#/responses/empty" + // "403": + // "$ref": "#/responses/forbidden" + // "422": + // "$ref": "#/responses/validationError" + + if ctx.ContextUser.IsOrganization() { + ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("%s is an organization not a user", ctx.ContextUser.Name)) + return + } + + newName := web.GetForm(ctx).(*api.RenameUserOption).NewName + // Check if user name has been changed + if ctx.ContextUser.LowerName != strings.ToLower(newName) { + if err := user_model.ChangeUserName(ctx.ContextUser, newName); err != nil { + switch { + case user_model.IsErrUserAlreadyExist(err): + ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("form.username_been_taken")) + case user_model.IsErrEmailAlreadyUsed(err): + ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("form.email_been_used")) + case db.IsErrNameReserved(err): + ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_reserved", newName)) + case db.IsErrNamePatternNotAllowed(err): + ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_pattern_not_allowed", newName)) + case db.IsErrNameCharsNotAllowed(err): + ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_chars_not_allowed", newName)) + default: + ctx.ServerError("ChangeUserName", err) + } + return + } + } else { + if err := repo_model.UpdateRepositoryOwnerNames(ctx.ContextUser.ID, newName); err != nil { + fmt.Println("RenameUser 6") + ctx.ServerError("UpdateRepository", err) + return + } + } + // update all agit flow pull request header + err := agit.UserNameChanged(ctx.ContextUser, newName) + if err != nil { + ctx.ServerError("agit.UserNameChanged", err) + return + } + if err := container_service.UpdateRepositoryNames(ctx, ctx.ContextUser, newName); err != nil { + ctx.ServerError("UpdateRepositoryNames", err) + return + } + + ctx.ContextUser.Name = newName + ctx.ContextUser.LowerName = strings.ToLower(newName) + if err := user_model.UpdateUser(ctx, ctx.ContextUser, false); err != nil { + ctx.ServerError("UpdateUser", err) + return + } + + log.Trace("User name changed: %s -> %s", ctx.ContextUser.Name, newName) + ctx.Status(http.StatusNoContent) +} diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 5f57977c290b..5d7086c10143 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1250,6 +1250,7 @@ func Routes(ctx gocontext.Context) *web.Route { m.Get("/orgs", org.ListUserOrgs) m.Post("/orgs", bind(api.CreateOrgOption{}), admin.CreateOrg) m.Post("/repos", bind(api.CreateRepoOption{}), admin.CreateRepo) + m.Post("/rename", bind(api.RenameUserOption{}), admin.RenameUser) }, context_service.UserAssignmentAPI()) }) m.Group("/unadopted", func() { From 6e37106be351cedb47561277df6cd6cbcb4e3ded Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Tue, 21 Feb 2023 11:45:33 -0500 Subject: [PATCH 02/21] update swagger --- templates/swagger/v1_json.tmpl | 40 +++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 2a675766abc9..f016262b4cdb 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -477,6 +477,44 @@ } }, "/admin/users/{username}": { + "post": { + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "Rename a user", + "operationId": "adminRenameUser", + "parameters": [ + { + "type": "string", + "description": "existing username of user", + "name": "username", + "in": "path", + "required": true + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/RenameUserOption" + } + } + ], + "responses": { + "204": { + "$ref": "#/responses/empty" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "422": { + "$ref": "#/responses/validationError" + } + } + }, "delete": { "produces": [ "application/json" @@ -21020,4 +21058,4 @@ "TOTPHeader": [] } ] -} +} \ No newline at end of file From b960b1fb0c0d0d6ae416d117458ef161f924db47 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Wed, 1 Mar 2023 23:33:19 -0500 Subject: [PATCH 03/21] fix swagger --- routers/api/v1/admin/user.go | 2 +- templates/swagger/v1_json.tmpl | 78 +++++++++++++++++----------------- 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index 9e61d47eba3c..c77fe9918d95 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -463,7 +463,7 @@ func GetAllUsers(ctx *context.APIContext) { // RenameUser api for renaming a user func RenameUser(ctx *context.APIContext) { - // swagger:operation POST /admin/users/{username} admin adminRenameUser + // swagger:operation POST /admin/users/{username}/rename admin adminRenameUser // --- // summary: Rename a user // produces: diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index f016262b4cdb..f1de078b14dd 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -477,44 +477,6 @@ } }, "/admin/users/{username}": { - "post": { - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "Rename a user", - "operationId": "adminRenameUser", - "parameters": [ - { - "type": "string", - "description": "existing username of user", - "name": "username", - "in": "path", - "required": true - }, - { - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/RenameUserOption" - } - } - ], - "responses": { - "204": { - "$ref": "#/responses/empty" - }, - "403": { - "$ref": "#/responses/forbidden" - }, - "422": { - "$ref": "#/responses/validationError" - } - } - }, "delete": { "produces": [ "application/json" @@ -711,6 +673,46 @@ } } }, + "/admin/users/{username}/rename": { + "post": { + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "Rename a user", + "operationId": "adminRenameUser", + "parameters": [ + { + "type": "string", + "description": "existing username of user", + "name": "username", + "in": "path", + "required": true + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/RenameUserOption" + } + } + ], + "responses": { + "204": { + "$ref": "#/responses/empty" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "422": { + "$ref": "#/responses/validationError" + } + } + } + }, "/admin/users/{username}/repos": { "post": { "consumes": [ From 87ccd60ff6b026ea117028bd97ba854256228167 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Wed, 1 Mar 2023 23:41:21 -0500 Subject: [PATCH 04/21] fix swagger --- routers/api/v1/swagger/options.go | 3 +++ templates/swagger/v1_json.tmpl | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/routers/api/v1/swagger/options.go b/routers/api/v1/swagger/options.go index 979b18407590..0c8d3d353fec 100644 --- a/routers/api/v1/swagger/options.go +++ b/routers/api/v1/swagger/options.go @@ -48,6 +48,9 @@ type swaggerParameterBodies struct { // in:body CreateKeyOption api.CreateKeyOption + // in:body + RenameUserOption api.RenameUserOption + // in:body CreateLabelOption api.CreateLabelOption // in:body diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index f1de078b14dd..b6d456cee737 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -18961,6 +18961,22 @@ }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, + "RenameUserOption": { + "description": "CreateKeyOption options when creating a key", + "type": "object", + "required": [ + "new_username" + ], + "properties": { + "new_username": { + "description": "New username", + "type": "string", + "uniqueItems": true, + "x-go-name": "NewName" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, "RepoCollaboratorPermission": { "description": "RepoCollaboratorPermission to get repository permission for a collaborator", "type": "object", From ebe6a71bec3bed1c25edb232f5c386358c09a5d0 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Thu, 2 Mar 2023 00:39:45 -0500 Subject: [PATCH 05/21] remove log debugging --- routers/api/v1/admin/user.go | 1 - 1 file changed, 1 deletion(-) diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index c77fe9918d95..f87a5f55d4f4 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -514,7 +514,6 @@ func RenameUser(ctx *context.APIContext) { } } else { if err := repo_model.UpdateRepositoryOwnerNames(ctx.ContextUser.ID, newName); err != nil { - fmt.Println("RenameUser 6") ctx.ServerError("UpdateRepository", err) return } From 83ac9e501678febfb0427bff2fbabc85d3f70b89 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Wed, 8 Mar 2023 22:37:56 -0500 Subject: [PATCH 06/21] error will never be reached --- routers/api/v1/admin/user.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index f87a5f55d4f4..dbbbe397b76a 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -499,8 +499,6 @@ func RenameUser(ctx *context.APIContext) { switch { case user_model.IsErrUserAlreadyExist(err): ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("form.username_been_taken")) - case user_model.IsErrEmailAlreadyUsed(err): - ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("form.email_been_used")) case db.IsErrNameReserved(err): ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_reserved", newName)) case db.IsErrNamePatternNotAllowed(err): From d44c8e011ae92ed00a5570671d6ea7233e59b541 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Wed, 8 Mar 2023 22:40:30 -0500 Subject: [PATCH 07/21] update swagger docs --- modules/structs/user.go | 4 ++-- templates/swagger/v1_json.tmpl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/structs/user.go b/modules/structs/user.go index fde62ae85796..f68b92ac069e 100644 --- a/modules/structs/user.go +++ b/modules/structs/user.go @@ -94,9 +94,9 @@ type UserSettingsOptions struct { HideActivity *bool `json:"hide_activity"` } -// CreateKeyOption options when creating a key +// RenameUserOption options when renaming a user type RenameUserOption struct { - // New username + // New username for this user. This name cannot be in use yet by any other user. // // required: true // unique: true diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index b2aff8d8f08b..2edc6b8beefa 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -18984,14 +18984,14 @@ "x-go-package": "code.gitea.io/gitea/modules/structs" }, "RenameUserOption": { - "description": "CreateKeyOption options when creating a key", + "description": "RenameUserOption options when renaming a user", "type": "object", "required": [ "new_username" ], "properties": { "new_username": { - "description": "New username", + "description": "New username for this user. This name cannot be in use yet by any other user.", "type": "string", "uniqueItems": true, "x-go-name": "NewName" From 5dd3a5fdbfc05be8e972a5689927a69258474ba9 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Wed, 8 Mar 2023 23:02:02 -0500 Subject: [PATCH 08/21] move renameUser to service --- routers/api/v1/admin/user.go | 54 +++++++++--------------------------- services/user/rename.go | 47 +++++++++++++++++++++++++++++++ services/user/user.go | 5 ++++ 3 files changed, 65 insertions(+), 41 deletions(-) create mode 100644 services/user/rename.go diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index dbbbe397b76a..eb48fbebd04b 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -14,7 +14,6 @@ import ( asymkey_model "code.gitea.io/gitea/models/asymkey" "code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/auth/password" "code.gitea.io/gitea/modules/context" @@ -26,11 +25,9 @@ import ( "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/user" "code.gitea.io/gitea/routers/api/v1/utils" - "code.gitea.io/gitea/services/agit" asymkey_service "code.gitea.io/gitea/services/asymkey" "code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/mailer" - container_service "code.gitea.io/gitea/services/packages/container" user_service "code.gitea.io/gitea/services/user" ) @@ -493,47 +490,22 @@ func RenameUser(ctx *context.APIContext) { } newName := web.GetForm(ctx).(*api.RenameUserOption).NewName + // Check if user name has been changed - if ctx.ContextUser.LowerName != strings.ToLower(newName) { - if err := user_model.ChangeUserName(ctx.ContextUser, newName); err != nil { - switch { - case user_model.IsErrUserAlreadyExist(err): - ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("form.username_been_taken")) - case db.IsErrNameReserved(err): - ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_reserved", newName)) - case db.IsErrNamePatternNotAllowed(err): - ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_pattern_not_allowed", newName)) - case db.IsErrNameCharsNotAllowed(err): - ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_chars_not_allowed", newName)) - default: - ctx.ServerError("ChangeUserName", err) - } - return + if err := user_service.RenameUser(ctx, ctx.ContextUser, newName); err != nil { + switch { + case user_model.IsErrUserAlreadyExist(err): + ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("form.username_been_taken")) + case db.IsErrNameReserved(err): + ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_reserved", newName)) + case db.IsErrNamePatternNotAllowed(err): + ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_pattern_not_allowed", newName)) + case db.IsErrNameCharsNotAllowed(err): + ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_chars_not_allowed", newName)) + default: + ctx.ServerError("ChangeUserName", err) } - } else { - if err := repo_model.UpdateRepositoryOwnerNames(ctx.ContextUser.ID, newName); err != nil { - ctx.ServerError("UpdateRepository", err) - return - } - } - // update all agit flow pull request header - err := agit.UserNameChanged(ctx.ContextUser, newName) - if err != nil { - ctx.ServerError("agit.UserNameChanged", err) return } - if err := container_service.UpdateRepositoryNames(ctx, ctx.ContextUser, newName); err != nil { - ctx.ServerError("UpdateRepositoryNames", err) - return - } - - ctx.ContextUser.Name = newName - ctx.ContextUser.LowerName = strings.ToLower(newName) - if err := user_model.UpdateUser(ctx, ctx.ContextUser, false); err != nil { - ctx.ServerError("UpdateUser", err) - return - } - - log.Trace("User name changed: %s -> %s", ctx.ContextUser.Name, newName) ctx.Status(http.StatusNoContent) } diff --git a/services/user/rename.go b/services/user/rename.go new file mode 100644 index 000000000000..76be5eb827be --- /dev/null +++ b/services/user/rename.go @@ -0,0 +1,47 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package user + +import ( + "context" + "fmt" + "strings" + + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/services/agit" + container_service "code.gitea.io/gitea/services/packages/container" +) + +func renameUser(ctx context.Context, u *user_model.User, newUserName string) (err error) { + if u.IsOrganization() { + return fmt.Errorf("cannot rename organization") + } + + if u.LowerName == strings.ToLower(newUserName) { + return fmt.Errorf("new username is the same as the old one") + } + + if err := user_model.ChangeUserName(u, newUserName); err != nil { + return err + } + + err = agit.UserNameChanged(u, newUserName) + if err != nil { + return err + } + if err = container_service.UpdateRepositoryNames(ctx, u, newUserName); err != nil { + return err + } + + u.Name = newUserName + u.LowerName = strings.ToLower(newUserName) + if err := user_model.UpdateUser(ctx, u, false); err != nil { + return err + } + + log.Trace("User name changed: %s -> %s", u.Name, newUserName) + return + +} diff --git a/services/user/user.go b/services/user/user.go index f0b8fe1c3174..6da074e5c147 100644 --- a/services/user/user.go +++ b/services/user/user.go @@ -27,6 +27,11 @@ import ( "code.gitea.io/gitea/services/packages" ) +// RenameUser renames a user +func RenameUser(ctx context.Context, u *user_model.User, newUserName string) error { + return renameUser(ctx, u, newUserName) +} + // DeleteUser completely and permanently deletes everything of a user, // but issues/comments/pulls will be kept and shown as someone has been deleted, // unless the user is younger than USER_DELETE_WITH_COMMENTS_MAX_DAYS. From cb84b4e231a52b0f694663722f101549ab589bfc Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Wed, 8 Mar 2023 23:08:31 -0500 Subject: [PATCH 09/21] make fmt --- services/user/rename.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/services/user/rename.go b/services/user/rename.go index 76be5eb827be..7ce29c90a28f 100644 --- a/services/user/rename.go +++ b/services/user/rename.go @@ -42,6 +42,5 @@ func renameUser(ctx context.Context, u *user_model.User, newUserName string) (er } log.Trace("User name changed: %s -> %s", u.Name, newUserName) - return - + return nil } From 2a1a46f5b7dc84735b9f8fe4d7b97293680e12bb Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Wed, 8 Mar 2023 23:10:02 -0500 Subject: [PATCH 10/21] add newline to end of swagger template --- templates/swagger/v1_json.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 2edc6b8beefa..ec14980f987f 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -21098,4 +21098,4 @@ "TOTPHeader": [] } ] -} \ No newline at end of file +} From df46a9f9c4d5ccf764c2aab4c4dbd5aa88c87664 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Wed, 8 Mar 2023 23:20:29 -0500 Subject: [PATCH 11/21] move db into tx --- routers/api/v1/admin/user.go | 2 +- services/user/user.go | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index eb48fbebd04b..bc2a16d763f2 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -492,7 +492,7 @@ func RenameUser(ctx *context.APIContext) { newName := web.GetForm(ctx).(*api.RenameUserOption).NewName // Check if user name has been changed - if err := user_service.RenameUser(ctx, ctx.ContextUser, newName); err != nil { + if err := user_service.RenameUser(ctx.ContextUser, newName); err != nil { switch { case user_model.IsErrUserAlreadyExist(err): ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("form.username_been_taken")) diff --git a/services/user/user.go b/services/user/user.go index 6da074e5c147..7e3bf5455079 100644 --- a/services/user/user.go +++ b/services/user/user.go @@ -28,8 +28,19 @@ import ( ) // RenameUser renames a user -func RenameUser(ctx context.Context, u *user_model.User, newUserName string) error { - return renameUser(ctx, u, newUserName) +func RenameUser(u *user_model.User, newUserName string) error { + ctx, committer, err := db.TxContext(db.DefaultContext) + if err != nil { + return err + } + defer committer.Close() + if err := renameUser(ctx, u, newUserName); err != nil { + return fmt.Errorf("renameUser: %w", err) + } + if err := committer.Commit(); err != nil { + return err + } + return err } // DeleteUser completely and permanently deletes everything of a user, From e6437df1c6276dea06bc96a5c6ca8deda75d37e9 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Wed, 8 Mar 2023 23:39:15 -0500 Subject: [PATCH 12/21] noop for no user change --- routers/api/v1/admin/user.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index bc2a16d763f2..b16d0146efe3 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -491,6 +491,12 @@ func RenameUser(ctx *context.APIContext) { newName := web.GetForm(ctx).(*api.RenameUserOption).NewName + if strings.ToLower(newName) == strings.ToLower(ctx.ContextUser.Name) { + // Noop as username is not changed + ctx.Status(http.StatusNoContent) + return + } + // Check if user name has been changed if err := user_service.RenameUser(ctx.ContextUser, newName); err != nil { switch { From 8c71935658e975e430c8f6e4c780cacdadb3284e Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Wed, 8 Mar 2023 23:41:59 -0500 Subject: [PATCH 13/21] adds ctx back --- routers/api/v1/admin/user.go | 2 +- services/user/user.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index b16d0146efe3..0cca7f52686e 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -498,7 +498,7 @@ func RenameUser(ctx *context.APIContext) { } // Check if user name has been changed - if err := user_service.RenameUser(ctx.ContextUser, newName); err != nil { + if err := user_service.RenameUser(ctx, ctx.ContextUser, newName); err != nil { switch { case user_model.IsErrUserAlreadyExist(err): ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("form.username_been_taken")) diff --git a/services/user/user.go b/services/user/user.go index 7e3bf5455079..e4b38fda064c 100644 --- a/services/user/user.go +++ b/services/user/user.go @@ -28,8 +28,8 @@ import ( ) // RenameUser renames a user -func RenameUser(u *user_model.User, newUserName string) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func RenameUser(ctx context.Context, u *user_model.User, newUserName string) error { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } From 07cc2ef987eb6dc7b73771edbcbad2cbf3a23615 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Wed, 8 Mar 2023 23:59:21 -0500 Subject: [PATCH 14/21] make lint --- routers/api/v1/admin/user.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index 0cca7f52686e..fcfda2e53723 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -491,7 +491,7 @@ func RenameUser(ctx *context.APIContext) { newName := web.GetForm(ctx).(*api.RenameUserOption).NewName - if strings.ToLower(newName) == strings.ToLower(ctx.ContextUser.Name) { + if strings.EqualFold(newName, ctx.ContextUser.Name) { // Noop as username is not changed ctx.Status(http.StatusNoContent) return From 09d410e3ee834bcb8d287c4a0aeadea454ef661b Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Mon, 13 Mar 2023 02:09:15 -0400 Subject: [PATCH 15/21] add context --- models/user/user.go | 4 ++-- routers/web/org/setting.go | 2 +- routers/web/user/setting/profile.go | 2 +- services/user/rename.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/models/user/user.go b/models/user/user.go index f6fafe64f391..07a411816f90 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -737,13 +737,13 @@ func VerifyUserActiveCode(code string) (user *User) { } // ChangeUserName changes all corresponding setting from old user name to new one. -func ChangeUserName(u *User, newUserName string) (err error) { +func ChangeUserName(ctx context.Context, u *User, newUserName string) (err error) { oldUserName := u.Name if err = IsUsableUsername(newUserName); err != nil { return err } - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go index f713d096639b..f6789173925a 100644 --- a/routers/web/org/setting.go +++ b/routers/web/org/setting.go @@ -79,7 +79,7 @@ func SettingsPost(ctx *context.Context) { ctx.Data["OrgName"] = true ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), tplSettingsOptions, &form) return - } else if err = user_model.ChangeUserName(org.AsUser(), form.Name); err != nil { + } else if err = user_model.ChangeUserName(ctx, org.AsUser(), form.Name); err != nil { switch { case db.IsErrNameReserved(err): ctx.Data["OrgName"] = true diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index f0f053a514e0..31e9bbf9e2e2 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -59,7 +59,7 @@ func HandleUsernameChange(ctx *context.Context, user *user_model.User, newName s // Check if user name has been changed if user.LowerName != strings.ToLower(newName) { - if err := user_model.ChangeUserName(user, newName); err != nil { + if err := user_model.ChangeUserName(ctx, user, newName); err != nil { switch { case user_model.IsErrUserAlreadyExist(err): ctx.Flash.Error(ctx.Tr("form.username_been_taken")) diff --git a/services/user/rename.go b/services/user/rename.go index 7ce29c90a28f..a9c4aa6fc0a8 100644 --- a/services/user/rename.go +++ b/services/user/rename.go @@ -23,7 +23,7 @@ func renameUser(ctx context.Context, u *user_model.User, newUserName string) (er return fmt.Errorf("new username is the same as the old one") } - if err := user_model.ChangeUserName(u, newUserName); err != nil { + if err := user_model.ChangeUserName(ctx, u, newUserName); err != nil { return err } From 0d7542bb7fca2dc6064e1c52fc15bf58cb8335b7 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Mon, 13 Mar 2023 14:41:17 -0400 Subject: [PATCH 16/21] add context and move rename to service --- models/issues/pull.go | 4 +-- routers/web/user/setting/profile.go | 50 +++++++++++------------------ services/agit/agit.go | 4 +-- services/user/rename.go | 2 +- 4 files changed, 23 insertions(+), 37 deletions(-) diff --git a/models/issues/pull.go b/models/issues/pull.go index 6a1dc3155624..a15ebec0b52a 100644 --- a/models/issues/pull.go +++ b/models/issues/pull.go @@ -660,10 +660,10 @@ func GetPullRequestByIssueID(ctx context.Context, issueID int64) (*PullRequest, // GetAllUnmergedAgitPullRequestByPoster get all unmerged agit flow pull request // By poster id. -func GetAllUnmergedAgitPullRequestByPoster(uid int64) ([]*PullRequest, error) { +func GetAllUnmergedAgitPullRequestByPoster(ctx context.Context, uid int64) ([]*PullRequest, error) { pulls := make([]*PullRequest, 0, 10) - err := db.GetEngine(db.DefaultContext). + err := db.GetEngine(ctx). Where("has_merged=? AND flow = ? AND issue.is_closed=? AND issue.poster_id=?", false, PullRequestFlowAGit, false, uid). Join("INNER", "issue", "issue.id=pull_request.issue_id"). diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index 31e9bbf9e2e2..95008c3e4675 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -27,9 +27,7 @@ import ( "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web/middleware" - "code.gitea.io/gitea/services/agit" "code.gitea.io/gitea/services/forms" - container_service "code.gitea.io/gitea/services/packages/container" user_service "code.gitea.io/gitea/services/user" ) @@ -57,45 +55,33 @@ func HandleUsernameChange(ctx *context.Context, user *user_model.User, newName s return fmt.Errorf(ctx.Tr("form.username_change_not_local_user")) } - // Check if user name has been changed - if user.LowerName != strings.ToLower(newName) { - if err := user_model.ChangeUserName(ctx, user, newName); err != nil { - switch { - case user_model.IsErrUserAlreadyExist(err): - ctx.Flash.Error(ctx.Tr("form.username_been_taken")) - case user_model.IsErrEmailAlreadyUsed(err): - ctx.Flash.Error(ctx.Tr("form.email_been_used")) - case db.IsErrNameReserved(err): - ctx.Flash.Error(ctx.Tr("user.form.name_reserved", newName)) - case db.IsErrNamePatternNotAllowed(err): - ctx.Flash.Error(ctx.Tr("user.form.name_pattern_not_allowed", newName)) - case db.IsErrNameCharsNotAllowed(err): - ctx.Flash.Error(ctx.Tr("user.form.name_chars_not_allowed", newName)) - default: - ctx.ServerError("ChangeUserName", err) - } - return err - } - } else { + if strings.EqualFold(newName, ctx.ContextUser.Name) { if err := repo_model.UpdateRepositoryOwnerNames(user.ID, newName); err != nil { ctx.ServerError("UpdateRepository", err) return err } + return nil } - // update all agit flow pull request header - err := agit.UserNameChanged(user, newName) - if err != nil { - ctx.ServerError("agit.UserNameChanged", err) - return err - } - - if err := container_service.UpdateRepositoryNames(ctx, user, newName); err != nil { - ctx.ServerError("UpdateRepositoryNames", err) + // rename user + if err := user_service.RenameUser(ctx, ctx.ContextUser, newName); err != nil { + switch { + case user_model.IsErrUserAlreadyExist(err): + ctx.Flash.Error(ctx.Tr("form.username_been_taken")) + case user_model.IsErrEmailAlreadyUsed(err): + ctx.Flash.Error(ctx.Tr("form.email_been_used")) + case db.IsErrNameReserved(err): + ctx.Flash.Error(ctx.Tr("user.form.name_reserved", newName)) + case db.IsErrNamePatternNotAllowed(err): + ctx.Flash.Error(ctx.Tr("user.form.name_pattern_not_allowed", newName)) + case db.IsErrNameCharsNotAllowed(err): + ctx.Flash.Error(ctx.Tr("user.form.name_chars_not_allowed", newName)) + default: + ctx.ServerError("ChangeUserName", err) + } return err } - log.Trace("User name changed: %s -> %s", user.Name, newName) return nil } diff --git a/services/agit/agit.go b/services/agit/agit.go index b61cb6f3f569..32fc3cba4a36 100644 --- a/services/agit/agit.go +++ b/services/agit/agit.go @@ -226,8 +226,8 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git. } // UserNameChanged handle user name change for agit flow pull -func UserNameChanged(user *user_model.User, newName string) error { - pulls, err := issues_model.GetAllUnmergedAgitPullRequestByPoster(user.ID) +func UserNameChanged(ctx context.Context, user *user_model.User, newName string) error { + pulls, err := issues_model.GetAllUnmergedAgitPullRequestByPoster(ctx, user.ID) if err != nil { return err } diff --git a/services/user/rename.go b/services/user/rename.go index a9c4aa6fc0a8..245cd3a3ee5a 100644 --- a/services/user/rename.go +++ b/services/user/rename.go @@ -27,7 +27,7 @@ func renameUser(ctx context.Context, u *user_model.User, newUserName string) (er return err } - err = agit.UserNameChanged(u, newUserName) + err = agit.UserNameChanged(ctx, u, newUserName) if err != nil { return err } From 621cd1991e025b26d44abc3badde7d92b08f0564 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Mon, 13 Mar 2023 16:23:18 -0400 Subject: [PATCH 17/21] fix panic --- routers/web/user/setting/profile.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index 95008c3e4675..c75270c249e2 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -55,7 +55,7 @@ func HandleUsernameChange(ctx *context.Context, user *user_model.User, newName s return fmt.Errorf(ctx.Tr("form.username_change_not_local_user")) } - if strings.EqualFold(newName, ctx.ContextUser.Name) { + if strings.EqualFold(user.LowerName, newName) { if err := repo_model.UpdateRepositoryOwnerNames(user.ID, newName); err != nil { ctx.ServerError("UpdateRepository", err) return err From d53ea529475e275f9c9d05bbe7a1d0c7bb521333 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Mon, 13 Mar 2023 16:45:35 -0400 Subject: [PATCH 18/21] fix panic --- routers/web/user/setting/profile.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index c75270c249e2..e9c581a6ce7d 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -64,7 +64,7 @@ func HandleUsernameChange(ctx *context.Context, user *user_model.User, newName s } // rename user - if err := user_service.RenameUser(ctx, ctx.ContextUser, newName); err != nil { + if err := user_service.RenameUser(ctx, user, newName); err != nil { switch { case user_model.IsErrUserAlreadyExist(err): ctx.Flash.Error(ctx.Tr("form.username_been_taken")) From 5e9192b53dd74b39208ca2dcb404acc5c5ea1916 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Mon, 13 Mar 2023 17:33:41 -0400 Subject: [PATCH 19/21] unwrap error --- services/user/user.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/user/user.go b/services/user/user.go index e4b38fda064c..d52a2f404bcf 100644 --- a/services/user/user.go +++ b/services/user/user.go @@ -35,7 +35,7 @@ func RenameUser(ctx context.Context, u *user_model.User, newUserName string) err } defer committer.Close() if err := renameUser(ctx, u, newUserName); err != nil { - return fmt.Errorf("renameUser: %w", err) + return err } if err := committer.Commit(); err != nil { return err From f30a88d3322a7a067bc5b87bec06a3d011497cef Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Mon, 13 Mar 2023 23:19:24 -0400 Subject: [PATCH 20/21] remove duped code --- routers/web/user/setting/profile.go | 8 -------- services/user/rename.go | 4 ---- 2 files changed, 12 deletions(-) diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index e9c581a6ce7d..f500be763233 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -55,14 +55,6 @@ func HandleUsernameChange(ctx *context.Context, user *user_model.User, newName s return fmt.Errorf(ctx.Tr("form.username_change_not_local_user")) } - if strings.EqualFold(user.LowerName, newName) { - if err := repo_model.UpdateRepositoryOwnerNames(user.ID, newName); err != nil { - ctx.ServerError("UpdateRepository", err) - return err - } - return nil - } - // rename user if err := user_service.RenameUser(ctx, user, newName); err != nil { switch { diff --git a/services/user/rename.go b/services/user/rename.go index 245cd3a3ee5a..87e05220d7e1 100644 --- a/services/user/rename.go +++ b/services/user/rename.go @@ -19,10 +19,6 @@ func renameUser(ctx context.Context, u *user_model.User, newUserName string) (er return fmt.Errorf("cannot rename organization") } - if u.LowerName == strings.ToLower(newUserName) { - return fmt.Errorf("new username is the same as the old one") - } - if err := user_model.ChangeUserName(ctx, u, newUserName); err != nil { return err } From 79ed00ff0252ae1445dba768141520abe64bedfe Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Tue, 14 Mar 2023 00:33:57 -0400 Subject: [PATCH 21/21] Apply suggestions from code review Co-authored-by: Jason Song --- services/user/rename.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/services/user/rename.go b/services/user/rename.go index 87e05220d7e1..af195d7d76a2 100644 --- a/services/user/rename.go +++ b/services/user/rename.go @@ -14,7 +14,7 @@ import ( container_service "code.gitea.io/gitea/services/packages/container" ) -func renameUser(ctx context.Context, u *user_model.User, newUserName string) (err error) { +func renameUser(ctx context.Context, u *user_model.User, newUserName string) error { if u.IsOrganization() { return fmt.Errorf("cannot rename organization") } @@ -23,11 +23,10 @@ func renameUser(ctx context.Context, u *user_model.User, newUserName string) (er return err } - err = agit.UserNameChanged(ctx, u, newUserName) - if err != nil { + if err := agit.UserNameChanged(ctx, u, newUserName); err != nil { return err } - if err = container_service.UpdateRepositoryNames(ctx, u, newUserName); err != nil { + if err := container_service.UpdateRepositoryNames(ctx, u, newUserName); err != nil { return err }