fix: log /register listener failures instead of discarding them

A failing user.Register or user.Created listener is logged at Error level
with the user ID; the committed registration still succeeds.
This commit is contained in:
Jakub Zych
2026-10-22 03:07:22 +02:00
parent b6b7ac7534
commit e0b5ffe20d
4 changed files with 39 additions and 10 deletions

View File

@@ -682,8 +682,14 @@ func Register(app *backpack.App) http.HandlerFunc {
})
return
}
_ = FireRegisterEvent(r.Context(), app, user, fields)
_ = FireCreatedEvent(r.Context(), app, user)
// The row is committed: a failing listener is logged and never undoes
// or fails the registration, as in Winter.
if err := FireRegisterEvent(r.Context(), app, user, fields); err != nil {
pluginLog.Error("golem15.user: register listener failed", "user_id", user.ID, "err", err)
}
if err := FireCreatedEvent(r.Context(), app, user); err != nil {
pluginLog.Error("golem15.user: created listener failed", "user_id", user.ID, "err", err)
}
ctx := r.Context()
if mode == "user" {
vars := mailVars(displayName(user), "", "")

View File

@@ -133,8 +133,9 @@ func FinishLogin(ctx context.Context, app *backpack.App, db *gorm.DB, user *mode
// FireRegisterEvent fires classes.RegisterEvent for user with Payload set
// to a copy of fields without password and password_confirmation, and
// returns the listeners' error. /register ignores that error, as Winter
// does not stop a registration for a failing listener.
// returns the listeners' error. /register logs that error and continues, as
// Winter does not stop a registration for a failing listener. Payload is
// untrusted client input: it carries every extra key the client sent.
func FireRegisterEvent(ctx context.Context, app *backpack.App, user *models.User, fields map[string]any) error {
if app == nil || app.Events == nil {
return nil
@@ -149,8 +150,8 @@ func FireRegisterEvent(ctx context.Context, app *backpack.App, user *models.User
}
// FireCreatedEvent fires classes.CreatedEvent (user.Created) for user and
// returns the listeners' error. /register ignores that error, as it does
// for FireRegisterEvent.
// returns the listeners' error. /register logs that error and continues, as
// it does for FireRegisterEvent.
func FireCreatedEvent(ctx context.Context, app *backpack.App, user *models.User) error {
if app == nil || app.Events == nil {
return nil