From 63f2918336aec5ef960e31e03f207a39967d14bf Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sun, 16 Aug 2026 21:39:28 +0800 Subject: [PATCH] fix: make "login_name" field optional for API edit user (#38917) --- modules/structs/admin_user.go | 5 +-- modules/structs/user.go | 1 - routers/api/v1/admin/user.go | 2 +- templates/swagger/v1-openapi3.generated.json | 6 +--- templates/swagger/v1-swagger.generated.json | 6 +--- tests/integration/api_admin_test.go | 32 +++----------------- 6 files changed, 9 insertions(+), 43 deletions(-) diff --git a/modules/structs/admin_user.go b/modules/structs/admin_user.go index 4fd10aa5805..9795e83b5db 100644 --- a/modules/structs/admin_user.go +++ b/modules/structs/admin_user.go @@ -11,7 +11,6 @@ type CreateUserOption struct { // The authentication source ID to associate with the user SourceID int64 `json:"source_id"` // identifier of the user, provided by the external authenticator (if configured) - // default: empty LoginName string `json:"login_name"` // username of the user // required: true @@ -43,9 +42,7 @@ type EditUserOption struct { // The authentication source ID to associate with the user SourceID int64 `json:"source_id"` // identifier of the user, provided by the external authenticator (if configured) - // default: empty - // required: true - LoginName string `json:"login_name" binding:"Required"` + LoginName *string `json:"login_name"` // swagger:strfmt email // The email address of the user Email *string `json:"email" binding:"MaxSize(254)"` diff --git a/modules/structs/user.go b/modules/structs/user.go index 1c1fc68f8b8..a14f5805ca5 100644 --- a/modules/structs/user.go +++ b/modules/structs/user.go @@ -18,7 +18,6 @@ type User struct { // login of the user, same as `username` UserName string `json:"login"` // identifier of the user, provided by the external authenticator (if configured) - // default: empty LoginName string `json:"login_name"` // The ID of the user's Authentication Source SourceID int64 `json:"source_id"` diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index 9a4508991cb..d7cd45fd3c4 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -194,7 +194,7 @@ func EditUser(ctx *context.APIContext) { authOpts := &user_service.UpdateAuthOptions{ LoginSource: optional.FromNonDefault(form.SourceID), - LoginName: optional.Some(form.LoginName), + LoginName: optional.FromPtr(form.LoginName), Password: optional.FromNonDefault(form.Password), MustChangePassword: optional.FromPtr(form.MustChangePassword), ProhibitLogin: optional.FromPtr(form.ProhibitLogin), diff --git a/templates/swagger/v1-openapi3.generated.json b/templates/swagger/v1-openapi3.generated.json index cb2423be78e..fe6197465ae 100644 --- a/templates/swagger/v1-openapi3.generated.json +++ b/templates/swagger/v1-openapi3.generated.json @@ -4956,7 +4956,6 @@ "x-go-name": "FullName" }, "login_name": { - "default": "empty", "description": "identifier of the user, provided by the external authenticator (if configured)", "type": "string", "x-go-name": "LoginName" @@ -6234,7 +6233,6 @@ "x-go-name": "Location" }, "login_name": { - "default": "empty", "description": "identifier of the user, provided by the external authenticator (if configured)", "type": "string", "x-go-name": "LoginName" @@ -6286,8 +6284,7 @@ } }, "required": [ - "source_id", - "login_name" + "source_id" ], "type": "object", "x-go-package": "gitea.dev/modules/structs" @@ -10658,7 +10655,6 @@ "x-go-name": "UserName" }, "login_name": { - "default": "empty", "description": "identifier of the user, provided by the external authenticator (if configured)", "type": "string", "x-go-name": "LoginName" diff --git a/templates/swagger/v1-swagger.generated.json b/templates/swagger/v1-swagger.generated.json index 500e6b06f89..e3b017977e1 100644 --- a/templates/swagger/v1-swagger.generated.json +++ b/templates/swagger/v1-swagger.generated.json @@ -27879,7 +27879,6 @@ "login_name": { "description": "identifier of the user, provided by the external authenticator (if configured)", "type": "string", - "default": "empty", "x-go-name": "LoginName" }, "must_change_password": { @@ -29124,8 +29123,7 @@ "description": "EditUserOption edit user options", "type": "object", "required": [ - "source_id", - "login_name" + "source_id" ], "properties": { "active": { @@ -29177,7 +29175,6 @@ "login_name": { "description": "identifier of the user, provided by the external authenticator (if configured)", "type": "string", - "default": "empty", "x-go-name": "LoginName" }, "max_repo_creation": { @@ -33551,7 +33548,6 @@ "login_name": { "description": "identifier of the user, provided by the external authenticator (if configured)", "type": "string", - "default": "empty", "x-go-name": "LoginName" }, "prohibit_login": { diff --git a/tests/integration/api_admin_test.go b/tests/integration/api_admin_test.go index fba9e55c25a..b4d1bcee8a0 100644 --- a/tests/integration/api_admin_test.go +++ b/tests/integration/api_admin_test.go @@ -204,12 +204,7 @@ func TestAPIEditUser(t *testing.T) { user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{LoginName: "user2"}) assert.Equal(t, fullNameToChange, user2.FullName) - empty := "" - req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{ - LoginName: "user2", - SourceID: 0, - Email: &empty, - }).AddTokenAuth(token) + req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{SourceID: 0, Email: new("")}).AddTokenAuth(token) resp := MakeRequest(t, req, http.StatusBadRequest) errMap := make(map[string]any) @@ -218,14 +213,7 @@ func TestAPIEditUser(t *testing.T) { user2 = unittest.AssertExistsAndLoadBean(t, &user_model.User{LoginName: "user2"}) assert.False(t, user2.IsRestricted) - bTrue := true - req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{ - // required - LoginName: "user2", - SourceID: 0, - // to change - Restricted: &bTrue, - }).AddTokenAuth(token) + req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{Restricted: new(true)}).AddTokenAuth(token) MakeRequest(t, req, http.StatusOK) user2 = unittest.AssertExistsAndLoadBean(t, &user_model.User{LoginName: "user2"}) assert.True(t, user2.IsRestricted) @@ -361,24 +349,14 @@ func TestAPIEditUser_NotAllowedEmailDomain(t *testing.T) { adminUsername := "user1" token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeWriteAdmin) - urlStr := "/api/v1/admin/users/" + "user2" + urlStr := "/api/v1/admin/users/user2" - newEmail := "user2@example1.com" - req := NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{ - LoginName: "user2", - SourceID: 0, - Email: &newEmail, - }).AddTokenAuth(token) + req := NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{Email: new("user2@example1.com")}).AddTokenAuth(token) resp := MakeRequest(t, req, http.StatusBadRequest) errMap := make(map[string]string) assert.NoError(t, json.Unmarshal(resp.Body.Bytes(), &errMap)) assert.Equal(t, "the domain of user email user2@example1.com conflicts with EMAIL_DOMAIN_ALLOWLIST or EMAIL_DOMAIN_BLOCKLIST", errMap["message"]) - originalEmail := "user2@example.org" - req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{ - LoginName: "user2", - SourceID: 0, - Email: &originalEmail, - }).AddTokenAuth(token) + req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{Email: new("user2@example.org")}).AddTokenAuth(token) MakeRequest(t, req, http.StatusOK) }