Fix bug when updating user email (#36058) (#36066)

Backport #36058 by @lunny

Fix #20390 

We should use `ReplacePrimaryEmailAddress` instead of
`AdminAddOrSetPrimaryEmailAddress` when modify user's email from admin
panel. And also we need a database transaction to keep deletion and
insertion succeed at the same time.

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
Giteabot 2025-12-02 09:57:21 +08:00 committed by GitHub
parent b276849cd8
commit 45cdc5d8fd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 34 deletions

View File

@ -409,7 +409,7 @@ func EditUserPost(ctx *context.Context) {
} }
if form.Email != "" { if form.Email != "" {
if err := user_service.AdminAddOrSetPrimaryEmailAddress(ctx, u, form.Email); err != nil { if err := user_service.ReplacePrimaryEmailAddress(ctx, u, form.Email); err != nil {
switch { switch {
case user_model.IsErrEmailCharIsNotSupported(err), user_model.IsErrEmailInvalid(err): case user_model.IsErrEmailCharIsNotSupported(err), user_model.IsErrEmailInvalid(err):
ctx.Data["Err_Email"] = true ctx.Data["Err_Email"] = true

View File

@ -77,43 +77,44 @@ func ReplacePrimaryEmailAddress(ctx context.Context, u *user_model.User, emailSt
return err return err
} }
if !u.IsOrganization() { return db.WithTx(ctx, func(ctx context.Context) error {
// Check if address exists already if !u.IsOrganization() {
email, err := user_model.GetEmailAddressByEmail(ctx, emailStr) // Check if address exists already
if err != nil && !errors.Is(err, util.ErrNotExist) { email, err := user_model.GetEmailAddressByEmail(ctx, emailStr)
return err if err != nil && !errors.Is(err, util.ErrNotExist) {
} return err
if email != nil { }
if email.IsPrimary && email.UID == u.ID { if email != nil {
return nil if email.IsPrimary && email.UID == u.ID {
return nil
}
return user_model.ErrEmailAlreadyUsed{Email: emailStr}
}
// Remove old primary address
primary, err := user_model.GetPrimaryEmailAddressOfUser(ctx, u.ID)
if err != nil {
return err
}
if _, err := db.DeleteByID[user_model.EmailAddress](ctx, primary.ID); err != nil {
return err
}
// Insert new primary address
if _, err := user_model.InsertEmailAddress(ctx, &user_model.EmailAddress{
UID: u.ID,
Email: emailStr,
IsActivated: true,
IsPrimary: true,
}); err != nil {
return err
} }
return user_model.ErrEmailAlreadyUsed{Email: emailStr}
} }
// Remove old primary address u.Email = emailStr
primary, err := user_model.GetPrimaryEmailAddressOfUser(ctx, u.ID)
if err != nil {
return err
}
if _, err := db.DeleteByID[user_model.EmailAddress](ctx, primary.ID); err != nil {
return err
}
// Insert new primary address return user_model.UpdateUserCols(ctx, u, "email")
email = &user_model.EmailAddress{ })
UID: u.ID,
Email: emailStr,
IsActivated: true,
IsPrimary: true,
}
if _, err := user_model.InsertEmailAddress(ctx, email); err != nil {
return err
}
}
u.Email = emailStr
return user_model.UpdateUserCols(ctx, u, "email")
} }
func AddEmailAddresses(ctx context.Context, u *user_model.User, emails []string) error { func AddEmailAddresses(ctx context.Context, u *user_model.User, emails []string) error {