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

@ -1,54 +1,52 @@
{{ define "base" }} {{ define "base" }}
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>{{ template "title" . }} - CAcert Board Voting System</title> <title>{{ template "title" . }} - CAcert Board Voting System</title>
<link rel="stylesheet" type="text/css" href="/static/lato-fonts.css"> <link rel="stylesheet" type="text/css" href="/static/lato-fonts.css">
<link rel="stylesheet" type="text/css" href="/static/semantic.min.css"> <link rel="stylesheet" type="text/css" href="/static/semantic.min.css">
<link rel="icon" href="/static/images/favicon.ico"> <link rel="icon" href="/static/images/favicon.ico">
</head> </head>
<body id="cacert-board-voting"> <body id="cacert-board-voting">
<header class="pusher"> <header class="pusher">
<div class="ui vertical masthead center aligned segment"> <div class="ui vertical masthead center aligned segment">
<div class="ui left secondary container"> <div class="ui left secondary container">
<img src="/static/images/CAcert-logo-colour.svg" alt="CAcert" height="40rem"/> <img src="/static/images/CAcert-logo-colour.svg" alt="CAcert" height="40rem"/>
</div> </div>
<div class="ui text container"> <div class="ui text container">
<h1 class="ui header"> <h1 class="ui header">
{{ template "title" . }} {{ template "title" . }}
{{ if .User }} {{ if .User }}
<span class="ui left pointing label">Authenticated as {{ .User.Name }} &lt;{{ .User.Reminder }}&gt; <span class="ui left pointing label">Authenticated as {{ .User.Name }} &lt;{{ .User.Reminder }}&gt;
</span> </span>
{{ end }} {{ end }}
</h1> </h1>
</div>
</div> </div>
</div> </header>
</header> {{ template "nav" . }}
{{ template "nav" . }} <main class="ui container">
<main class="ui container"> {{ with .Flash }}
{{ template "main" . }} <div class="basic segment">
{{ with .Flashes }} <div class="ui info message">
<div class="basic segment"> <i class="close icon"></i>
<div class="ui info message"> <div class="ui list">
<i class="close icon"></i>
<div class="ui list">
{{ range . }}
<div class="ui item">{{ . }}</div> <div class="ui item">{{ . }}</div>
{{ end }} </div>
</div> </div>
</div> </div>
{{ end }}
{{ template "main" . }}
</main>
<footer class="ui vertical footer segment">
<div class="ui container">
<span class="ui small text">© 2017-2022 CAcert Inc.</span>
</div> </div>
{{ end }} </footer>
</main> </body>
<footer class="ui vertical footer segment"> <script src="/static/jquery.min.js"></script>
<div class="ui container"> <script src="/static/semantic.min.js"></script>
<span class="ui small text">© 2017-2022 CAcert Inc.</span> <script src="/static/handlers.js"></script>
</div> </html>
</footer>
</body>
<script src="/static/jquery.min.js"></script>
<script src="/static/semantic.min.js"></script>
<script src="/static/handlers.js"></script>
</html>
{{ end }} {{ end }}
Loading…
Cancel
Save