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.") } }