fix: atomic unlink with the PHP last-identity rule

- OAuthIdentitiesDestroy locks the users row (SELECT ... FOR UPDATE) and runs
  the PHP guarded DELETE in one transaction: a self-set password or another
  identity allows the unlink; otherwise 409 with the unchanged body
- the default allow-list adds microsoft, and an OAuthProviderSource's known
  names are used when the host passes no Providers
- TestOAuthIdentitiesDestroyLastIdentityWithPassword (204),
  TestOAuthIdentitiesDestroyConcurrentSmoke; README
- gofmt of the forgotPasswordBody line touched in the previous commit
This commit is contained in:
Jakub Zych
2026-10-20 23:05:14 +02:00
parent 78a867bccb
commit 174161895e
4 changed files with 144 additions and 25 deletions

View File

@@ -241,7 +241,7 @@ func oauthProviderSource(app *backpack.App) (classes.OAuthProviderSource, bool)
return src, ok && src != nil
}
const forgotPasswordBody ="If that email exists, a reset link has been sent."
const forgotPasswordBody = "If that email exists, a reset link has been sent."
// ForgotPassword always returns the same 200 body. A real account also gets a reset mail.
func ForgotPassword(app *backpack.App) http.HandlerFunc {