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()