package services import ( "encoding/gob" "fmt" "html/template" "log" "net/http" "time" "github.com/alexedwards/scs" ) var ( // 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 { SessionName string CookieKey string HttpOnly bool Secure bool Lifetime time.Duration } // Sessions is a wrapped scs.Store in order to implement custom logic type Sessions struct { *scs.Manager } // NewSessions populates the default sessions Store func NewSessions(conf *SessionsConfig) *Sessions { store := scs.NewCookieManager( conf.CookieKey, ) store.Name(conf.SessionName) store.HttpOnly(true) store.Lifetime(conf.Lifetime) store.Secure(conf.Secure) return &Sessions{store} } func (store *Sessions) 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 *Sessions) 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( "