Skip to content
Snippets Groups Projects
handler-index.go 3.28 KiB
Newer Older
gbe's avatar
gbe committed
package main

import (
gbe's avatar
gbe committed
	"context"
gbe's avatar
gbe committed
	"database/sql"
gbe's avatar
gbe committed
	"errors"
	"html/template"
	"net/http"
	"strconv"
gbe's avatar
gbe committed
	"github.com/go-kit/kit/log/level"

	"git.c3pb.de/gbe/invinoveritas/auth"
gbe's avatar
gbe committed
	"git.c3pb.de/gbe/invinoveritas/log"
gbe's avatar
gbe committed
	"git.c3pb.de/gbe/invinoveritas/storage"
	"git.c3pb.de/gbe/invinoveritas/storage/query"
gbe's avatar
gbe committed
func (h Handler) index() http.Handler {
	var (
		once sync.Once
		tpl  *template.Template
	)
gbe's avatar
gbe committed
	type templateData struct {
gbe's avatar
gbe committed
		Wines []query.ListWinesRow
gbe's avatar
gbe committed
		User  auth.User
	}

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		once.Do(func() {
			tpl = template.Must(template.ParseFS(templateFS, "templates/base.tpl", "templates/index.tpl"))
		})

gbe's avatar
gbe committed
		level.Debug(log.Get(r)).Log("user", auth.Get(r))

		if r.Method == "GET" {
gbe's avatar
gbe committed
			wines, err := h.Q.ListWines(r.Context())
			if err != nil {
gbe's avatar
gbe committed
				httpError(w, r, "can't list wines", err, http.StatusInternalServerError)
				return
			}

			w.Header().Add("content-type", "text/html")

gbe's avatar
gbe committed
			data := templateData{
				Wines: wines,
				User:  auth.Get(r),
			}

			err = tpl.ExecuteTemplate(w, "index.tpl", data)
			if err != nil {
gbe's avatar
gbe committed
				level.Error(log.Get(r)).
					Log("error", err,
						"msg", "can't execute index template")
		if r.Method != "POST" {
gbe's avatar
gbe committed
			httpError(w, r, "invalid method", errors.New(r.Method), http.StatusMethodNotAllowed)
		name := r.FormValue("name")
		if len(name) > 80 || len(name) == 0 {
			httpError(w, r, "bad name", errors.New("name must be between 1 and 80 chars"), http.StatusBadRequest)
		ratingVal := r.FormValue("rating")
gbe's avatar
gbe committed
			id     int64
			rating int
			err    error
		)
		if ratingVal != "" {
			rating, err = strconv.Atoi(ratingVal)
			if err != nil {
gbe's avatar
gbe committed
				httpError(w, r, "can't convert rating", err, http.StatusBadRequest)
		err = r.ParseMultipartForm(16 * 1024 * 1024)
gbe's avatar
gbe committed
		if err != nil {
gbe's avatar
gbe committed
			level.Warn(log.Get(r)).Log("error", err, "msg", "can't parse multipart form data")
gbe's avatar
gbe committed
		}
gbe's avatar
gbe committed
		err = h.Q.RunTx(r.Context(), func(ctx context.Context, q *query.Queries) error {
gbe's avatar
gbe committed
			params := query.InsertWineParams{
				Name: name,
			}
			if ratingVal != "" {
				params.Rating = sql.NullInt32{
					Int32: int32(rating),
					Valid: true,
				}
			}

gbe's avatar
gbe committed
			res, err := q.InsertWine(ctx, params)
gbe's avatar
gbe committed
			if err != nil {
				httpError(w, r, "can't store wine", err, http.StatusInternalServerError)

				return err
			}

gbe's avatar
gbe committed
			id, err = res.LastInsertId()
			if err != nil {
				httpError(w, r, "can't store wine", err, http.StatusInternalServerError)

				return err
			}

			level.Debug(log.Get(r)).Log("msg", "inserted new wine", "id", id)
gbe's avatar
gbe committed

			// See if there's an image file uploaded and persist it if that's the case.
			if r.MultipartForm == nil || len(r.MultipartForm.File["picture"]) == 0 {
				return nil
			}

			picFile, picHdr, err := r.FormFile("picture")
			if err != nil {
gbe's avatar
gbe committed
				httpError(w, r, "can't open picture file", err, http.StatusInternalServerError)
gbe's avatar
gbe committed
				return err
			}
			defer picFile.Close()

gbe's avatar
gbe committed
			err = storage.AddPicture(ctx, q, int(id), picFile, picHdr.Header.Get("Content-Type"))
			if err != nil {
gbe's avatar
gbe committed
				httpError(w, r, "can't load picture", err, http.StatusBadRequest)
gbe's avatar
gbe committed
				return err
gbe's avatar
gbe committed

gbe's avatar
gbe committed
			return nil
		})
gbe's avatar
gbe committed
		if err != nil {
			return
		}
gbe's avatar
gbe committed
		http.Redirect(w, r, "/details?id="+strconv.Itoa(int(id)), http.StatusSeeOther) // TODO: Is this the correct status?
gbe's avatar
gbe committed
}