diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go
index 125e387866..466fbff435 100644
--- a/routers/web/user/setting/profile.go
+++ b/routers/web/user/setting/profile.go
@@ -43,8 +43,8 @@ const (
var commonPronouns = []string{"he/him", "she/her", "they/them", "it/its", "any pronouns"}
-// Profile render user's profile page
-func Profile(ctx *context.Context) {
+// profileContext sets common context for profile settings template.
+func profileContext(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("settings.profile")
ctx.Data["PageIsSettingsProfile"] = true
ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
@@ -55,20 +55,24 @@ func Profile(ctx *context.Context) {
ctx.Data["MaxAvatarWidth"] = setting.Avatar.MaxWidth
ctx.Data["MaxAvatarHeight"] = setting.Avatar.MaxHeight
+ canUserRename, err := user_service.CanUserRename(ctx, ctx.Doer)
+ if err != nil {
+ log.Error("CanUserRename for user[%d]: %v", ctx.Doer.ID, err)
+ }
+
+ ctx.Data["UserRenameDisabled"] = !canUserRename
+}
+
+// Profile render user's profile page
+func Profile(ctx *context.Context) {
+ profileContext(ctx)
+
ctx.HTML(http.StatusOK, tplSettingsProfile)
}
// ProfilePost response for change user's profile
func ProfilePost(ctx *context.Context) {
- ctx.Data["Title"] = ctx.Tr("settings")
- ctx.Data["PageIsSettingsProfile"] = true
- ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
- ctx.Data["DisableGravatar"] = setting.Config().Picture.DisableGravatar.Value(ctx)
- ctx.Data["CooldownPeriod"] = setting.Service.UsernameCooldownPeriod
- ctx.Data["CommonPronouns"] = commonPronouns
- ctx.Data["MaxAvatarFileSize"] = setting.Avatar.MaxFileSize
- ctx.Data["MaxAvatarWidth"] = setting.Avatar.MaxWidth
- ctx.Data["MaxAvatarHeight"] = setting.Avatar.MaxHeight
+ profileContext(ctx)
if ctx.HasError() {
ctx.HTML(http.StatusOK, tplSettingsProfile)
diff --git a/services/user/user.go b/services/user/user.go
index 020d68d432..e16ec7c754 100644
--- a/services/user/user.go
+++ b/services/user/user.go
@@ -38,35 +38,47 @@ func RenameUser(ctx context.Context, u *user_model.User, newUserName string) err
return renameUser(ctx, u, newUserName, false)
}
-// RenameUser renames a user as an admin.
+// AdminRenameUser renames a user as an admin.
func AdminRenameUser(ctx context.Context, u *user_model.User, newUserName string) error {
return renameUser(ctx, u, newUserName, true)
}
+// CanUserRename returns if the given user can be renamed.
+//
+// This is merely a precondition, you likely want to use [RenameUser] or [AdminRenameUser]
+// which also takes into consideration username cooldown of a new username.
+func CanUserRename(ctx context.Context, user *user_model.User) (bool, error) {
+ // Non-local users are not allowed to change their username.
+ // Organizations can always be renamed.
+ if user.IsOrganization() || user.IsLocal() {
+ return true, nil
+ }
+
+ // If the user's authentication source is OAuth2 and that source allows for
+ // username changes then don't make a fuzz about it.
+ if !user.IsOAuth2() {
+ return false, nil
+ }
+
+ source, err := auth.GetSourceByID(ctx, user.LoginSource)
+ if err != nil {
+ return false, err
+ }
+ return source.Cfg.(*oauth2.Source).AllowUsernameChange, nil
+}
+
func renameUser(ctx context.Context, u *user_model.User, newUserName string, doerIsAdmin bool) error {
if newUserName == u.Name {
return nil
}
- // Non-local users are not allowed to change their username.
// If the doer is an admin, then allow the rename - they know better.
- if !doerIsAdmin && !u.IsOrganization() && !u.IsLocal() {
- // If the user's authentication source is OAuth2 and that source allows for
- // username changes then don't make a fuzz about it.
-
- if !u.IsOAuth2() {
- return user_model.ErrUserIsNotLocal{
- UID: u.ID,
- Name: u.Name,
- }
- }
-
- source, err := auth.GetSourceByID(ctx, u.LoginSource)
+ if !doerIsAdmin {
+ canRenamed, err := CanUserRename(ctx, u)
if err != nil {
return err
}
- sourceCfg := source.Cfg.(*oauth2.Source)
- if !sourceCfg.AllowUsernameChange {
+ if !canRenamed {
return user_model.ErrUserIsNotLocal{
UID: u.ID,
Name: u.Name,
diff --git a/templates/user/settings/profile.tmpl b/templates/user/settings/profile.tmpl
index d43a4d4c6e..49a349a4f1 100644
--- a/templates/user/settings/profile.tmpl
+++ b/templates/user/settings/profile.tmpl
@@ -9,8 +9,8 @@