ovpn-certman/services/sessions.go

105 lines
2.4 KiB
Go
Raw Normal View History

2018-01-26 14:49:03 +01:00
package services
import (
2018-01-29 09:18:19 +01:00
"encoding/gob"
2019-05-15 19:08:24 +02:00
"errors"
2018-01-29 09:18:19 +01:00
"fmt"
"html/template"
"log"
"net/http"
"time"
"github.com/alexedwards/scs"
2018-01-26 14:49:03 +01:00
)
2019-05-15 19:08:24 +02:00
const (
2018-01-29 09:18:19 +01:00
// FlashesKey is the key used for the flashes in the cookie
FlashesKey = "_flashes"
// UserEmailKey is the key used to reference usernames
UserEmailKey = "_user_email"
)
func init() {
// Register the Flash message type, so gob can serialize it
gob.Register(Flash{})
}
type SessionsConfig struct {
2019-05-15 19:08:24 +02:00
HTTPOnly bool
Secure bool
Lifetime time.Duration
}
2018-01-26 14:49:03 +01:00
// Sessions is a wrapped scs.Store in order to implement custom logic
type Sessions struct {
2019-05-15 19:08:24 +02:00
*scs.Session
2018-01-29 09:18:19 +01:00
}
// NewSessions populates the default sessions Store
func NewSessions(conf *SessionsConfig) *Sessions {
2019-05-15 19:08:24 +02:00
session := scs.NewSession()
session.Lifetime = conf.Lifetime
session.Cookie.HttpOnly = true
session.Cookie.Secure = conf.Secure
2018-01-29 09:18:19 +01:00
2019-05-15 19:08:24 +02:00
return &Sessions{session}
2018-01-29 09:18:19 +01:00
}
2018-02-01 09:31:06 +01:00
func (store *Sessions) GetUsername(req *http.Request) string {
2018-01-29 09:18:19 +01:00
if store == nil {
// if store was not initialized, all requests fail
2018-02-03 18:14:47 +01:00
log.Println("Nil pointer when checking session for username")
2018-01-29 09:18:19 +01:00
return ""
}
2019-05-15 19:08:24 +02:00
email := store.GetString(req.Context(), UserEmailKey)
return email // "" if no user is logged in
2018-01-29 09:18:19 +01:00
}
2018-02-01 09:31:06 +01:00
func (store *Sessions) SetUsername(w http.ResponseWriter, req *http.Request, username string) {
2018-01-29 09:18:19 +01:00
if store == nil {
// if store was not initialized, do nothing
return
}
// renew token to avoid session pinning/fixation attack
2019-05-15 19:08:24 +02:00
store.RenewToken(req.Context())
2018-01-29 09:18:19 +01:00
2019-05-15 19:08:24 +02:00
store.Put(req.Context(), UserEmailKey, username)
2018-01-29 09:18:19 +01:00
}
type Flash struct {
Message template.HTML
Type string
}
// Render renders the flash message as a notification box
func (flash Flash) Render() template.HTML {
return template.HTML(
fmt.Sprintf(
"<div class=\"notification is-radiusless is-%s\"><div class=\"container has-text-centered\">%s</div></div>",
flash.Type, flash.Message,
),
)
}
// Flash add flash message to session data
func (store *Sessions) Flash(w http.ResponseWriter, req *http.Request, flash Flash) error {
2019-05-15 19:08:24 +02:00
flashes, ok := store.Get(req.Context(), FlashesKey).([]Flash)
if !ok {
return errors.New("Could not get flashes")
2018-01-29 09:18:19 +01:00
}
flashes = append(flashes, flash)
2019-05-15 19:08:24 +02:00
return nil
2018-01-29 09:18:19 +01:00
}
2018-01-26 14:49:03 +01:00
2018-01-29 09:18:19 +01:00
// Flashes returns a slice of flash messages from session data
func (store *Sessions) Flashes(w http.ResponseWriter, req *http.Request) []Flash {
2019-05-15 19:08:24 +02:00
flashes, ok := store.Pop(req.Context(), FlashesKey).([]Flash)
if !ok {
return nil
}
2018-01-29 09:18:19 +01:00
return flashes
2018-01-26 14:49:03 +01:00
}