package c import ( "bytes" "encoding/json" "fmt" "html/template" "io" "log" "net/http" "strings" "git.sr.ht/~evanj/cms/internal/m/user" ) type KeyCookie = string var KeyUserLogin KeyCookie = "KeyUserLogin" type Controller struct { log *log.Logger db dber } type dber interface { UserGet(username, password string) (user.User, error) UserGetFromToken(token string) (user.User, error) } func New(log *log.Logger, db dber) *Controller { return &Controller{ log, db, } } // TODO: You know why this is bad, change it. func (c *Controller) GetCookieUser2(w http.ResponseWriter, r *http.Request) (user.User, error) { cookie, err := r.Cookie(KeyUserLogin) if err != nil { return nil, err } user, err := c.db.UserGetFromToken(cookie.Value) if err != nil { return nil, err } return user, nil } func (c *Controller) GetCookieUser(w http.ResponseWriter, r *http.Request) (user.User, error) { user, err := c.GetCookieUser2(w, r) if err != nil { // No user in cookie, lets check in basic auth. u, p, ok := r.BasicAuth() if !ok { return nil, fmt.Errorf("no user available") } user, err = c.db.UserGet(u, p) if err != nil { return nil, err } } return user, nil } func (c *Controller) SetCookieUser(w http.ResponseWriter, r *http.Request, user user.User) { var tok string if user != nil { tok = user.Token() } http.SetCookie(w, &http.Cookie{ Name: KeyUserLogin, Value: tok, HttpOnly: true, MaxAge: 50000, Path: "/", }) } func (c *Controller) String(w http.ResponseWriter, r *http.Request, str string) { w.Header().Add("Content-Type", "text/plain") w.WriteHeader(http.StatusOK) fmt.Fprintf(w, str) } func (c *Controller) Error(w http.ResponseWriter, r *http.Request, code int, str string) { w.Header().Add("Content-Type", "text/plain") w.WriteHeader(code) fmt.Fprintf(w, str) } // TODO: You know why this is bad, change it. func (c *Controller) HTML(w http.ResponseWriter, r *http.Request, tmpl *template.Template, data interface{}) { // Check JSON wanted. if !strings.Contains(r.Header.Get("Accept"), "text/html") { c.JSON(w, r, data) return } buf := bytes.Buffer{} if err := tmpl.Execute(&buf, data); err != nil { c.log.Println(err) c.Error(w, r, http.StatusInternalServerError, "failed to build html response") return } switch r.Method { case "POST": w.Header().Add("Cache-Control", "no-cache, must-revalidate, max-age=0") break default: w.Header().Add("Cache-Control", "no-store, must-revalidate, max-age=0") break } w.Header().Add("Content-Type", "text/html") w.Header().Add("Pragma", "no-cache") w.Header().Add("Expires", "Sat, 26 Jul 1997 05:00:00 GMT") w.WriteHeader(http.StatusOK) io.Copy(w, &buf) } // TODO: You know why this is bad, change it. func (c *Controller) JSON(w http.ResponseWriter, r *http.Request, data interface{}) { bytes, err := json.Marshal(data) if err != nil { c.log.Println(err) c.Error(w, r, http.StatusInternalServerError, "failed to build json response") return } w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) w.Write(bytes) }