Session
A session is a non-persistent, per-user data storage, which is created when the user is logged in and destroyed when the user is logged out.
The session is used to store flash messages or any temporary user-specific data.
Configuration
Before using the session you must configure the main app with a session driver, and provide a unique secret session key.
Under the hood, the framework uses gorilla/sessions so you can choose one of many store implementations.
key := os.Getenv("SESSION_KEY")
cookieStore := sessions.NewCookieStore([]byte(keyPairs))
cookieStore.Options.HttpOnly = true // more secure
cookieStore.Options.MaxAge = 30 * 24 * 3600 // expire in one month
app := gotuna.App{
Session: gotuna.NewSession(cookieStore, "app_session"),
}
Using the session
First, you need to initialize a session for the authenticated user.
After successful authentication, your UserRepository
will return a User
object
which you can use to get the user ID and initialize the session:
func handlerLogin(app App) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, err := app.UserRepository.Authenticate(w, r)
if err != nil {
return // wrong, try again
}
app.Session.SetUserID(w, r, user.GetID())
})
}
You can now store, retrive and delete string values in the user’s session:
func handlerHome(app App) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
app.Session.Put(w, r, "color", "red")
app.Session.Get(r, "color")
app.Session.Delete(w, r, "color")
})
}
If you wish to log out the current user, you can simply destroy this session:
func handlerLogout(app App) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
app.Session.Destroy(w, r)
})
}
Flash messages
Sometimes you may wish to store a message or status update in the session for the next request. Data stored in the session using the flash method will be available in the first subsequent request.
msg := "Welcome!"
app.Session.Flash(w, r, gotuna.NewFlash(msg))
app.Session.Flash(w, r, gotuna.FlashMessage{
Kind: "success",
Message: "Another info message",
})
You can range over .Flashes
to render this in your template:
{{range $e := .Flashes}}
<div class="notification {{if $e.Kind}}is-{{$e.Kind}}{{end}}">
{{$e.Message}}
</div>
{{end}}
Storing non-string values
If you need to store your custom struct into the session, you can use
TypeToString
and TypeFromString
helper functions:
type myType struct {
Str string
Bl bool
}
val := myType{
Str: "test string",
Bl: true,
}
s, err := gotuna.TypeToString(val)
r := myType{}
err = gotuna.TypeFromString(s, &r)