hlfw.ca

webbing

Download patch

ref: dc410ec80e1295d40a83e6826cdcf2095ef75ed1
parent: 910a508a5ca9c521acbb7c9fab2ee06d174b38e4
author: halfwit <michaelmisch1985@gmail.com>
date: Thu Aug 6 05:46:15 PDT 2020

Add session

--- a/.github/workflows/go.yml
+++ /dev/null
@@ -1,35 +1,0 @@
-name: Testing
-
-on:
-  pull_request:
-    branches: [ master ]
-
-jobs:
-
-  build:
-    name: Build
-    runs-on: ubuntu-latest
-    steps:
-    - name: Configure git for private modules
-      env:
-        TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
-      run: git config --global url."https://halfwit:${TOKEN}@github.com".insteadOf "https://github.com"
-    - name: Set up Go 1.13
-      uses: actions/setup-go@v1
-      with:
-        go-version: 1.13
-      id: go
-
-    - name: Check out code into the Go module directory
-      uses: actions/checkout@v2
-
-    - name: Get dependencies
-      run: |
-        go get -v -t -d ./...
-        if [ -f Gopkg.toml ]; then
-            curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
-            dep ensure
-        fi
-
-    - name: Run Tests
-      run: go test -v ./...
--- a/data.go
+++ /dev/null
@@ -1,116 +1,0 @@
-package session
-
-import (
-	"container/list"
-	"log"
-	"sync"
-	"time"
-)
-
-var pder = &Default{
-	list: list.New(),
-}
-
-// Store - map of clients and their sessions
-type Store struct {
-	sid   string
-	atime time.Time
-	value map[interface{}]interface{}
-}
-
-func init() {
-	pder.sessions = make(map[string]*list.Element, 0)
-	Register("default", pder)
-}
-
-// Set - register kv into manager
-func (st *Store) Set(key, value interface{}) error {
-	st.value[key] = value
-	pder.Update(st.sid)
-	return nil
-}
-
-// Get - lookup value by key
-func (st *Store) Get(key interface{}) interface{} {
-	pder.Update(st.sid)
-	if v, ok := st.value[key]; ok {
-		return v
-	}
-	return nil
-}
-
-// Delete - remove value pointed to by key
-func (st *Store) Delete(key interface{}) error {
-	delete(st.value, key)
-	pder.Update(st.sid)
-	return nil
-}
-
-// ID - return session ID
-func (st *Store) ID() string {
-	return st.sid
-}
-
-// Default - The main session used for clients on the site
-type Default struct {
-	lock     sync.Mutex
-	sessions map[string]*list.Element
-	list     *list.List
-}
-
-// Init - create session
-func (pder *Default) Init(sid string) (Session, error) {
-	pder.lock.Lock()
-	defer pder.lock.Unlock()
-	v := make(map[interface{}]interface{}, 0)
-	newsess := &Store{sid: sid, atime: time.Now(), value: v}
-	element := pder.list.PushBack(newsess)
-	pder.sessions[sid] = element
-	return newsess, nil
-}
-
-// Read - Request session by id
-func (pder *Default) Read(sid string) (Session, error) {
-	if element, ok := pder.sessions[sid]; ok {
-		return element.Value.(*Store), nil
-	}
-	return pder.Init(sid)
-}
-
-// Destroy - Remove session by id
-func (pder *Default) Destroy(sid string) error {
-	if element, ok := pder.sessions[sid]; ok {
-		delete(pder.sessions, sid)
-		pder.list.Remove(element)
-	}
-	return nil
-}
-
-// GC - Clean up all expired sessions
-func (pder *Default) GC(maxlifetime int64) {
-	log.Println("Starting GC sweep")
-	pder.lock.Lock()
-	defer pder.lock.Unlock()
-	for {
-		element := pder.list.Back()
-		if element == nil {
-			return
-		}
-		if (element.Value.(*Store).atime.Unix() + maxlifetime) >= time.Now().Unix() {
-			return
-		}
-		pder.list.Remove(element)
-		delete(pder.sessions, element.Value.(*Store).sid)
-	}
-}
-
-// Update - move session labelled with ID to top of list
-func (pder *Default) Update(sid string) error {
-	pder.lock.Lock()
-	defer pder.lock.Unlock()
-	if element, ok := pder.sessions[sid]; ok {
-		element.Value.(*Store).atime = time.Now()
-		pder.list.MoveToFront(element)
-	}
-	return nil
-}
--- a/go.mod
+++ /dev/null
@@ -1,5 +1,0 @@
-module github.com/olmaxmedical/session
-
-go 1.14
-
-require github.com/google/uuid v1.1.1
--- a/go.sum
+++ /dev/null
@@ -1,2 +1,0 @@
-github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
-github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
--- a/manager.go
+++ /dev/null
@@ -1,122 +1,0 @@
-package session
-
-import (
-	"fmt"
-	"log"
-	"net/http"
-	"net/url"
-	"sync"
-	"time"
-
-	"github.com/google/uuid"
-)
-
-var provides = make(map[string]Provider)
-
-// Manager - Represents a particular cookie to a client
-type Manager struct {
-	cookieName  string
-	lock        sync.Mutex
-	provider    Provider
-	maxlifetime int64
-}
-
-// NewManager - returns a Cookie manager, ready to use or an error
-func NewManager(provideName, cookieName string, maxlifetime int64) (*Manager, error) {
-	if provider, ok := provides[provideName]; ok {
-		m := &Manager{
-			provider:    provider,
-			cookieName:  cookieName,
-			maxlifetime: maxlifetime,
-		}
-		return m, nil
-	}
-	return nil, fmt.Errorf("session: unknown provide %q", provideName)
-}
-
-// Provider - interface our cookie manager calls to manage lifetimes
-type Provider interface {
-	Init(sid string) (Session, error)
-	Read(sid string) (Session, error)
-	Destroy(sid string) error
-	GC(maxLifeTime int64)
-}
-
-// Session - a client connection
-type Session interface {
-	Set(key, value interface{}) error
-	Get(key interface{}) interface{}
-	Delete(key interface{}) error
-	ID() string
-}
-
-// Register - Add a provider to our stack (e.g., Default)
-func Register(name string, provider Provider) {
-	if provider == nil {
-		log.Fatal("session: Register provider is nil")
-	}
-	if _, ok := provides[name]; !ok {
-		provides[name] = provider
-		return
-	}
-	log.Fatal("session: Register called twice for provider " + name)
-}
-
-// Destroy - Call provider Destroy
-func (manager *Manager) Destroy(w http.ResponseWriter, r *http.Request) {
-	cookie, err := r.Cookie(manager.cookieName)
-	if err != nil || cookie.Value == "" {
-		return
-	}
-	manager.lock.Lock()
-	defer manager.lock.Unlock()
-	manager.provider.Destroy(cookie.Value)
-	expiration := time.Now()
-	c := http.Cookie{
-		Name:     manager.cookieName,
-		Path:     "/",
-		HttpOnly: true,
-		Expires:  expiration,
-		MaxAge:   -1,
-	}
-	http.SetCookie(w, &c)
-}
-
-// Start - Call provider Start
-func (manager *Manager) Start(w http.ResponseWriter, r *http.Request) (session Session) {
-	manager.lock.Lock()
-	defer manager.lock.Unlock()
-	cookie, err := r.Cookie(manager.cookieName)
-	if err != nil || cookie.Value == "" {
-		sid := manager.sessionID()
-		session, _ = manager.provider.Init(sid)
-		cookie := http.Cookie{
-			Name:     manager.cookieName,
-			Value:    url.QueryEscape(sid),
-			Path:     "/",
-			HttpOnly: true,
-			MaxAge:   int(manager.maxlifetime),
-		}
-		http.SetCookie(w, &cookie)
-		return
-	}
-	sid, _ := url.QueryUnescape(cookie.Value)
-	session, _ = manager.provider.Read(sid)
-	return
-}
-
-// GC - call all providers GC
-func (manager *Manager) GC() {
-	manager.lock.Lock()
-	defer manager.lock.Unlock()
-	manager.provider.GC(manager.maxlifetime)
-	time.AfterFunc(30*time.Second, func() { manager.GC() })
-}
-
-func (manager *Manager) sessionID() string {
-	u, err := uuid.NewRandom()
-	if err != nil {
-		log.Fatalf("Unable to generate UUID %q", err)
-	}
-	return u.String()
-}
--- /dev/null
+++ b/session/data.go
@@ -1,0 +1,116 @@
+package session
+
+import (
+	"container/list"
+	"log"
+	"sync"
+	"time"
+)
+
+var pder = &Default{
+	list: list.New(),
+}
+
+// Store - map of clients and their sessions
+type Store struct {
+	sid   string
+	atime time.Time
+	value map[interface{}]interface{}
+}
+
+func init() {
+	pder.sessions = make(map[string]*list.Element, 0)
+	Register("default", pder)
+}
+
+// Set - register kv into manager
+func (st *Store) Set(key, value interface{}) error {
+	st.value[key] = value
+	pder.Update(st.sid)
+	return nil
+}
+
+// Get - lookup value by key
+func (st *Store) Get(key interface{}) interface{} {
+	pder.Update(st.sid)
+	if v, ok := st.value[key]; ok {
+		return v
+	}
+	return nil
+}
+
+// Delete - remove value pointed to by key
+func (st *Store) Delete(key interface{}) error {
+	delete(st.value, key)
+	pder.Update(st.sid)
+	return nil
+}
+
+// ID - return session ID
+func (st *Store) ID() string {
+	return st.sid
+}
+
+// Default - The main session used for clients on the site
+type Default struct {
+	lock     sync.Mutex
+	sessions map[string]*list.Element
+	list     *list.List
+}
+
+// Init - create session
+func (pder *Default) Init(sid string) (Session, error) {
+	pder.lock.Lock()
+	defer pder.lock.Unlock()
+	v := make(map[interface{}]interface{}, 0)
+	newsess := &Store{sid: sid, atime: time.Now(), value: v}
+	element := pder.list.PushBack(newsess)
+	pder.sessions[sid] = element
+	return newsess, nil
+}
+
+// Read - Request session by id
+func (pder *Default) Read(sid string) (Session, error) {
+	if element, ok := pder.sessions[sid]; ok {
+		return element.Value.(*Store), nil
+	}
+	return pder.Init(sid)
+}
+
+// Destroy - Remove session by id
+func (pder *Default) Destroy(sid string) error {
+	if element, ok := pder.sessions[sid]; ok {
+		delete(pder.sessions, sid)
+		pder.list.Remove(element)
+	}
+	return nil
+}
+
+// GC - Clean up all expired sessions
+func (pder *Default) GC(maxlifetime int64) {
+	log.Println("Starting GC sweep")
+	pder.lock.Lock()
+	defer pder.lock.Unlock()
+	for {
+		element := pder.list.Back()
+		if element == nil {
+			return
+		}
+		if (element.Value.(*Store).atime.Unix() + maxlifetime) >= time.Now().Unix() {
+			return
+		}
+		pder.list.Remove(element)
+		delete(pder.sessions, element.Value.(*Store).sid)
+	}
+}
+
+// Update - move session labelled with ID to top of list
+func (pder *Default) Update(sid string) error {
+	pder.lock.Lock()
+	defer pder.lock.Unlock()
+	if element, ok := pder.sessions[sid]; ok {
+		element.Value.(*Store).atime = time.Now()
+		pder.list.MoveToFront(element)
+	}
+	return nil
+}
--- /dev/null
+++ b/session/manager.go
@@ -1,0 +1,122 @@
+package session
+
+import (
+	"fmt"
+	"log"
+	"net/http"
+	"net/url"
+	"sync"
+	"time"
+
+	"github.com/google/uuid"
+)
+
+var provides = make(map[string]Provider)
+
+// Manager - Represents a particular cookie to a client
+type Manager struct {
+	cookieName  string
+	lock        sync.Mutex
+	provider    Provider
+	maxlifetime int64
+}
+
+// NewManager - returns a Cookie manager, ready to use or an error
+func NewManager(provideName, cookieName string, maxlifetime int64) (*Manager, error) {
+	if provider, ok := provides[provideName]; ok {
+		m := &Manager{
+			provider:    provider,
+			cookieName:  cookieName,
+			maxlifetime: maxlifetime,
+		}
+		return m, nil
+	}
+	return nil, fmt.Errorf("session: unknown provide %q", provideName)
+}
+
+// Provider - interface our cookie manager calls to manage lifetimes
+type Provider interface {
+	Init(sid string) (Session, error)
+	Read(sid string) (Session, error)
+	Destroy(sid string) error
+	GC(maxLifeTime int64)
+}
+
+// Session - a client connection
+type Session interface {
+	Set(key, value interface{}) error
+	Get(key interface{}) interface{}
+	Delete(key interface{}) error
+	ID() string
+}
+
+// Register - Add a provider to our stack (e.g., Default)
+func Register(name string, provider Provider) {
+	if provider == nil {
+		log.Fatal("session: Register provider is nil")
+	}
+	if _, ok := provides[name]; !ok {
+		provides[name] = provider
+		return
+	}
+	log.Fatal("session: Register called twice for provider " + name)
+}
+
+// Destroy - Call provider Destroy
+func (manager *Manager) Destroy(w http.ResponseWriter, r *http.Request) {
+	cookie, err := r.Cookie(manager.cookieName)
+	if err != nil || cookie.Value == "" {
+		return
+	}
+	manager.lock.Lock()
+	defer manager.lock.Unlock()
+	manager.provider.Destroy(cookie.Value)
+	expiration := time.Now()
+	c := http.Cookie{
+		Name:     manager.cookieName,
+		Path:     "/",
+		HttpOnly: true,
+		Expires:  expiration,
+		MaxAge:   -1,
+	}
+	http.SetCookie(w, &c)
+}
+
+// Start - Call provider Start
+func (manager *Manager) Start(w http.ResponseWriter, r *http.Request) (session Session) {
+	manager.lock.Lock()
+	defer manager.lock.Unlock()
+	cookie, err := r.Cookie(manager.cookieName)
+	if err != nil || cookie.Value == "" {
+		sid := manager.sessionID()
+		session, _ = manager.provider.Init(sid)
+		cookie := http.Cookie{
+			Name:     manager.cookieName,
+			Value:    url.QueryEscape(sid),
+			Path:     "/",
+			HttpOnly: true,
+			MaxAge:   int(manager.maxlifetime),
+		}
+		http.SetCookie(w, &cookie)
+		return
+	}
+	sid, _ := url.QueryUnescape(cookie.Value)
+	session, _ = manager.provider.Read(sid)
+	return
+}
+
+// GC - call all providers GC
+func (manager *Manager) GC() {
+	manager.lock.Lock()
+	defer manager.lock.Unlock()
+	manager.provider.GC(manager.maxlifetime)
+	time.AfterFunc(30*time.Second, func() { manager.GC() })
+}
+
+func (manager *Manager) sessionID() string {
+	u, err := uuid.NewRandom()
+	if err != nil {
+		log.Fatalf("Unable to generate UUID %q", err)
+	}
+	return u.String()
+}