package serve import ( "context" "log/slog" "net" "net/http" "strings" "gopkg.awl.red/bizdex/db" ) // TODO: fix const specialLocal = "[::1]" func mkMiddlewareSession(d *db.DB) func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie("Session") if err != nil { w.WriteHeader(http.StatusUnauthorized) slog.Info("no session cookie", "err", err) return } session, err := d.GetSession(cookie.Value, d.GetConfig()) if err != nil || session == nil { w.WriteHeader(http.StatusUnauthorized) slog.Info("error middleware session", "err", err) return } next.ServeHTTP(w, r.WithContext(context.WithValue(r.Context(), "auth", *session))) }) } } func mkMiddlewareAllows(d *db.DB) func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { cfg := d.GetConfig() lenPolicies := len(cfg.UsagePolicies) slog.Info("policies", "count", lenPolicies, "plcystruct", cfg.UsagePolicies) if lenPolicies == 0 { next.ServeHTTP(w, r) return } slog.Info(r.RemoteAddr) lastCol := strings.LastIndex(r.RemoteAddr, ":") remoteIp := r.RemoteAddr if lastCol != -1 { remoteIp = r.RemoteAddr[:lastCol] } parsedRemote := net.ParseIP(remoteIp) isSpecialIp6Local := remoteIp == specialLocal if parsedRemote == nil && !isSpecialIp6Local { slog.Error("bad remote ip", "remote_ip", remoteIp) return } for _, policy := range cfg.UsagePolicies { if policy.ExtraType != "allow_blocks" { continue } for extra := range strings.SplitSeq(policy.Extra, ",") { if isSpecialIp6Local && extra == remoteIp { next.ServeHTTP(w, r) return } _, cidr, err := net.ParseCIDR(extra) if err != nil { slog.Error("bad allow block in usage limits config", "block", extra) continue } if cidr.Contains(parsedRemote) { slog.Info("allowed ip", "ip", remoteIp, "block", cidr.String()) next.ServeHTTP(w, r) return } } } slog.Info("dropped", "ip", remoteIp) w.WriteHeader(http.StatusTooManyRequests) // TODO: its not that they can request later successfully // its that the policy says never to serve the user // see what convention is in this case }) } } // func (m middlewares) Srv(next http.Handler) http.Handler { // return http.HandlerFunc(func(w http.ResponseWriter, rOrig *http.Request) { // func compose(mws ...func(next http.Handler) http.HandlerFunc) func(next http.Handler) { // if len(mws) == 0 { // panic("compose called with no handlers") // } // // if len(mws) == 1 { // // return mws[0] // // } // var acc func(next http.Handler) // for i, elt := range slices.Backward(mws) { // if i == 0 { // acc = elt // } // acc = elt(acc) // } // return acc // }