Item sharing progress
This commit is contained in:
parent
34054eb1df
commit
007cb94891
9 changed files with 78 additions and 9 deletions
|
@ -26,7 +26,7 @@
|
||||||
<p style="margin-right: 6px">
|
<p style="margin-right: 6px">
|
||||||
<label for="share-token">Share Url</label>
|
<label for="share-token">Share Url</label>
|
||||||
<div class="input-container">
|
<div class="input-container">
|
||||||
<span class="prefix">{{ .baseUrl }}/</span>
|
<span class="prefix">{{ .baseUrl }}/item/share/</span>
|
||||||
<input name="Token" id="share-token" type="url" readonly="readonly" value="{{ .shareToken }}" />
|
<input name="Token" id="share-token" type="url" readonly="readonly" value="{{ .shareToken }}" />
|
||||||
</div>
|
</div>
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<p style="margin-right: 6px">
|
<p style="margin-right: 6px">
|
||||||
<label for="share-token">Share Url</label>
|
<label for="share-token">Share Url</label>
|
||||||
<div class="input-container">
|
<div class="input-container">
|
||||||
<span class="prefix">{{ .baseUrl }}/</span>
|
<span class="prefix">{{ .baseUrl }}/item/share/</span>
|
||||||
<input name="Token" id="share-token" type="url" readonly="readonly" value="{{ .itemShare.Token }}" />
|
<input name="Token" id="share-token" type="url" readonly="readonly" value="{{ .itemShare.Token }}" />
|
||||||
</div>
|
</div>
|
||||||
</p>
|
</p>
|
||||||
|
|
4
assets/templates/items/shared.tmpl
Normal file
4
assets/templates/items/shared.tmpl
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{{define "page:content"}}
|
||||||
|
Shared item FOUND
|
||||||
|
{{ .itemShare.ItemTitle}}
|
||||||
|
{{end}}
|
3
assets/templates/items/shared_not_found.tmpl
Normal file
3
assets/templates/items/shared_not_found.tmpl
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{{define "page:content"}}
|
||||||
|
Shared item not found
|
||||||
|
{{end}}
|
|
@ -134,7 +134,7 @@ func (app *application) signup(w http.ResponseWriter, r *http.Request) {
|
||||||
data := app.newTemplateData(r)
|
data := app.newTemplateData(r)
|
||||||
data["Form"] = form
|
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 {
|
if err != nil {
|
||||||
app.serverError(w, r, err)
|
app.serverError(w, r, err)
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ func (app *application) login(w http.ResponseWriter, r *http.Request) {
|
||||||
data := app.newTemplateData(r)
|
data := app.newTemplateData(r)
|
||||||
data["Form"] = form
|
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 {
|
if err != nil {
|
||||||
app.serverError(w, r, err)
|
app.serverError(w, r, err)
|
||||||
}
|
}
|
||||||
|
@ -280,7 +280,7 @@ func (app *application) forgottenPassword(w http.ResponseWriter, r *http.Request
|
||||||
data := app.newTemplateData(r)
|
data := app.newTemplateData(r)
|
||||||
data["Form"] = form
|
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 {
|
if err != nil {
|
||||||
app.serverError(w, r, err)
|
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) {
|
func (app *application) forgottenPasswordConfirmation(w http.ResponseWriter, r *http.Request) {
|
||||||
data := app.newTemplateData(r)
|
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 {
|
if err != nil {
|
||||||
app.serverError(w, r, err)
|
app.serverError(w, r, err)
|
||||||
}
|
}
|
||||||
|
@ -364,7 +364,7 @@ func (app *application) passwordReset(w http.ResponseWriter, r *http.Request) {
|
||||||
data := app.newTemplateData(r)
|
data := app.newTemplateData(r)
|
||||||
data["InvalidLink"] = true
|
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 {
|
if err != nil {
|
||||||
app.serverError(w, r, err)
|
app.serverError(w, r, err)
|
||||||
}
|
}
|
||||||
|
@ -404,7 +404,7 @@ func (app *application) passwordReset(w http.ResponseWriter, r *http.Request) {
|
||||||
data["Form"] = form
|
data["Form"] = form
|
||||||
data["PlaintextToken"] = plaintextToken
|
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 {
|
if err != nil {
|
||||||
app.serverError(w, r, err)
|
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) {
|
func (app *application) passwordResetConfirmation(w http.ResponseWriter, r *http.Request) {
|
||||||
data := app.newTemplateData(r)
|
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 {
|
if err != nil {
|
||||||
app.serverError(w, r, err)
|
app.serverError(w, r, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/justinas/nosurf"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"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) {
|
func (app *application) itemAddToDashboard(w http.ResponseWriter, r *http.Request) {
|
||||||
itemModel := models.NewItemModel(app.db)
|
itemModel := models.NewItemModel(app.db)
|
||||||
itemId, _ := strconv.ParseInt(flow.Param(r.Context(), "item_id"), 10, 64)
|
itemId, _ := strconv.ParseInt(flow.Param(r.Context(), "item_id"), 10, 64)
|
||||||
|
|
|
@ -27,6 +27,7 @@ func (app *application) routes() http.Handler {
|
||||||
mux.Group(func(mux *flow.Mux) {
|
mux.Group(func(mux *flow.Mux) {
|
||||||
mux.Use(app.requireAnonymousUser)
|
mux.Use(app.requireAnonymousUser)
|
||||||
mux.HandleFunc("/login", app.login, "GET", "POST")
|
mux.HandleFunc("/login", app.login, "GET", "POST")
|
||||||
|
mux.HandleFunc("/item/shared/:token", app.itemShared, "GET", "POST")
|
||||||
})
|
})
|
||||||
|
|
||||||
mux.Group(func(mux *flow.Mux) {
|
mux.Group(func(mux *flow.Mux) {
|
||||||
|
|
|
@ -52,6 +52,22 @@ func Fragment(pagePaths []string, templateName string, data any) (*bytes.Buffer,
|
||||||
return buf, err
|
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 {
|
func Page(w http.ResponseWriter, status int, data any, pagePaths []string, templateNames ...string) error {
|
||||||
templateName := "base"
|
templateName := "base"
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,23 @@ func (model *ItemShareModel) One(id int64) (*ItemShare, bool, error) {
|
||||||
return &row, true, err
|
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) {
|
func (model *ItemShareModel) Create(ItemShare *ItemShare) (int64, error) {
|
||||||
ctx, cancel := database.GetContext()
|
ctx, cancel := database.GetContext()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
Loading…
Add table
Reference in a new issue