package web import ( "fmt" "net/http" "os" "time" "github.com/gorilla/handlers" "github.com/gorilla/mux" "github.com/rs/zerolog/log" "code.chrissexton.org/cws/cabinet/auth" "code.chrissexton.org/cws/cabinet/db" "github.com/stretchr/graceful" ) type Web struct { addr string db *db.Database salt string static http.FileSystem } func New(addr string, db *db.Database, static http.FileSystem) *Web { w := &Web{ addr: addr, db: db, static: static, } if err := db.MakeDB(); err != nil { log.Fatal(). Err(err). Msg("could not create database") } return w } type AuthMiddleware struct { web *Web db *db.Database } func NewAuthMiddleware(web *Web) AuthMiddleware { return AuthMiddleware{ web: web, db: web.db, } } func (aw *AuthMiddleware) Middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if aw.web.AuthCheck(r) { next.ServeHTTP(w, r) return } w.WriteHeader(401) fmt.Fprint(w, "invalid login") }) } func (web *Web) AuthCheck(r *http.Request) bool { key := r.Header.Get("X-Auth-Key") u, err := auth.GetByKey(web.db, key) if key == "" || err != nil { return false } log.Debug().Msgf("This shit is authed to user %s!", u.Name) return true } func (web *Web) routeSetup() http.Handler { r := mux.NewRouter() api := r.PathPrefix("/v1/").Subrouter() auth := NewAuthMiddleware(web) authedApi := r.PathPrefix("/v1/").Subrouter() authedApi.Use(auth.Middleware) api.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) { log.Debug().Msg("test json") }).Methods(http.MethodPost).HeadersRegexp("Content-Type", `application/json.*`) api.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) { log.Debug().Msg("test markdown") }).Methods(http.MethodPost).HeadersRegexp("Content-Type", `application/markdown.*`) // curl 'http://127.0.0.1:8080/v1/test' -X POST -H 'Accept: application/json, text/plain, */*' --compressed -H 'Content-Type: application/json;charset=utf-8' --data '{ "test": 1 }' authedApi.HandleFunc("/entries", web.newEntry).Methods(http.MethodPost). HeadersRegexp("Content-Type", "application/(text|json).*") authedApi.HandleFunc("/entries", web.newMarkdownEntry).Methods(http.MethodPost). HeadersRegexp("Content-Type", "application/markdown") authedApi.HandleFunc("/entries", web.newAdocEntry).Methods(http.MethodPost). HeadersRegexp("Content-Type", "application/asciidoc") authedApi.HandleFunc("/entries/{slug}", web.removeEntry).Methods(http.MethodDelete) authedApi.HandleFunc("/entries/{slug}", web.editEntry).Methods(http.MethodPut) api.HandleFunc("/entries/{slug}", web.getEntry).Methods(http.MethodGet) api.HandleFunc("/entries", web.allEntries).Methods(http.MethodGet) api.HandleFunc("/auth/new", web.newUser).Methods(http.MethodPost) api.HandleFunc("/auth", web.auth).Methods(http.MethodPost) r.PathPrefix("/").HandlerFunc(web.indexHandler("/index.html")) loggedRouter := handlers.LoggingHandler(os.Stdout, r) return loggedRouter } func (web *Web) Serve() { middle := web.routeSetup() log.Info().Str("addr", "http://"+web.addr).Msg("serving HTTP") graceful.Run(web.addr, 10*time.Second, middle) }