Skip to content
Snippets Groups Projects
Commit e8bfbd5c authored by gbe's avatar gbe
Browse files

Wire up new storage backend, fix /add

parent a3e57ebb
No related branches found
No related tags found
No related merge requests found
...@@ -18,7 +18,7 @@ import ( ...@@ -18,7 +18,7 @@ import (
"git.c3pb.de/gbe/invinoveritas/vino" "git.c3pb.de/gbe/invinoveritas/vino"
) )
func (h Handler) img() http.HandlerFunc { func (h Handler) img(read ReadStorage) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" { if r.Method != "GET" {
httpError(w, r, "bad method", errors.New(r.Method), http.StatusMethodNotAllowed) httpError(w, r, "bad method", errors.New(r.Method), http.StatusMethodNotAllowed)
...@@ -33,7 +33,7 @@ func (h Handler) img() http.HandlerFunc { ...@@ -33,7 +33,7 @@ func (h Handler) img() http.HandlerFunc {
return return
} }
img, err := h.storage.LoadPictureData(r.Context(), id) img, err := read.LoadPictureData(r.Context(), id)
if err != nil { if err != nil {
httpError(w, r, "can't load image", err, http.StatusNotFound) httpError(w, r, "can't load image", err, http.StatusNotFound)
return return
...@@ -51,7 +51,7 @@ func (h Handler) img() http.HandlerFunc { ...@@ -51,7 +51,7 @@ func (h Handler) img() http.HandlerFunc {
} }
} }
func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) { func (h Handler) detailsPost(write WriteStorage, read ReadStorage, w http.ResponseWriter, r *http.Request) {
action := r.FormValue("action") action := r.FormValue("action")
if strings.HasPrefix(action, "delete-comment-") { if strings.HasPrefix(action, "delete-comment-") {
level.Debug(log.Get(r)). level.Debug(log.Get(r)).
...@@ -65,7 +65,7 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) { ...@@ -65,7 +65,7 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) {
return return
} }
err = h.storage.DeleteComment(r.Context(), commentID) err = write.DeleteComment(r.Context(), commentID)
if err != nil { if err != nil {
httpError(w, r, "internal server error", err, http.StatusInternalServerError) httpError(w, r, "internal server error", err, http.StatusInternalServerError)
return return
...@@ -93,7 +93,7 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) { ...@@ -93,7 +93,7 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) {
} }
if action == "delete" { if action == "delete" {
err = h.storage.DeleteVino(r.Context(), id) err = write.DeleteVino(r.Context(), id)
if err != nil { if err != nil {
httpError(w, r, "can't delete wine", err, http.StatusInternalServerError) httpError(w, r, "can't delete wine", err, http.StatusInternalServerError)
return return
...@@ -103,7 +103,8 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) { ...@@ -103,7 +103,8 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) {
return return
} }
v, err := h.storage.LoadVino(r.Context(), id) // Read (possibly) existing data for updates
v, err := read.LoadVino(r.Context(), id)
if err != nil { if err != nil {
// Only log error here, just create a new entry. // Only log error here, just create a new entry.
level.Error(log.Get(r)). level.Error(log.Get(r)).
...@@ -140,7 +141,7 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) { ...@@ -140,7 +141,7 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) {
comment = comment[:1024] + "..." comment = comment[:1024] + "..."
} }
err = h.storage.StoreComment(r.Context(), &v, comment) err = write.StoreComment(r.Context(), &v, comment)
if err != nil { if err != nil {
httpError(w, r, "can't add comment", err, http.StatusInternalServerError) httpError(w, r, "can't add comment", err, http.StatusInternalServerError)
return return
...@@ -169,7 +170,7 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) { ...@@ -169,7 +170,7 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) {
} }
} }
err = h.storage.Store(r.Context(), &v) err = write.Store(r.Context(), &v)
if err != nil { if err != nil {
httpError(w, r, "can't store wine", err, http.StatusInternalServerError) httpError(w, r, "can't store wine", err, http.StatusInternalServerError)
return return
...@@ -178,7 +179,7 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) { ...@@ -178,7 +179,7 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/details?id="+r.FormValue("id"), http.StatusSeeOther) http.Redirect(w, r, "/details?id="+r.FormValue("id"), http.StatusSeeOther)
} }
func (h Handler) details() http.Handler { func (h Handler) details(read ReadStorage, write WriteStorage) http.Handler {
var ( var (
once sync.Once once sync.Once
tpl *template.Template tpl *template.Template
...@@ -195,7 +196,7 @@ func (h Handler) details() http.Handler { ...@@ -195,7 +196,7 @@ func (h Handler) details() http.Handler {
}) })
if r.Method == "POST" { if r.Method == "POST" {
h.detailsPost(w, r) h.detailsPost(write, read, w, r)
return return
} }
...@@ -212,7 +213,7 @@ func (h Handler) details() http.Handler { ...@@ -212,7 +213,7 @@ func (h Handler) details() http.Handler {
return return
} }
v, err := h.storage.LoadVino(r.Context(), id) v, err := read.LoadVino(r.Context(), id)
if err != nil { if err != nil {
httpError(w, r, "can't load wine data", err, http.StatusInternalServerError) httpError(w, r, "can't load wine data", err, http.StatusInternalServerError)
return return
......
...@@ -15,7 +15,7 @@ import ( ...@@ -15,7 +15,7 @@ import (
"git.c3pb.de/gbe/invinoveritas/vino" "git.c3pb.de/gbe/invinoveritas/vino"
) )
func (h Handler) index() http.Handler { func (h Handler) index(write WriteStorage, read ReadStorage) http.Handler {
var ( var (
once sync.Once once sync.Once
tpl *template.Template tpl *template.Template
...@@ -32,7 +32,7 @@ func (h Handler) index() http.Handler { ...@@ -32,7 +32,7 @@ func (h Handler) index() http.Handler {
}) })
if r.Method == "GET" { if r.Method == "GET" {
wines, err := h.storage.ListWines(r.Context()) wines, err := read.ListWines(r.Context())
if err != nil { if err != nil {
httpError(w, r, "can't list wines", err, http.StatusInternalServerError) httpError(w, r, "can't list wines", err, http.StatusInternalServerError)
return return
...@@ -107,7 +107,7 @@ func (h Handler) index() http.Handler { ...@@ -107,7 +107,7 @@ func (h Handler) index() http.Handler {
} }
} }
err = h.storage.Store(r.Context(), &vino) err = write.Store(r.Context(), &vino)
if err != nil { if err != nil {
httpError(w, r, fmt.Sprintf("can't store wine %q", vino), err, http.StatusInternalServerError) httpError(w, r, fmt.Sprintf("can't store wine %q", vino), err, http.StatusInternalServerError)
return return
......
package main package main
import ( import (
"net/http" "context"
"net/http/httptest" "net/http/httptest"
"net/url" "net/url"
"strings" "strings"
"testing" "testing"
"git.c3pb.de/gbe/invinoveritas/log" "git.c3pb.de/gbe/invinoveritas/log"
"git.c3pb.de/gbe/invinoveritas/vino"
) )
type testLogger struct { type testLogger struct {
...@@ -19,6 +20,24 @@ func (tl testLogger) Log(vals ...interface{}) error { ...@@ -19,6 +20,24 @@ func (tl testLogger) Log(vals ...interface{}) error {
return nil return nil
} }
type dummyStorage struct{}
func (d dummyStorage) Store(ctx context.Context, v *vino.Vino) error {
return nil
}
func (d dummyStorage) StoreComment(ctx context.Context, v *vino.Vino, txt string) error {
return nil
}
func (d dummyStorage) DeleteComment(ctx context.Context, id int) error {
return nil
}
func (d dummyStorage) DeleteVino(ctx context.Context, id int) error {
return nil
}
func TestHandler_Index_Add(t *testing.T) { func TestHandler_Index_Add(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
...@@ -28,14 +47,15 @@ func TestHandler_Index_Add(t *testing.T) { ...@@ -28,14 +47,15 @@ func TestHandler_Index_Add(t *testing.T) {
r := httptest.NewRequest("POST", "/add", strings.NewReader(data.Encode())) r := httptest.NewRequest("POST", "/add", strings.NewReader(data.Encode()))
r.Header.Set("Content-Type", "application/x-www-form-urlencoded") r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
h := Handler{} var h Handler
logger := testLogger{t} logger := testLogger{t}
hdlr := log.Request(h.index(), logger) hdlr := log.Request(h.index(dummyStorage{}, nil), logger)
hdlr.ServeHTTP(w, r) hdlr.ServeHTTP(w, r)
if w.Code != http.StatusOK { // We want a redirect to the index after storing something
if w.Code != 303 {
t.Error("unexpected HTTP status code:", w.Code) t.Error("unexpected HTTP status code:", w.Code)
} }
} }
...@@ -60,23 +60,21 @@ type userProvider interface { ...@@ -60,23 +60,21 @@ type userProvider interface {
UpdatePassword(ctx context.Context, name string, oldPW, newPW string) error UpdatePassword(ctx context.Context, name string, oldPW, newPW string) error
} }
type Storage interface { type WriteStorage interface {
DeleteComment(ctx context.Context, id int) error DeleteComment(ctx context.Context, id int) error
DeleteVino(ctx context.Context, id int) error DeleteVino(ctx context.Context, id int) error
StoreComment(ctx context.Context, v *vino.Vino, txt string) error
Store(ctx context.Context, v *vino.Vino) error
}
type ReadStorage interface {
ListWines(ctx context.Context) ([]vino.Vino, error) ListWines(ctx context.Context) ([]vino.Vino, error)
LoadVino(ctx context.Context, id int) (vino.Vino, error) LoadVino(ctx context.Context, id int) (vino.Vino, error)
LoadPictureData(ctx context.Context, id int) ([]byte, error) LoadPictureData(ctx context.Context, id int) ([]byte, error)
StoreComment(ctx context.Context, v *vino.Vino, txt string) error
Store(ctx context.Context, v *vino.Vino) error
} }
type Handler struct { type Handler struct {
storage Storage
db *sqlx.DB
sp sessionProvider sp sessionProvider
up userProvider up userProvider
} }
...@@ -184,26 +182,25 @@ func main() { ...@@ -184,26 +182,25 @@ func main() {
} }
handler := Handler{ handler := Handler{
storage: storage.Backend{
DB: db,
},
db: db,
sp: sessions, sp: sessions,
up: sessions, up: sessions,
} }
http.Handle("/details/img/", addCacheHeaders(wrapMiddleware(handler.img(), sessions, logger))) storage := storage.Backend{
http.Handle("/details/", wrapMiddleware(handler.details(), sessions, logger)) DB: db,
}
http.Handle("/details/img/", addCacheHeaders(wrapMiddleware(handler.img(storage), sessions, logger)))
http.Handle("/details/", wrapMiddleware(handler.details(storage, storage), sessions, logger))
http.Handle("/user/sessions", wrapMiddleware(handler.user(pageSessions), sessions, logger)) http.Handle("/user/sessions", wrapMiddleware(handler.user(pageSessions), sessions, logger))
http.Handle("/user/all-users", wrapMiddleware(handler.user(pageAllUsers), sessions, logger)) http.Handle("/user/all-users", wrapMiddleware(handler.user(pageAllUsers), sessions, logger))
http.Handle("/user/you", wrapMiddleware(handler.user(pageYou), sessions, logger)) http.Handle("/user/you", wrapMiddleware(handler.user(pageYou), sessions, logger))
index := wrapMiddleware(handler.index(), sessions, logger) index := wrapMiddleware(handler.index(storage, storage), sessions, logger)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" { if r.URL.Path != "/" && r.URL.Path != "/add" {
logged404.ServeHTTP(w, r) logged404.ServeHTTP(w, r)
return return
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment