feat: carry the register input on RegisterEvent and export the registration steps

- RegisterEvent.Payload: a copy of the register input without password and
  password_confirmation (Winter's golem15.user.register data array)
- RegisterUser, RegisterOptions, FireRegisterEvent, IssueToken and APIArray:
  the steps POST /register runs, now called by Register itself; its status
  codes and bodies are unchanged
- README documents the exports and Payload
This commit is contained in:
Jakub Zych
2026-10-03 07:12:00 +02:00
parent c258e9fade
commit d80d7990f6
5 changed files with 235 additions and 42 deletions

View File

@@ -601,7 +601,7 @@ func MarketingConsent(app *backpack.App) http.HandlerFunc {
// Register creates an account and follows activate_mode: auto, user, or admin.
func Register(app *backpack.App) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
gdb, secret, ok := sessionDeps(w, app)
gdb, _, ok := sessionDeps(w, app)
if !ok {
return
}
@@ -623,8 +623,7 @@ func Register(app *backpack.App) http.HandlerFunc {
if _, exists := fields["password_confirmation"]; !exists {
fields["password_confirmation"] = fields["password"]
}
rules := (models.User{}).Rules()
errs, err := lagoon.Validate(r.Context(), gdb, models.User{}, rules, fields, appTranslator(app))
user, errs, err := RegisterUser(r.Context(), app, gdb, fields, RegisterOptions{Activate: mode == "auto", IP: ip})
if err != nil {
writeOpaque500(w)
return
@@ -636,40 +635,7 @@ func Register(app *backpack.App) http.HandlerFunc {
})
return
}
password := strField(fields, "password")
cost := 10
if app.Config != nil && app.Config.Int("golem15.user.password.bcrypt_cost") > 0 {
cost = app.Config.Int("golem15.user.password.bcrypt_cost")
}
hashed, err := bouncer.HashPassword(cost, password)
if err != nil {
writeOpaque500(w)
return
}
fields["password"] = hashed
if ip != "" {
fields["created_ip_address"] = ip
fields["last_ip_address"] = ip
}
user := &models.User{}
production := app.Config == nil || !app.Config.Bool("app.debug")
if err := lagoon.Fill(user, user.Fillable(), fields, production); err != nil {
writeOpaque500(w)
return
}
user.HasSelfSetPassword = true
if mode == "auto" {
user.IsActivated = true
now := time.Now()
user.ActivatedAt = &now
}
if err := gdb.WithContext(r.Context()).Create(user).Error; err != nil {
writeOpaque500(w)
return
}
if app.Events != nil {
_ = app.Events.Fire(r.Context(), &classes.RegisterEvent{User: user})
}
_ = FireRegisterEvent(r.Context(), app, user, fields)
ctx := r.Context()
if mode == "user" {
vars := mailVars(displayName(user), "", "")
@@ -685,12 +651,12 @@ func Register(app *backpack.App) http.HandlerFunc {
return
}
if mode == "auto" || !require {
token, err := mintFor(app, secret, user, requestURL(r))
token, err := IssueToken(app, user, r)
if err != nil {
writeOpaque500(w)
return
}
payload, err := apiArray(ctx, app, user)
payload, err := APIArray(ctx, app, user)
if err != nil {
writeOpaque500(w)
return