From 77663735a4328880fa2f6491c88b4fd49bc4f1db Mon Sep 17 00:00:00 2001 From: roberto Date: Wed, 16 Apr 2025 18:04:28 +0200 Subject: [PATCH] Progress on item sharing --- assets/static/css/guest.css | 160 +++++++++++++++++++++++++ assets/static/css/main.css | 5 - assets/templates/guest.tmpl | 13 +- assets/templates/items/share.tmpl | 2 +- assets/templates/items/share_edit.tmpl | 2 +- assets/templates/items/shared.tmpl | 8 +- cmd/web/config.go | 7 +- cmd/web/items_handlers.go | 17 ++- cmd/web/main.go | 3 +- models/itemshare.go | 26 ++-- 10 files changed, 212 insertions(+), 31 deletions(-) create mode 100644 assets/static/css/guest.css diff --git a/assets/static/css/guest.css b/assets/static/css/guest.css new file mode 100644 index 0000000..d336d72 --- /dev/null +++ b/assets/static/css/guest.css @@ -0,0 +1,160 @@ +/* Global variables. */ +:root, +::backdrop { + /* Set sans-serif & mono fonts */ + --sans-font: -apple-system, BlinkMacSystemFont, "Avenir Next", Avenir, + "Nimbus Sans L", Roboto, "Noto Sans", "Segoe UI", Arial, Helvetica, + "Helvetica Neue", sans-serif; + --mono-font: Consolas, Menlo, Monaco, "Andale Mono", "Ubuntu Mono", monospace; + --standard-border-radius: 5px; + + /* Default (light) theme */ + --bg: #fff; + --primary-color: #2b5797; +} + +/* Reset */ + +/* Box sizing rules */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +/* Prevent font size inflation */ +html { + -moz-text-size-adjust: none; + -webkit-text-size-adjust: none; + text-size-adjust: none; +} + +/* Remove default margin in favour of better control in authored CSS */ +body, h1, h2, h3, h4, p, +figure, blockquote, dl, dd { + margin-block-end: 0; +} + +/* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */ +ul[role='list'], +ol[role='list'] { + list-style: none; +} + +/* Set core body defaults */ +body { + margin: 0; + min-height: 100vh; + line-height: 1.5; +} + +/* Set shorter line heights on headings and interactive elements */ +h1, h2, h3, h4, +input, label { + line-height: 1.1; +} + +/* Balance text wrapping on headings */ +h1, h2, +h3, h4 { + text-wrap: balance; +} + +/* A elements that don't have a class get default styles */ +a:not([class]) { + text-decoration-skip-ink: auto; + color: currentColor; +} + +/* Inherit fonts for inputs and buttons */ +input, button, +textarea, select { + font-family: inherit; + font-size: inherit; +} + +/* Anything that has been anchored to should have extra scroll margin */ +:target { + scroll-margin-block: 5ex; +} + +h1,h2,h3,h4,h5,h6, form { + margin: 0; + padding: 0; +} + +a { + text-decoration: none; + color: var(--primary-color); +} +/* End reset */ + + +html { + font-family: var(--sans-font), sans-serif; + scroll-behavior: smooth; + overflow-x: hidden; + box-sizing: border-box; +} + +.logo { + width: 32px; + float: left; + padding-right: 10px; +} + +#page-top-bar { + display: flex; + align-items: center; + z-index: 1; + height: 50px; + background-color: var(--primary-color); + position: fixed; + width: 100%; +} + +#app-title { + height: 50px; + background-color: var(--primary-color); + color: #ffffff; + font-size: 22px; + font-weight: bold; + padding-left: 8px; + display: flex; + align-items: center; +} + +#app-title h5 { + color: #ffffff; + font-size: 22px; + font-weight: bold; +} + +#page-title { + color: #ffffff; + font-size: 20px; +} + +#page-content { + padding-top: 60px; + padding-left: 4px; + padding-right: 4px; +} + +.item-detail dt { + font-weight: bold; +} + +.show-large { + display: none; +} + +/* Large */ +@media (min-width:992px) { + .show-large { + display: inline !important; + } + #app-title { + width: 200px; + } +} \ No newline at end of file diff --git a/assets/static/css/main.css b/assets/static/css/main.css index ec70a27..398b153 100644 --- a/assets/static/css/main.css +++ b/assets/static/css/main.css @@ -104,11 +104,6 @@ textarea, select { font-size: inherit; } -/* Make sure textareas without a rows attribute are not tiny */ -/*textarea:not([rows]) { - min-height: 10em; -}*/ - /* Anything that has been anchored to should have extra scroll margin */ :target { scroll-margin-block: 5ex; diff --git a/assets/templates/guest.tmpl b/assets/templates/guest.tmpl index ef15439..0d796e0 100644 --- a/assets/templates/guest.tmpl +++ b/assets/templates/guest.tmpl @@ -6,7 +6,7 @@ - + {{block "page:meta" . }} @@ -15,8 +15,15 @@ }} - Title -
+
+
+
BrainMinder
+
+
+
Shared item : {{ .itemShare.ItemTitle}}
+
+
+
{{template "page:content" .}}
diff --git a/assets/templates/items/share.tmpl b/assets/templates/items/share.tmpl index 1f9d2bc..d4df542 100644 --- a/assets/templates/items/share.tmpl +++ b/assets/templates/items/share.tmpl @@ -26,7 +26,7 @@

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

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

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

diff --git a/assets/templates/items/shared.tmpl b/assets/templates/items/shared.tmpl index 8cca497..ea8da70 100644 --- a/assets/templates/items/shared.tmpl +++ b/assets/templates/items/shared.tmpl @@ -1,4 +1,8 @@ {{define "page:content"}} -Shared item FOUND - {{ .itemShare.ItemTitle}} +
+
Summary
+
{{ .itemShare.ItemSummaryRendered | safeHTML}}
+
Description
+
{{ .itemShare.ItemDescriptionRendered | safeHTML}}
+
{{end}} diff --git a/cmd/web/config.go b/cmd/web/config.go index b80f91c..913b32d 100644 --- a/cmd/web/config.go +++ b/cmd/web/config.go @@ -1,9 +1,10 @@ package main type config struct { - baseURL string - httpPort int - cookie struct { + publicBaseURL string + baseURL string + httpPort int + cookie struct { secretKey string } db struct { diff --git a/cmd/web/items_handlers.go b/cmd/web/items_handlers.go index 8c4fcfe..1ea7ac4 100644 --- a/cmd/web/items_handlers.go +++ b/cmd/web/items_handlers.go @@ -1,6 +1,7 @@ package main import ( + "brainminder.speedtech.it/internal/password" "bytes" "fmt" "github.com/justinas/nosurf" @@ -993,7 +994,7 @@ func (app *application) itemShare(w http.ResponseWriter, r *http.Request) { data := app.newTemplateData(r) data["item"] = item - data["baseUrl"] = app.config.baseURL + data["publicBaseUrl"] = app.config.publicBaseURL switch r.Method { case http.MethodGet: @@ -1023,10 +1024,14 @@ func (app *application) itemShare(w http.ResponseWriter, r *http.Request) { return } + hashedPassword := "" + if itemShareFromForm.Password != "" { + hashedPassword, _ = password.Hash(itemShareFromForm.Password) + } itemShare := &models.ItemShare{ ItemId: itemId, Token: itemShareFromForm.Token, - Password: itemShareFromForm.Password, + Password: hashedPassword, PermissionEdit: itemShareFromForm.PermissionEdit, StartDatetime: itemShareFromForm.StartDatetime, EndDatetime: itemShareFromForm.EndDatetime, @@ -1065,7 +1070,7 @@ func (app *application) itemShareEdit(w http.ResponseWriter, r *http.Request) { data := app.newTemplateData(r) data["itemShare"] = itemShare - data["baseUrl"] = app.config.baseURL + data["publicBaseUrl"] = app.config.publicBaseURL switch r.Method { case http.MethodGet: @@ -1093,9 +1098,13 @@ func (app *application) itemShareEdit(w http.ResponseWriter, r *http.Request) { return } + hashedPassword := "" + if itemShareFromForm.Password != "" { + hashedPassword, _ = password.Hash(itemShareFromForm.Password) + } itemShare := &models.ItemShare{ Token: itemShareFromForm.Token, - Password: itemShareFromForm.Password, + Password: hashedPassword, PermissionEdit: itemShareFromForm.PermissionEdit, StartDatetime: itemShareFromForm.StartDatetime, EndDatetime: itemShareFromForm.EndDatetime, diff --git a/cmd/web/main.go b/cmd/web/main.go index 7d4b28e..216ee6a 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -33,7 +33,8 @@ func main() { func run(logger *slog.Logger) error { var cfg config - cfg.baseURL = env.GetString("BASE_URL", "http://localhost:4445") + cfg.publicBaseURL = env.GetString("PUBLIC_BASE_URL", "http://localhost:4445") + cfg.baseURL = env.GetString("BASE_URL", "http://localhost") cfg.httpPort = env.GetInt("HTTP_PORT", 4445) cfg.cookie.secretKey = env.GetString("COOKIE_SECRET_KEY", `CHANGE_THIS_COOKIE_KEY`) cfg.db.dsn = env.GetString("DB_DSN", "db.sqlite") diff --git a/models/itemshare.go b/models/itemshare.go index 41a71b7..e36082b 100644 --- a/models/itemshare.go +++ b/models/itemshare.go @@ -11,14 +11,16 @@ type ItemShareModel struct { } type ItemShare struct { - Id int64 `db:"id"` - Token string `db:"token"` - ItemId int64 `db:"item_id"` - PermissionEdit int `db:"permission_edit"` - StartDatetime string `db:"start_datetime"` - EndDatetime string `db:"end_datetime"` - Password string `db:"password"` - ItemTitle string `db:"item_title"` + Id int64 `db:"id"` + Token string `db:"token"` + ItemId int64 `db:"item_id"` + PermissionEdit int `db:"permission_edit"` + StartDatetime string `db:"start_datetime"` + EndDatetime string `db:"end_datetime"` + Password string `db:"password"` + ItemTitle string `db:"item_title"` + ItemSummaryRendered string `db:"item_summary_rendered"` + ItemDescriptionRendered string `db:"item_description_rendered"` } func (model *ItemShareModel) One(id int64) (*ItemShare, bool, error) { @@ -27,7 +29,8 @@ func (model *ItemShareModel) One(id int64) (*ItemShare, bool, error) { var row ItemShare - query := `SELECT bmi.title AS item_title, bmis.* FROM bm_item_shares bmis + query := `SELECT bmi.title AS item_title, bmi.summary_rendered as item_summary_rendered, bmi.description_rendered as item_description_rendered, + bmis.* FROM bm_item_shares bmis INNER JOIN bm_item bmi ON bmis.item_id=bmi.id WHERE bmis.id = $1` err := model.DB.GetContext(ctx, &row, query, id) @@ -44,7 +47,8 @@ func (model *ItemShareModel) OneByToken(token string) (*ItemShare, bool, error) var row ItemShare - query := `SELECT bmi.title AS item_title, bmis.* FROM bm_item_shares bmis + query := `SELECT bmi.title AS item_title, bmi.summary_rendered as item_summary_rendered, bmi.description_rendered as item_description_rendered, + 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) @@ -78,7 +82,7 @@ func (model *ItemShareModel) Update(ItemShare *ItemShare) error { ctx, cancel := database.GetContext() defer cancel() - query := `UPDATE bm_item_shares SET token=:token, permission_edit=:permission_edit, start_datetime=:start_datetime, end_datetime=:end_datetime WHERE id = :id` + query := `UPDATE bm_item_shares SET token=:token, permission_edit=:permission_edit, start_datetime=:start_datetime, end_datetime=:end_datetime, password=:password WHERE id = :id` _, err := model.DB.NamedExecContext(ctx, query, ItemShare) if err != nil {