diff --git a/assets/templates/items/share.tmpl b/assets/templates/items/share.tmpl index 6ffbd96..1f9d2bc 100644 --- a/assets/templates/items/share.tmpl +++ b/assets/templates/items/share.tmpl @@ -26,7 +26,7 @@

- {{ .baseUrl }}/ + {{ .baseUrl }}/item/share/

diff --git a/assets/templates/items/share_edit.tmpl b/assets/templates/items/share_edit.tmpl index 64365eb..319ed2e 100644 --- a/assets/templates/items/share_edit.tmpl +++ b/assets/templates/items/share_edit.tmpl @@ -26,7 +26,7 @@

- {{ .baseUrl }}/ + {{ .baseUrl }}/item/share/

diff --git a/assets/templates/items/shared.tmpl b/assets/templates/items/shared.tmpl new file mode 100644 index 0000000..8cca497 --- /dev/null +++ b/assets/templates/items/shared.tmpl @@ -0,0 +1,4 @@ +{{define "page:content"}} +Shared item FOUND + {{ .itemShare.ItemTitle}} +{{end}} diff --git a/assets/templates/items/shared_not_found.tmpl b/assets/templates/items/shared_not_found.tmpl new file mode 100644 index 0000000..a8f2f47 --- /dev/null +++ b/assets/templates/items/shared_not_found.tmpl @@ -0,0 +1,3 @@ +{{define "page:content"}} +Shared item not found +{{end}} diff --git a/cmd/web/handlers.go b/cmd/web/handlers.go index d2a48bb..ba80489 100644 --- a/cmd/web/handlers.go +++ b/cmd/web/handlers.go @@ -134,7 +134,7 @@ func (app *application) signup(w http.ResponseWriter, r *http.Request) { data := app.newTemplateData(r) data["Form"] = form - err := response.Page(w, http.StatusUnprocessableEntity, data, []string{"pages/signup.tmpl"}, "full") + err := response.GuestPage(w, http.StatusUnprocessableEntity, data, []string{"pages/signup.tmpl"}, "full") if err != nil { app.serverError(w, r, err) } @@ -183,7 +183,7 @@ func (app *application) login(w http.ResponseWriter, r *http.Request) { data := app.newTemplateData(r) data["Form"] = form - err := response.Page(w, http.StatusOK, data, []string{"pages/login.tmpl"}, "full") + err := response.GuestPage(w, http.StatusOK, data, []string{"pages/login.tmpl"}, "full") if err != nil { app.serverError(w, r, err) } @@ -280,7 +280,7 @@ func (app *application) forgottenPassword(w http.ResponseWriter, r *http.Request data := app.newTemplateData(r) data["Form"] = form - err := response.Page(w, http.StatusOK, data, []string{"pages/forgotten-password.tmpl"}, "full") + err := response.GuestPage(w, http.StatusOK, data, []string{"pages/forgotten-password.tmpl"}, "full") if err != nil { app.serverError(w, r, err) } @@ -343,7 +343,7 @@ func (app *application) forgottenPassword(w http.ResponseWriter, r *http.Request func (app *application) forgottenPasswordConfirmation(w http.ResponseWriter, r *http.Request) { data := app.newTemplateData(r) - err := response.Page(w, http.StatusOK, data, []string{"pages/forgotten-password-confirmation.tmpl"}, "full") + err := response.GuestPage(w, http.StatusOK, data, []string{"pages/forgotten-password-confirmation.tmpl"}, "full") if err != nil { app.serverError(w, r, err) } @@ -364,7 +364,7 @@ func (app *application) passwordReset(w http.ResponseWriter, r *http.Request) { data := app.newTemplateData(r) data["InvalidLink"] = true - err := response.Page(w, http.StatusUnprocessableEntity, data, []string{"pages/password-reset.tmpl"}, "full") + err := response.GuestPage(w, http.StatusUnprocessableEntity, data, []string{"pages/password-reset.tmpl"}, "full") if err != nil { app.serverError(w, r, err) } @@ -404,7 +404,7 @@ func (app *application) passwordReset(w http.ResponseWriter, r *http.Request) { data["Form"] = form data["PlaintextToken"] = plaintextToken - err := response.Page(w, http.StatusUnprocessableEntity, data, []string{"pages/password-reset.tmpl"}, "full") + err := response.GuestPage(w, http.StatusUnprocessableEntity, data, []string{"pages/password-reset.tmpl"}, "full") if err != nil { app.serverError(w, r, err) } @@ -436,7 +436,7 @@ func (app *application) passwordReset(w http.ResponseWriter, r *http.Request) { func (app *application) passwordResetConfirmation(w http.ResponseWriter, r *http.Request) { data := app.newTemplateData(r) - err := response.Page(w, http.StatusOK, data, []string{"pages/password-reset-confirmation.tmpl"}, "full") + err := response.GuestPage(w, http.StatusOK, data, []string{"pages/password-reset-confirmation.tmpl"}, "full") if err != nil { app.serverError(w, r, err) } diff --git a/cmd/web/items_handlers.go b/cmd/web/items_handlers.go index a2bf951..37502b5 100644 --- a/cmd/web/items_handlers.go +++ b/cmd/web/items_handlers.go @@ -3,6 +3,7 @@ package main import ( "bytes" "fmt" + "github.com/justinas/nosurf" "net/http" "strconv" "strings" @@ -1125,6 +1126,33 @@ func (app *application) itemShareEdit(w http.ResponseWriter, r *http.Request) { } } +func (app *application) itemShared(w http.ResponseWriter, r *http.Request) { + token := flow.Param(r.Context(), "token") + itemShareModel := models.NewItemShareModel(app.db) + + itemShare, found, _ := itemShareModel.OneByToken(token) + data := map[string]any{"CSRFToken": nosurf.Token(r)} + + if !found { + err := response.GuestPage(w, http.StatusOK, data, []string{"items/shared_not_found.tmpl"}) + if err != nil { + app.serverError(w, r, err) + } + } else { + //Check dates + //Does it need a password ? + switch r.Method { + case http.MethodGet: + data["itemShare"] = itemShare + err := response.GuestPage(w, http.StatusOK, data, []string{"items/shared.tmpl"}) + if err != nil { + app.serverError(w, r, err) + } + case http.MethodPost: + } + } +} + func (app *application) itemAddToDashboard(w http.ResponseWriter, r *http.Request) { itemModel := models.NewItemModel(app.db) itemId, _ := strconv.ParseInt(flow.Param(r.Context(), "item_id"), 10, 64) diff --git a/cmd/web/routes.go b/cmd/web/routes.go index 6f464b4..17f16b8 100644 --- a/cmd/web/routes.go +++ b/cmd/web/routes.go @@ -27,6 +27,7 @@ func (app *application) routes() http.Handler { mux.Group(func(mux *flow.Mux) { mux.Use(app.requireAnonymousUser) mux.HandleFunc("/login", app.login, "GET", "POST") + mux.HandleFunc("/item/shared/:token", app.itemShared, "GET", "POST") }) mux.Group(func(mux *flow.Mux) { diff --git a/internal/response/templates.go b/internal/response/templates.go index 7f1ead6..26e487e 100644 --- a/internal/response/templates.go +++ b/internal/response/templates.go @@ -52,6 +52,22 @@ func Fragment(pagePaths []string, templateName string, data any) (*bytes.Buffer, return buf, err } +func GuestPage(w http.ResponseWriter, status int, data any, pagePaths []string, templateNames ...string) error { + templateName := "full" + + if len(templateNames) > 0 { + templateName = templateNames[0] + } + return GuestPageWithHeaders(w, status, data, nil, pagePaths, templateName) +} + +func GuestPageWithHeaders(w http.ResponseWriter, status int, data any, headers http.Header, pagePaths []string, templateName string) error { + templateFile := templateName + ".tmpl" + pagePaths = append(pagePaths, templateFile) + + return NamedTemplateWithHeaders(w, status, data, headers, templateName, pagePaths) +} + func Page(w http.ResponseWriter, status int, data any, pagePaths []string, templateNames ...string) error { templateName := "base" diff --git a/models/itemshare.go b/models/itemshare.go index f2e3c5c..41a71b7 100644 --- a/models/itemshare.go +++ b/models/itemshare.go @@ -38,6 +38,23 @@ func (model *ItemShareModel) One(id int64) (*ItemShare, bool, error) { return &row, true, err } +func (model *ItemShareModel) OneByToken(token string) (*ItemShare, bool, error) { + ctx, cancel := database.GetContext() + defer cancel() + + var row ItemShare + + query := `SELECT bmi.title AS item_title, bmis.* FROM bm_item_shares bmis + INNER JOIN bm_item bmi ON bmis.item_id=bmi.id WHERE bmis.token = $1` + + err := model.DB.GetContext(ctx, &row, query, token) + if errors.Is(err, sql.ErrNoRows) { + return nil, false, nil + } + + return &row, true, err +} + func (model *ItemShareModel) Create(ItemShare *ItemShare) (int64, error) { ctx, cancel := database.GetContext() defer cancel()