gowebframework/session.go

105 lines
2.7 KiB
Go

/*
* @Author: Bartuccio Antoine
* @Date: 2018-07-16 14:07:07
* @Last Modified by: klmp200
* @Last Modified time: 2018-07-18 00:03:26
*/
package gowebframework
import (
"fmt"
"github.com/google/uuid"
"log"
"net/http"
"net/url"
"sync"
"time"
)
var SESSION *SessionManager
var providers = make(map[string]Provider)
type SessionManager struct {
cookieName string // Name of the cookie on the client side
lock sync.Mutex
provider Provider
maxLifetime time.Duration
}
type Session interface {
Set(key string, value interface{}) error // set a session value
Get(key string) interface{} // get session value
Delete(key string) error // delete session value
SessionUUID() string // get the current session UUID
}
type Provider interface {
SessionInit(uuid string) (Session, error)
SessionRead(uuid string) (Session, error)
SessionDestroy(uuid string) error
SessionClearExpired(maxLifetime time.Duration)
}
func (manager *SessionManager) generateUUID() string {
return uuid.New().String()
}
// Launch a Clear Expired Sessions task at fixed rate
func clearExpiredSessionsCron() {
SESSION.lock.Lock()
lifetime := SESSION.maxLifetime
SESSION.lock.Unlock()
for {
SESSION.lock.Lock()
SESSION.provider.SessionClearExpired(lifetime)
SESSION.lock.Unlock()
time.Sleep(lifetime)
}
}
func SessionProviderRegister(provider Provider, providerName string) error {
if provider == nil {
return fmt.Errorf("No provider found for provider name %s", providerName)
}
if _, exists := providers[providerName]; exists {
return fmt.Errorf("Provider with name %s already exists", providerName)
}
providers[providerName] = provider
return nil
}
func (manager *SessionManager) GetSession(w http.ResponseWriter, r *http.Request) Session {
var session Session
manager.lock.Lock()
defer manager.lock.Unlock()
cookie, err := r.Cookie(manager.cookieName)
if err != nil || cookie.Value == "" {
// Create a new session
session_id := manager.generateUUID()
s, err := manager.provider.SessionInit(session_id)
if err != nil {
log.Fatal(err)
}
session = s
AddCookie(w, manager.cookieName, url.QueryEscape(session_id), manager.maxLifetime)
} else {
// Get the session
session_id, _ := url.QueryUnescape(cookie.Value)
s, err := manager.provider.SessionRead(session_id)
if err != nil {
log.Fatal(err)
}
session = s
}
return session
}
func newSessionManager(providerName string, cookieName string, maxLifetime time.Duration) (*SessionManager, error) {
provider, ok := providers[providerName]
if !ok {
return nil, fmt.Errorf("Session error: unknown provider %s", providerName)
}
return &SessionManager{provider: provider, cookieName: cookieName, maxLifetime: maxLifetime}, nil
}