ovpn-certman/services/sessions.go
2018-01-29 09:18:19 +01:00

127 lines
2.8 KiB
Go

package services
import (
"encoding/gob"
"fmt"
"html/template"
"log"
"net/http"
"time"
"git.klink.asia/paul/certman/settings"
"github.com/alexedwards/scs"
"github.com/gorilla/securecookie"
)
var (
// SessionName is the name of the session cookie
SessionName = "session"
// CookieKey is the key the cookies are encrypted and signed with
CookieKey = string(securecookie.GenerateRandomKey(32))
// 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{})
}
// SessionStore is a globally accessible sessions store for the application
var SessionStore *Store
// Store is a wrapped scs.Store in order to implement custom
// logic
type Store struct {
*scs.Manager
}
// InitSession populates the default sessions Store
func InitSession() {
store := scs.NewCookieManager(
CookieKey,
)
store.HttpOnly(true)
store.Lifetime(24 * time.Hour)
// Use secure cookies (HTTPS only) in production
store.Secure(settings.Get("ENVIRONMENT", "") == "production")
SessionStore = &Store{store}
}
func (store *Store) GetUserEmail(req *http.Request) string {
if store == nil {
// if store was not initialized, all requests fail
log.Println("Zero pointer when checking session for username")
return ""
}
sess := store.Load(req)
email, err := sess.GetString(UserEmailKey)
if err != nil {
// Username found
return ""
}
// User is logged in
return email
}
func (store *Store) SetUserEmail(w http.ResponseWriter, req *http.Request, email string) {
if store == nil {
// if store was not initialized, do nothing
return
}
sess := store.Load(req)
// renew token to avoid session pinning/fixation attack
sess.RenewToken(w)
sess.PutString(w, UserEmailKey, email)
}
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 *Store) Flash(w http.ResponseWriter, req *http.Request, flash Flash) error {
var flashes []Flash
sess := store.Load(req)
if err := sess.GetObject(FlashesKey, &flashes); err != nil {
return err
}
flashes = append(flashes, flash)
return sess.PutObject(w, FlashesKey, flashes)
}
// Flashes returns a slice of flash messages from session data
func (store *Store) Flashes(w http.ResponseWriter, req *http.Request) []Flash {
var flashes []Flash
sess := store.Load(req)
sess.PopObject(w, FlashesKey, &flashes)
return flashes
}