From 2c5edbdb307cd66919f40486cc9b8d9200e1a77b Mon Sep 17 00:00:00 2001 From: Bwko Date: Sun, 9 Jul 2017 01:44:02 +0200 Subject: [PATCH 01/11] Add option to change username to the admin panel --- integrations/admin_user_test.go | 81 +++++++++++++++++++++++++++++++++ modules/auth/admin.go | 1 + public/js/index.js | 2 + routers/admin/users.go | 8 ++++ templates/admin/user/edit.tmpl | 4 +- 5 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 integrations/admin_user_test.go diff --git a/integrations/admin_user_test.go b/integrations/admin_user_test.go new file mode 100644 index 0000000000000..14e3596b96d8a --- /dev/null +++ b/integrations/admin_user_test.go @@ -0,0 +1,81 @@ +// Copyright 2017 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package integrations + +import ( + "net/http" + "strconv" + "testing" + + "code.gitea.io/gitea/models" + "github.com/stretchr/testify/assert" +) + +func TestAdminViewUsers(t *testing.T) { + prepareTestEnv(t) + + session := loginUser(t, "user1") + req := NewRequest(t, "GET", "/admin/users") + session.MakeRequest(t, req, http.StatusOK) + + session = loginUser(t, "user2") + req = NewRequest(t, "GET", "/admin/users") + session.MakeRequest(t, req, http.StatusForbidden) +} + +func TestAdminViewUser(t *testing.T) { + prepareTestEnv(t) + + session := loginUser(t, "user1") + req := NewRequest(t, "GET", "/admin/users/1") + session.MakeRequest(t, req, http.StatusOK) + + session = loginUser(t, "user2") + req = NewRequest(t, "GET", "/admin/users/1") + session.MakeRequest(t, req, http.StatusForbidden) +} + +func TestAdminEditUser(t *testing.T) { + prepareTestEnv(t) + + testSuccessfullEdit(t, models.User{ID: 2, Name: "newusername", LoginName: "otherlogin", Email: "new@e-mail.gitea"}) +} + +func testSuccessfullEdit(t *testing.T, formData models.User) { + makeRequest(t, formData, http.StatusFound) +} + +func makeRequest(t *testing.T, formData models.User, headerCode int) { + session := loginUser(t, "user1") + csrf := GetCSRF(t, session, "/admin/users/"+strconv.Itoa(int(formData.ID))) + req := NewRequestWithValues(t, "POST", "/admin/users/"+strconv.Itoa(int(formData.ID)), map[string]string{ + "_csrf": csrf, + "user_name": formData.Name, + "login_name": formData.LoginName, + "login_type": "0-0", + "email": formData.Email, + }) + + session.MakeRequest(t, req, headerCode) + user := models.AssertExistsAndLoadBean(t, &models.User{ID: formData.ID}).(*models.User) + assert.Equal(t, formData.Name, user.Name) + assert.Equal(t, formData.LoginName, user.LoginName) + assert.Equal(t, formData.Email, user.Email) +} + +func TestAdminDeleteUser(t *testing.T) { + prepareTestEnv(t) + + session := loginUser(t, "user1") + + csrf := GetCSRF(t, session, "/admin/users/8") + req := NewRequestWithValues(t, "POST", "/admin/users/8/delete", map[string]string{ + "_csrf": csrf, + }) + session.MakeRequest(t, req, http.StatusOK) + + models.AssertNotExistsBean(t, &models.User{ID: 8}) + models.CheckConsistencyFor(t, &models.User{}) +} diff --git a/modules/auth/admin.go b/modules/auth/admin.go index 0bb7d355c45fe..e1b52a9486f18 100644 --- a/modules/auth/admin.go +++ b/modules/auth/admin.go @@ -28,6 +28,7 @@ func (f *AdminCreateUserForm) Validate(ctx *macaron.Context, errs binding.Errors // AdminEditUserForm form for admin to create user type AdminEditUserForm struct { LoginType string `binding:"Required"` + UserName string `binding:"AlphaDashDot;MaxSize(35)"` LoginName string FullName string `binding:"MaxSize(100)"` Email string `binding:"Required;Email;MaxSize(254)"` diff --git a/public/js/index.js b/public/js/index.js index 25915bc2abf2c..73266dff9a7c9 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -1015,6 +1015,7 @@ function initAdmin() { $('.admin.edit.user').length > 0) { $('#login_type').change(function () { if ($(this).val().substring(0, 1) == '0') { + $('#user_name').removeAttr('disabled'); $('#login_name').removeAttr('required'); $('.non-local').hide(); $('.local').show(); @@ -1025,6 +1026,7 @@ function initAdmin() { } } else { + $('#user_name').attr('disabled', 'disabled'); $('#login_name').attr('required', 'required'); $('.non-local').show(); $('.local').hide(); diff --git a/routers/admin/users.go b/routers/admin/users.go index d480029143fa6..658536422daf3 100644 --- a/routers/admin/users.go +++ b/routers/admin/users.go @@ -205,6 +205,14 @@ func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) { u.EncodePasswd() } + if u.IsLocal() && len(form.UserName) > 0 && u.Name != form.UserName { + if err := models.ChangeUserName(u, form.UserName); err != nil { + ctx.Handle(500, "ChangeUserName", err) + return + } + u.Name = form.UserName + } + u.LoginName = form.LoginName u.FullName = form.FullName u.Email = form.Email diff --git a/templates/admin/user/edit.tmpl b/templates/admin/user/edit.tmpl index 4feeef302a40b..e6240625fe3fd 100644 --- a/templates/admin/user/edit.tmpl +++ b/templates/admin/user/edit.tmpl @@ -9,9 +9,9 @@
{{.CsrfTokenHtml}} -
+
- {{.User.Name}} +
From 93076c0187e003db4b49e076763ebe9c5657621b Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Wed, 30 Jan 2019 12:24:37 -0500 Subject: [PATCH 02/11] Update year --- integrations/admin_user_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/admin_user_test.go b/integrations/admin_user_test.go index 14e3596b96d8a..6ad8ba90f3557 100644 --- a/integrations/admin_user_test.go +++ b/integrations/admin_user_test.go @@ -1,4 +1,4 @@ -// Copyright 2017 The Gitea Authors. All rights reserved. +// Copyright 2019 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. From 16bc2b9b93a05476698e9c85ecd4fef4d6d9feb6 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sun, 3 Jan 2021 18:23:45 +0100 Subject: [PATCH 03/11] fix merge conflict relicts --- web_src/js/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web_src/js/index.js b/web_src/js/index.js index ef674ad6a6b90..6fa6584d37332 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -1794,6 +1794,7 @@ function initAdmin() { if ($('.admin.new.user').length > 0 || $('.admin.edit.user').length > 0) { $('#login_type').on('change', function () { if ($(this).val().substring(0, 1) === '0') { + $('#user_name').removeAttr('disabled'); $('#login_name').removeAttr('required'); $('.non-local').hide(); $('.local').show(); @@ -1803,6 +1804,7 @@ function initAdmin() { $('#password').attr('required', 'required'); } } else { + $('#user_name').attr('disabled', 'disabled'); $('#login_name').attr('required', 'required'); $('.non-local').show(); $('.local').hide(); From a8a44d0f6b62205e2fbc739257c56a7292cd8a6f Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sun, 3 Jan 2021 18:28:39 +0100 Subject: [PATCH 04/11] fix --- routers/admin/users.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/admin/users.go b/routers/admin/users.go index cf5741a74896a..dc24052f90c3a 100644 --- a/routers/admin/users.go +++ b/routers/admin/users.go @@ -261,7 +261,7 @@ func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) { if u.IsLocal() && len(form.UserName) > 0 && u.Name != form.UserName { if err := models.ChangeUserName(u, form.UserName); err != nil { - ctx.Handle(500, "ChangeUserName", err) + ctx.InternalServerError(err) return } u.Name = form.UserName From f6926aea314db0ccddaee327b60429276328579f Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sun, 3 Jan 2021 18:40:20 +0100 Subject: [PATCH 05/11] Same limit on AdminEditUserForm as in AdminCreateUserForm --- modules/auth/admin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auth/admin.go b/modules/auth/admin.go index fb7f8667c5879..7fad0521d93af 100644 --- a/modules/auth/admin.go +++ b/modules/auth/admin.go @@ -28,7 +28,7 @@ func (f *AdminCreateUserForm) Validate(ctx *macaron.Context, errs binding.Errors // AdminEditUserForm form for admin to create user type AdminEditUserForm struct { LoginType string `binding:"Required"` - UserName string `binding:"AlphaDashDot;MaxSize(35)"` + UserName string `binding:"AlphaDashDot;MaxSize(40)"` LoginName string FullName string `binding:"MaxSize(100)"` Email string `binding:"Required;Email;MaxSize(254)"` From e1db9501da817c808237e908e38d643a4bbbc959 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sun, 3 Jan 2021 18:49:28 +0100 Subject: [PATCH 06/11] Impruve ChangeUserName --- models/user.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/models/user.go b/models/user.go index 73178f256c1bb..d3f1b16c2e7f2 100644 --- a/models/user.go +++ b/models/user.go @@ -913,19 +913,19 @@ func ChangeUserName(u *User, newUserName string) (err error) { return err } - isExist, err := IsUserExist(0, newUserName) - if err != nil { - return err - } else if isExist { - return ErrUserAlreadyExist{newUserName} - } - sess := x.NewSession() defer sess.Close() if err = sess.Begin(); err != nil { return err } + isExist, err := isUserExist(sess, 0, newUserName) + if err != nil { + return err + } else if isExist { + return ErrUserAlreadyExist{newUserName} + } + if _, err = sess.Exec("UPDATE `repository` SET owner_name=? WHERE owner_name=?", newUserName, u.Name); err != nil { return fmt.Errorf("Change repo owner name: %v", err) } From e93e3ec782c057ed1e993efa9153d161954fc902 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sun, 3 Jan 2021 19:07:45 +0100 Subject: [PATCH 07/11] re-use HandleUsernameChange --- routers/admin/users.go | 8 +++++--- routers/user/setting/profile.go | 25 +++++++++++++------------ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/routers/admin/users.go b/routers/admin/users.go index dc24052f90c3a..e4d3f8d5190dd 100644 --- a/routers/admin/users.go +++ b/routers/admin/users.go @@ -18,6 +18,7 @@ import ( "code.gitea.io/gitea/modules/password" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/routers" + router_user_setting "code.gitea.io/gitea/routers/user/setting" "code.gitea.io/gitea/services/mailer" ) @@ -259,12 +260,13 @@ func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) { u.HashPassword(form.Password) } - if u.IsLocal() && len(form.UserName) > 0 && u.Name != form.UserName { - if err := models.ChangeUserName(u, form.UserName); err != nil { - ctx.InternalServerError(err) + if len(form.UserName) > 0 && u.Name != form.UserName { + router_user_setting.HandleUsernameChange(ctx, u, form.UserName) + if ctx.Written() { return } u.Name = form.UserName + u.LowerName = strings.ToLower(form.UserName) } u.LoginName = form.LoginName diff --git a/routers/user/setting/profile.go b/routers/user/setting/profile.go index fe9ce098fef71..3f6eb77983ede 100644 --- a/routers/user/setting/profile.go +++ b/routers/user/setting/profile.go @@ -38,15 +38,16 @@ func Profile(ctx *context.Context) { ctx.HTML(200, tplSettingsProfile) } -func handleUsernameChange(ctx *context.Context, newName string) { +// HandleUsernameChange handle username changes from user settings and admin interface +func HandleUsernameChange(ctx *context.Context, user *models.User, newName string) { // Non-local users are not allowed to change their username. - if len(newName) == 0 || !ctx.User.IsLocal() { + if len(newName) == 0 || !user.IsLocal() { return } // Check if user name has been changed - if ctx.User.LowerName != strings.ToLower(newName) { - if err := models.ChangeUserName(ctx.User, newName); err != nil { + if user.LowerName != strings.ToLower(newName) { + if err := models.ChangeUserName(user, newName); err != nil { switch { case models.IsErrUserAlreadyExist(err): ctx.Flash.Error(ctx.Tr("form.username_been_taken")) @@ -68,12 +69,8 @@ func handleUsernameChange(ctx *context.Context, newName string) { } return } - log.Trace("User name changed: %s -> %s", ctx.User.Name, newName) + log.Trace("User name changed: %s -> %s", user.Name, newName) } - - // In case it's just a case change - ctx.User.Name = newName - ctx.User.LowerName = strings.ToLower(newName) } // ProfilePost response for change user's profile @@ -86,9 +83,13 @@ func ProfilePost(ctx *context.Context, form auth.UpdateProfileForm) { return } - handleUsernameChange(ctx, form.Name) - if ctx.Written() { - return + if len(form.Name) != 0 && ctx.User.Name != form.Name { + HandleUsernameChange(ctx, ctx.User, form.Name) + if ctx.Written() { + return + } + ctx.User.Name = form.Name + ctx.User.LowerName = strings.ToLower(form.Name) } ctx.User.FullName = form.FullName From 3524d0c38605db817f500538f8237534d1e2e465 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sun, 3 Jan 2021 19:22:58 +0100 Subject: [PATCH 08/11] fix redirect url & return error if non local acount --- options/locale/locale_en-US.ini | 1 + routers/admin/users.go | 6 +++--- routers/user/setting/profile.go | 19 ++++++++----------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index ae72dff3ad210..4d2c10909952d 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -359,6 +359,7 @@ password_not_match = The passwords do not match. lang_select_error = Select a language from the list. username_been_taken = The username is already taken. +username_change_not_local_user = Non-local users are not allowed to change their username. repo_name_been_taken = The repository name is already used. repository_files_already_exist = Files already exist for this repository. Contact the system administrator. repository_files_already_exist.adopt = Files already exist for this repository and can only be Adopted. diff --git a/routers/admin/users.go b/routers/admin/users.go index e4d3f8d5190dd..3eaaa3791bd17 100644 --- a/routers/admin/users.go +++ b/routers/admin/users.go @@ -260,9 +260,9 @@ func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) { u.HashPassword(form.Password) } - if len(form.UserName) > 0 && u.Name != form.UserName { - router_user_setting.HandleUsernameChange(ctx, u, form.UserName) - if ctx.Written() { + if len(form.UserName) != 0 && u.Name != form.UserName { + if err := router_user_setting.HandleUsernameChange(ctx, u, form.UserName); err != nil { + ctx.Redirect(setting.AppSubURL + "/admin/users") return } u.Name = form.UserName diff --git a/routers/user/setting/profile.go b/routers/user/setting/profile.go index 3f6eb77983ede..c935b56230d85 100644 --- a/routers/user/setting/profile.go +++ b/routers/user/setting/profile.go @@ -39,10 +39,11 @@ func Profile(ctx *context.Context) { } // HandleUsernameChange handle username changes from user settings and admin interface -func HandleUsernameChange(ctx *context.Context, user *models.User, newName string) { +func HandleUsernameChange(ctx *context.Context, user *models.User, newName string) error { // Non-local users are not allowed to change their username. - if len(newName) == 0 || !user.IsLocal() { - return + if !user.IsLocal() { + ctx.Flash.Error(ctx.Tr("form.username_change_not_local_user")) + return fmt.Errorf(ctx.Tr("form.username_change_not_local_user")) } // Check if user name has been changed @@ -51,26 +52,22 @@ func HandleUsernameChange(ctx *context.Context, user *models.User, newName strin switch { case models.IsErrUserAlreadyExist(err): ctx.Flash.Error(ctx.Tr("form.username_been_taken")) - ctx.Redirect(setting.AppSubURL + "/user/settings") case models.IsErrEmailAlreadyUsed(err): ctx.Flash.Error(ctx.Tr("form.email_been_used")) - ctx.Redirect(setting.AppSubURL + "/user/settings") case models.IsErrNameReserved(err): ctx.Flash.Error(ctx.Tr("user.form.name_reserved", newName)) - ctx.Redirect(setting.AppSubURL + "/user/settings") case models.IsErrNamePatternNotAllowed(err): ctx.Flash.Error(ctx.Tr("user.form.name_pattern_not_allowed", newName)) - ctx.Redirect(setting.AppSubURL + "/user/settings") case models.IsErrNameCharsNotAllowed(err): ctx.Flash.Error(ctx.Tr("user.form.name_chars_not_allowed", newName)) - ctx.Redirect(setting.AppSubURL + "/user/settings") default: ctx.ServerError("ChangeUserName", err) } - return + return err } log.Trace("User name changed: %s -> %s", user.Name, newName) } + return nil } // ProfilePost response for change user's profile @@ -84,8 +81,8 @@ func ProfilePost(ctx *context.Context, form auth.UpdateProfileForm) { } if len(form.Name) != 0 && ctx.User.Name != form.Name { - HandleUsernameChange(ctx, ctx.User, form.Name) - if ctx.Written() { + if err := HandleUsernameChange(ctx, ctx.User, form.Name); err != nil { + ctx.Redirect(setting.AppSubURL + "/user/settings") return } ctx.User.Name = form.Name From d2592109a494b135132a1cb65bbe77785aa753b4 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sun, 3 Jan 2021 19:26:21 +0100 Subject: [PATCH 09/11] fix lint --- integrations/admin_user_test.go | 4 ++-- integrations/delete_user_test.go | 15 --------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/integrations/admin_user_test.go b/integrations/admin_user_test.go index 6ad8ba90f3557..a06e28b0c4b6d 100644 --- a/integrations/admin_user_test.go +++ b/integrations/admin_user_test.go @@ -66,7 +66,7 @@ func makeRequest(t *testing.T, formData models.User, headerCode int) { } func TestAdminDeleteUser(t *testing.T) { - prepareTestEnv(t) + defer prepareTestEnv(t)() session := loginUser(t, "user1") @@ -76,6 +76,6 @@ func TestAdminDeleteUser(t *testing.T) { }) session.MakeRequest(t, req, http.StatusOK) - models.AssertNotExistsBean(t, &models.User{ID: 8}) + assertUserDeleted(t, 8) models.CheckConsistencyFor(t, &models.User{}) } diff --git a/integrations/delete_user_test.go b/integrations/delete_user_test.go index 32032b3ddf453..86be6f22ad78b 100644 --- a/integrations/delete_user_test.go +++ b/integrations/delete_user_test.go @@ -24,21 +24,6 @@ func assertUserDeleted(t *testing.T, userID int64) { models.AssertNotExistsBean(t, &models.Star{UID: userID}) } -func TestAdminDeleteUser(t *testing.T) { - defer prepareTestEnv(t)() - - session := loginUser(t, "user1") - - csrf := GetCSRF(t, session, "/admin/users/8") - req := NewRequestWithValues(t, "POST", "/admin/users/8/delete", map[string]string{ - "_csrf": csrf, - }) - session.MakeRequest(t, req, http.StatusOK) - - assertUserDeleted(t, 8) - models.CheckConsistencyFor(t, &models.User{}) -} - func TestUserDeleteAccount(t *testing.T) { defer prepareTestEnv(t)() From ed4573ba4b74268a6cab3d861886db7686057806 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 4 Jan 2021 01:26:42 +0100 Subject: [PATCH 10/11] =?UTF-8?q?it's=202021=20=F0=9F=98=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- integrations/admin_user_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/admin_user_test.go b/integrations/admin_user_test.go index a06e28b0c4b6d..98d177dd014b3 100644 --- a/integrations/admin_user_test.go +++ b/integrations/admin_user_test.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Gitea Authors. All rights reserved. +// Copyright 2021 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. From cd2f5aa971851f04003e9dafadb5bf8b1dcf4dfa Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sat, 9 Jan 2021 18:19:02 +0100 Subject: [PATCH 11/11] Update integrations/admin_user_test.go --- integrations/admin_user_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/integrations/admin_user_test.go b/integrations/admin_user_test.go index 98d177dd014b3..f6b4590d27242 100644 --- a/integrations/admin_user_test.go +++ b/integrations/admin_user_test.go @@ -10,6 +10,7 @@ import ( "testing" "code.gitea.io/gitea/models" + "github.com/stretchr/testify/assert" )