fix: an email change drops the address proof

- /update clears email_verified_at in the same write when the email changes (case-only changes keep it)
- the admin Users form clears it in FormBeforeUpdate; storedEmail helper shared with guardCredentials
- README: the proof follows the address, never mass-assigned, no backfill
This commit is contained in:
Jakub Zych
2026-10-21 14:01:52 +02:00
parent add1f7a806
commit a99cb467b7
3 changed files with 48 additions and 14 deletions

View File

@@ -471,17 +471,29 @@ func Update(app *backpack.App) http.HandlerFunc {
}
name := strField(fields, "name")
surname := strField(fields, "surname")
if err := gdb.WithContext(r.Context()).Model(user).Updates(map[string]any{
email := strField(fields, "email")
columns := map[string]any{
"name": name,
"surname": surname,
"email": strField(fields, "email"),
}).Error; err != nil {
"email": email,
}
// The proof of the address follows the address (D-27): a new email
// is unproven until its owner proves it. A change of letter case
// only keeps it, because email matching is case-insensitive.
emailChanged := !strings.EqualFold(email, user.Email)
if emailChanged {
columns["email_verified_at"] = nil
}
if err := gdb.WithContext(r.Context()).Model(user).Updates(columns).Error; err != nil {
writeOpaque500(w)
return
}
user.Name = &name
user.Surname = &surname
user.Email = strField(fields, "email")
user.Email = email
if emailChanged {
user.EmailVerifiedAt = nil
}
payload, err := apiArray(r.Context(), app, user)
if err != nil {
writeOpaque500(w)