You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
2.4 KiB
116 lines
2.4 KiB
package auth
|
|
|
|
import (
|
|
"log"
|
|
"sync"
|
|
"time"
|
|
|
|
"git.aiterp.net/gisle/wrouter/generate"
|
|
)
|
|
|
|
const SessionMaxTime = time.Hour * 72
|
|
|
|
var sessionMutex sync.RWMutex
|
|
var sessions = make(map[string]*Session, 512)
|
|
var lastCheck = time.Now()
|
|
|
|
// SessionCookieName for the session cookie
|
|
var SessionCookieName = "sessid"
|
|
|
|
// Session is a simple in-memory structure describing a suer session
|
|
type Session struct {
|
|
ID string `json:"id"`
|
|
UserID string `json:"user"`
|
|
Time time.Time `json:"time"`
|
|
data map[string]string
|
|
}
|
|
|
|
// SetData sets session data
|
|
func (sess *Session) SetData(key, value string) {
|
|
sess.data[key] = value
|
|
}
|
|
|
|
// GetData gets session data for the following key
|
|
func (sess *Session) GetData(key string) string {
|
|
return sess.data[key]
|
|
}
|
|
|
|
// HasData checks if the session data contains the key
|
|
func (sess *Session) HasData(key string) bool {
|
|
_, ok := sess.data[key]
|
|
return ok
|
|
}
|
|
|
|
// OpenSession creates a new session from the supplied user's ID
|
|
func OpenSession(user *User) *Session {
|
|
session := &Session{generate.SessionID(), user.FullID(), time.Now(), make(map[string]string)}
|
|
|
|
sessionMutex.Lock()
|
|
sessions[session.ID] = session
|
|
sessionMutex.Unlock()
|
|
|
|
// No need to do these checks when there's no activity.
|
|
if time.Since(lastCheck) > time.Hour {
|
|
lastCheck = time.Now()
|
|
go cleanup()
|
|
}
|
|
|
|
user.Session = session
|
|
|
|
return session
|
|
}
|
|
|
|
// FindSession returns a session if the id maps to a still valid session
|
|
func FindSession(id string) *Session {
|
|
sessionMutex.RLock()
|
|
session := sessions[id]
|
|
sessionMutex.RUnlock()
|
|
|
|
// Check expiry and update
|
|
if session != nil {
|
|
if time.Since(session.Time) > SessionMaxTime {
|
|
return nil
|
|
}
|
|
|
|
if time.Since(session.Time) > time.Hour {
|
|
session.Time = time.Now()
|
|
}
|
|
}
|
|
|
|
return session
|
|
}
|
|
|
|
// CloseSession deletes a session by the id
|
|
func CloseSession(id string) {
|
|
sessionMutex.Lock()
|
|
delete(sessions, id)
|
|
sessionMutex.Unlock()
|
|
}
|
|
|
|
// ClearSessions removes all sessions with the given user ID
|
|
func ClearSessions(user *User) {
|
|
sessionMutex.Lock()
|
|
for _, sess := range sessions {
|
|
if sess.UserID == user.FullID() {
|
|
delete(sessions, sess.ID)
|
|
}
|
|
}
|
|
sessionMutex.Unlock()
|
|
}
|
|
|
|
func cleanup() {
|
|
count := 0
|
|
|
|
sessionMutex.Lock()
|
|
for key, session := range sessions {
|
|
if time.Since(session.Time) > SessionMaxTime {
|
|
delete(sessions, key)
|
|
count++
|
|
}
|
|
}
|
|
sessionMutex.Unlock()
|
|
|
|
if count > 0 {
|
|
log.Println("Removed", count, "sessions.")
|
|
}
|
|
}
|