package middleware import ( "net/http" "strings" "git.kirsle.net/apps/gophertype/pkg/responses" "git.kirsle.net/apps/gophertype/pkg/session" "git.kirsle.net/apps/gophertype/pkg/settings" ) // URL suffixes to allow to bypass the age gate middleware. var ageGateSuffixes = []string{ "/blog.rss", // Allow public access to RSS and Atom feeds. "/blog.atom", "/blog.json", ".js", ".css", ".txt", ".ico", ".png", ".jpg", ".jpeg", ".gif", ".mp4", ".webm", ".ttf", ".eot", ".svg", ".woff", ".woff2", } // AgeGate is a middleware generator that does age verification for NSFW sites. // Single GET requests with ?over18=1 parameter may skip the middleware check. func AgeGate(next http.Handler) http.Handler { middleware := func(w http.ResponseWriter, r *http.Request) { s := settings.Current if !s.NSFW { next.ServeHTTP(w, r) return } path := r.URL.Path // Let the age-verify handler catch its route. if strings.HasPrefix(path, "/age-verify") { next.ServeHTTP(w, r) return } // Allow static file requests to skip the check. for _, suffix := range ageGateSuffixes { if strings.HasSuffix(path, suffix) { next.ServeHTTP(w, r) return } } // POST requests are permitted (e.g. post a comment on a /?over18=1 page) if r.Method == http.MethodPost { next.ServeHTTP(w, r) return } // Finally, check if they've confirmed their age on the age-verify handler. ses := session.Get(r) if val, _ := ses.Values["age-ok"].(bool); !val { // They haven't been verified. Redirect them to the age-verify handler. if r.FormValue("over18") == "" && r.Header.Get("X-Over-18") == "" { responses.Redirect(w, r, "/age-verify?next="+path) return } } next.ServeHTTP(w, r) } return http.HandlerFunc(middleware) }