From 17de55c5c2f8b54384e0e5d7d3e63ad636f27a86 Mon Sep 17 00:00:00 2001 From: Amy Gale Ruth Bowersox Date: Tue, 21 Apr 2026 15:40:50 -0500 Subject: [PATCH] Admin can now change the user name of a user account. Closes issue #2. --- database/audit.go | 1 + database/auditref.yaml | 2 ++ database/user.go | 12 ++++++++++++ sysadmin.go | 10 ++++++++++ ui/dialogs/admin_user.yaml | 9 +++++++++ 5 files changed, 34 insertions(+) diff --git a/database/audit.go b/database/audit.go index d0efb00..bb13c12 100644 --- a/database/audit.go +++ b/database/audit.go @@ -93,6 +93,7 @@ const ( AuditAdminChangeUserAccount = 111 AuditAdminSetAccountSecurity = 112 AuditAdminLockUnlockAccount = 113 + AuditAdminSetUserName = 114 AuditCommunityCreate = 201 AuditCommunitySetMembership = 202 AuditCommunityContactInfo = 203 diff --git a/database/auditref.yaml b/database/auditref.yaml index bae44be..575a32b 100644 --- a/database/auditref.yaml +++ b/database/auditref.yaml @@ -44,6 +44,8 @@ auditReference: text: "Admin Set Account Security" - code: 113 text: "Admin Lock/Unlock Account" + - code: 114 + text: "Admin Set User Name" - code: 201 text: "Create New Community" - code: 202 diff --git a/database/user.go b/database/user.go index 151955f..cc15104 100644 --- a/database/user.go +++ b/database/user.go @@ -381,6 +381,18 @@ func (u *User) Prefs(ctx context.Context) (*UserPrefs, error) { return u.prefs, nil } +func (u *User) SetUsername(ctx context.Context, username string, setter *User, ipaddr string) error { + u.Mutex.Lock() + _, err := amdb.ExecContext(ctx, "UPDATE users SET username = ? WHERE uid = ?", username, u.Uid) + u.Mutex.Unlock() + if err == nil { + u.Username = username + AmStoreAudit(AmNewAudit(AuditAdminSetUserName, setter.Uid, ipaddr, fmt.Sprintf("uid=%d", u.Uid), + fmt.Sprintf("newname=%s", username))) + } + return err +} + /* SetProfileData sets the "profile" variables for this user. * Parameters: * ctx - Standard Go context value. diff --git a/sysadmin.go b/sysadmin.go index ff77c8e..b89d9fe 100644 --- a/sysadmin.go +++ b/sysadmin.go @@ -249,6 +249,7 @@ func UserManagementForm(ctxt ui.AmContext) (string, any) { var prefs *database.UserPrefs prefs, err = user.Prefs(ctxt.Ctx()) if err == nil { + dlg.Field("user").Value = user.Username dlg.Field("remind").Value = user.PassReminder dlg.Field("base_lvl").SetLevel(user.BaseLevel) dlg.Field("verify_email").SetChecked(user.VerifyEMail) @@ -327,6 +328,12 @@ func UserManagementSave(ctxt ui.AmContext) (string, any) { if err == nil { var prefs *database.UserPrefs prefs, err = user.Prefs(ctxt.Ctx()) + if err == nil && user.Username != dlg.Field("user").Value { + u2, e := database.AmGetUserByName(ctxt.Ctx(), dlg.Field("user").Value, nil) + if e == nil && u2 != nil { + err = errors.New("user name is already in use") + } + } if err == nil && !(dlg.Field("pass1").IsEmpty() && dlg.Field("pass2").IsEmpty()) { p1 := dlg.Field("pass1").Value if p1 == dlg.Field("pass2").Value { @@ -378,6 +385,9 @@ func UserManagementSave(ctxt ui.AmContext) (string, any) { err = user.SaveFlags(ctxt.Ctx(), nf) } } + if err == nil && user.Username != dlg.Field("user").Value { + err = user.SetUsername(ctxt.Ctx(), dlg.Field("user").Value, ctxt.CurrentUser(), ctxt.RemoteIP()) + } if err == nil { err = user.SetProfileData(ctxt.Ctx(), dlg.Field("remind").Value, dlg.Field("dob").AsDate(), dlg.Field("descr").ValPtr(), ctxt.CurrentUser(), ctxt.RemoteIP()) diff --git a/ui/dialogs/admin_user.yaml b/ui/dialogs/admin_user.yaml index 8e2c71d..d2def22 100644 --- a/ui/dialogs/admin_user.yaml +++ b/ui/dialogs/admin_user.yaml @@ -15,6 +15,15 @@ title: "Modify User Account" subtitle: "User: [USERNAME]" action: "/sysadmin/users/[USERNAME]" fields: + - type: "header" + name: "header0" + caption: "User Information" + - type: "ams_id" + name: "user" + caption: "User Name" + required: true + size: 32 + maxlength: 64 - type: "header" name: "header1" caption: "Security Information"