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
This commit is contained in:
Jan Dittberner 2022-05-26 16:27:44 +02:00
parent f8fbf00c4d
commit 47092bfa9b
4 changed files with 56 additions and 54 deletions

View file

@ -109,7 +109,7 @@ type templateData struct {
Motion *models.MotionForDisplay
Motions []*models.MotionForDisplay
Request *http.Request
Flashes []string
Flash string
Form any
ActiveNav topLevelNavItem
ActiveSubNav subLevelNavItem
@ -130,6 +130,7 @@ func (app *application) newTemplateData(
User: user,
ActiveNav: nav,
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},
}
// 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)
}

View file

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

View file

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

View file

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