package handlers import ( "context" "net/http" "time" "git.haelnorr.com/h/golib/hws" "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/view/page" ) func Register( server *hws.Server, conn *bun.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 := errors.Errorf( "registration redirect loop detected after %d attempts | ip=%s ua=%s path=%s first_seen=%s ssl=%t", attempts, track.IP, track.UserAgent, track.Path, track.FirstSeen.Format("2006-01-02T15:04:05Z07:00"), cfg.HWSAuth.SSL, ) store.ClearRedirectTrack(r, "/register") throwError( server, w, r, http.StatusBadRequest, "Registration failed: Cookies appear to be blocked or disabled. Please enable cookies in your browser and try again. If this problem persists, try a different browser or contact support.", err, "warn", ) return } sessionCookie, err := r.Cookie("registration_session") if err != nil { http.Redirect(w, r, "/login", http.StatusSeeOther) return } details, ok := store.GetRegistrationSession(sessionCookie.Value) ok = false if !ok { http.Redirect(w, r, "/login", http.StatusSeeOther) return } store.ClearRedirectTrack(r, "/register") ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) defer cancel() tx, err := conn.BeginTx(ctx, nil) if err != nil { throwInternalServiceError(server, w, r, "Database transaction failed", err) return } defer tx.Rollback() method := r.Method if method == "GET" { unique, err := db.IsUsernameUnique(ctx, tx, details.DiscordUser.Username) if err != nil { throwInternalServiceError(server, w, r, "Database query failed", err) return } tx.Commit() page.Register(details.DiscordUser.Username, unique).Render(r.Context(), w) return } if method == "POST" { // TODO: register the user // get the form data // return } }, ) } func IsUsernameUnique( server *hws.Server, conn *bun.DB, cfg *config.Config, store *store.Store, ) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { username := r.FormValue("username") ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) defer cancel() tx, err := conn.BeginTx(ctx, nil) if err != nil { throwInternalServiceError(server, w, r, "Database transaction failed", err) return } defer tx.Rollback() unique, err := db.IsUsernameUnique(ctx, tx, username) if err != nil { throwInternalServiceError(server, w, r, "Database query failed", err) return } tx.Commit() if !unique { w.WriteHeader(http.StatusConflict) } else { w.WriteHeader(http.StatusOK) } }, ) }