package user import ( "context" httplib "dev.tandem.ws/tandem/camper/pkg/http" "fmt" "net/http" "time" "dev.tandem.ws/tandem/camper/pkg/auth" "dev.tandem.ws/tandem/camper/pkg/database" "dev.tandem.ws/tandem/camper/pkg/template" ) func serveLoginAttemptIndex(w http.ResponseWriter, r *http.Request, loginAttempt *auth.User, company *auth.Company, conn *database.Conn) { filters := newFilterForm() if err := filters.Parse(r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } loginAttempts, err := collectLoginAttemptEntries(r.Context(), conn, filters) if err != nil { panic(err) } index := &loginAttemptIndex{ Attempts: filters.buildCursor(loginAttempts), Filters: filters, } index.MustRender(w, r, loginAttempt, company) } func collectLoginAttemptEntries(ctx context.Context, conn *database.Conn, filters *filterForm) ([]*loginAttemptEntry, error) { where, args := filters.BuildQuery(nil) rows, err := conn.Query(ctx, fmt.Sprintf(` select attempt_id , user_name , host(ip_address) , attempted_at , success from company_login_attempt where (%s) order by attempted_at desc, attempt_id desc limit %d `, where, filters.PerPage()+1), args...) if err != nil { return nil, err } defer rows.Close() var entries []*loginAttemptEntry for rows.Next() { entry := &loginAttemptEntry{} if err = rows.Scan(&entry.ID, &entry.UserName, &entry.IPAddress, &entry.Date, &entry.Success); err != nil { return nil, err } entries = append(entries, entry) } return entries, nil } type loginAttemptEntry struct { ID int UserName string IPAddress string Date time.Time Success bool } type loginAttemptIndex struct { Attempts []*loginAttemptEntry Filters *filterForm } func (page *loginAttemptIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) { if httplib.IsHTMxRequest(r) && page.Filters.Paginated() { template.MustRenderAdminNoLayout(w, r, user, company, "user/results.gohtml", page) } else { template.MustRenderAdminFiles(w, r, user, company, page, "user/login-attempts.gohtml", "user/results.gohtml") } }