package handlers import ( "context" "net/http" "git.haelnorr.com/h/golib/cookies" "git.haelnorr.com/h/golib/hws" "git.haelnorr.com/h/golib/hwsauth" "github.com/pkg/errors" "github.com/uptrace/bun" "git.haelnorr.com/h/oslstats/internal/config" "git.haelnorr.com/h/oslstats/internal/db" "git.haelnorr.com/h/oslstats/internal/store" "git.haelnorr.com/h/oslstats/internal/throw" authview "git.haelnorr.com/h/oslstats/internal/view/authview" ) func Register( s *hws.Server, auth *hwsauth.Authenticator[*db.User, bun.Tx], conn *db.DB, cfg *config.Config, store *store.Store, ) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { attempts, exceeded, track := store.TrackRedirect(r, "/register", 3) if exceeded { err := track.Error(attempts) store.ClearRedirectTrack(r, "/register") throw.BadRequest(s, w, r, "Cookies appear to be blocked or disabled. Please enable cookies in your browser and try again", err) return } sessionCookie, err := r.Cookie("registration_session") if err != nil { http.Redirect(w, r, "/login", http.StatusSeeOther) return } details, ok := store.GetRegistrationSession(sessionCookie.Value) if !ok { http.Redirect(w, r, "/login", http.StatusSeeOther) return } store.ClearRedirectTrack(r, "/register") if r.Method == "GET" { renderSafely(authview.RegisterPage(details.DiscordUser.Username), s, r, w) return } username := r.FormValue("username") unique := false var user *db.User if ok := conn.WithNotifyTx(s, w, r, func(ctx context.Context, tx bun.Tx) (bool, error) { unique, err = db.IsUnique(ctx, tx, (*db.User)(nil), "username", username) if err != nil { return false, errors.Wrap(err, "db.IsUsernameUnique") } if !unique { return true, nil } user, err = db.CreateUser(ctx, tx, username, details.DiscordUser, db.NewAudit(r, nil)) if err != nil { return false, errors.Wrap(err, "db.CreateUser") } err = user.UpdateDiscordToken(ctx, tx, details.Token) if err != nil { return false, errors.Wrap(err, "db.UpdateDiscordToken") } if shouldGrantAdmin(user, cfg.RBAC) { err := ensureUserHasAdminRole(ctx, tx, user) if err != nil { return false, errors.Wrap(err, "ensureUserHasAdminRole") } } return true, nil }); !ok { return } if !unique { w.WriteHeader(http.StatusConflict) } else { err = auth.Login(w, r, user, true) if err != nil { throw.InternalServiceError(s, w, r, "Login failed", err) return } pageFrom := cookies.CheckPageFrom(w, r) w.Header().Set("HX-Redirect", pageFrom) } }, ) }