Implement flash messages

- configure session cookie security
- setup flash message handling in newTemplateData
- show flash message in base.html
- add flash message for new motion
main
Jan Dittberner 2 years ago
parent f8fbf00c4d
commit 47092bfa9b

@ -109,7 +109,7 @@ type templateData struct {
Motion *models.MotionForDisplay Motion *models.MotionForDisplay
Motions []*models.MotionForDisplay Motions []*models.MotionForDisplay
Request *http.Request Request *http.Request
Flashes []string Flash string
Form any Form any
ActiveNav topLevelNavItem ActiveNav topLevelNavItem
ActiveSubNav subLevelNavItem ActiveSubNav subLevelNavItem
@ -130,6 +130,7 @@ func (app *application) newTemplateData(
User: user, User: user,
ActiveNav: nav, ActiveNav: nav,
ActiveSubNav: subNav, ActiveSubNav: subNav,
Flash: app.sessionManager.PopString(r.Context(), "flash"),
} }
} }
@ -434,7 +435,7 @@ func (app *application) newMotionSubmit(w http.ResponseWriter, r *http.Request)
decision: &models.NewMotion{Decision: decision, Proposer: user}, decision: &models.NewMotion{Decision: decision, Proposer: user},
} }
// TODO: add flash message for new motion app.sessionManager.Put(r.Context(), "flash", fmt.Sprintf("Started new motion %s: %s", decision.Tag, decision.Title))
http.Redirect(w, r, fmt.Sprintf("/motions/%s", decision.Tag), http.StatusSeeOther) http.Redirect(w, r, fmt.Sprintf("/motions/%s", decision.Tag), http.StatusSeeOther)
} }

@ -99,6 +99,8 @@ func main() {
sessionManager := scs.New() sessionManager := scs.New()
sessionManager.Store = sqlite3store.New(db.DB) sessionManager.Store = sqlite3store.New(db.DB)
sessionManager.Lifetime = sessionHours * time.Hour sessionManager.Lifetime = sessionHours * time.Hour
sessionManager.Cookie.SameSite = http.SameSiteStrictMode
sessionManager.Cookie.Secure = true
app := &application{ app := &application{
errorLog: errorLog, errorLog: errorLog,

@ -61,15 +61,16 @@ func (app *application) routes() http.Handler {
) )
router.Handler(http.MethodGet, "/static/*filepath", http.StripPrefix("/static", fileServer)) router.Handler(http.MethodGet, "/static/*filepath", http.StripPrefix("/static", fileServer))
csrfHandler := csrf.Protect(app.csrfKey, csrf.SameSite(csrf.SameSiteStrictMode))
dynamic := alice.New( dynamic := alice.New(
app.sessionManager.LoadAndSave, app.sessionManager.LoadAndSave,
csrf.Protect(app.csrfKey, csrf.SameSite(csrf.SameSiteStrictMode)),
app.tryAuthenticate, app.tryAuthenticate,
) )
canVote := dynamic.Append(app.userCanVote) canVote := dynamic.Append(app.userCanVote, csrfHandler)
canEditVote := dynamic.Append(app.userCanEditVote) canEditVote := dynamic.Append(app.userCanEditVote, csrfHandler)
canManageUsers := dynamic.Append(app.userCanChangeVoters) canManageUsers := dynamic.Append(app.userCanChangeVoters, csrfHandler)
router.Handler(http.MethodGet, "/motions/", dynamic.ThenFunc(app.motionList)) router.Handler(http.MethodGet, "/motions/", dynamic.ThenFunc(app.motionList))
router.Handler(http.MethodGet, "/motions/:tag", dynamic.ThenFunc(app.motionDetails)) router.Handler(http.MethodGet, "/motions/:tag", dynamic.ThenFunc(app.motionDetails))

@ -27,19 +27,17 @@
</header> </header>
{{ template "nav" . }} {{ template "nav" . }}
<main class="ui container"> <main class="ui container">
{{ template "main" . }} {{ with .Flash }}
{{ with .Flashes }}
<div class="basic segment"> <div class="basic segment">
<div class="ui info message"> <div class="ui info message">
<i class="close icon"></i> <i class="close icon"></i>
<div class="ui list"> <div class="ui list">
{{ range . }}
<div class="ui item">{{ . }}</div> <div class="ui item">{{ . }}</div>
{{ end }}
</div> </div>
</div> </div>
</div> </div>
{{ end }} {{ end }}
{{ template "main" . }}
</main> </main>
<footer class="ui vertical footer segment"> <footer class="ui vertical footer segment">
<div class="ui container"> <div class="ui container">

Loading…
Cancel
Save