aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/session/memory.go
diff options
context:
space:
mode:
authorLeonardo Bishop <me@leonardobishop.com>2025-08-14 18:07:12 +0100
committerLeonardo Bishop <me@leonardobishop.com>2025-08-14 18:07:12 +0100
commit4697556cac819c47d068819b9fc9c3b4ea84e279 (patch)
treeb832d8fc6b643a8b9d0eeca35c1268e1649da731 /pkg/session/memory.go
parentdd49c9205bb04844b686b9c3396c40eb49d25826 (diff)
Merge confplanner-web and replace fiber with native net/http
Diffstat (limited to 'pkg/session/memory.go')
-rw-r--r--pkg/session/memory.go95
1 files changed, 95 insertions, 0 deletions
diff --git a/pkg/session/memory.go b/pkg/session/memory.go
new file mode 100644
index 0000000..96e416b
--- /dev/null
+++ b/pkg/session/memory.go
@@ -0,0 +1,95 @@
+package session
+
+import (
+ "crypto/rand"
+ "encoding/hex"
+ "fmt"
+ "sync"
+ "time"
+)
+
+type memoryStore struct {
+ sessionsByToken map[string]*UserSession
+ sessionsBySID map[uint]*UserSession
+ nextSessionId uint
+ lock sync.RWMutex
+}
+
+func NewMemoryStore() Service {
+ return &memoryStore{
+ sessionsByToken: make(map[string]*UserSession),
+ sessionsBySID: make(map[uint]*UserSession),
+ }
+}
+
+func (s *memoryStore) GetByToken(token string) *UserSession {
+ if token == "" {
+ return nil
+ }
+
+ s.lock.RLock()
+ defer s.lock.RUnlock()
+
+ return s.sessionsByToken[token]
+}
+
+func (s *memoryStore) GetBySID(sid uint) *UserSession {
+ s.lock.RLock()
+ defer s.lock.RUnlock()
+
+ return s.sessionsBySID[sid]
+}
+
+func (s *memoryStore) Create(uid int32, username string, ip string, ua string) (*UserSession, error) {
+ token := generateSessionToken()
+
+ s.lock.Lock()
+ defer s.lock.Unlock()
+
+ sessionId := s.nextSessionId
+ s.nextSessionId++
+
+ _, sidExists := s.sessionsBySID[sessionId]
+ _, tokenExists := s.sessionsByToken[token]
+
+ // should never realistically happen but still theoretically possible
+ if sidExists || tokenExists {
+ return nil, fmt.Errorf("session conflict")
+ }
+
+ session := &UserSession{
+ UserID: uid,
+ SessionID: sessionId,
+ Token: token,
+ Username: username,
+ IP: ip,
+ UserAgent: ua,
+ LoginTime: time.Now(),
+ }
+ s.sessionsByToken[token] = session
+ s.sessionsBySID[sessionId] = session
+
+ return session, nil
+}
+
+func (s *memoryStore) Destroy(sid uint) error {
+ s.lock.Lock()
+ defer s.lock.Unlock()
+
+ session := s.sessionsBySID[sid]
+ if session == nil {
+ return fmt.Errorf("session does not exist")
+ }
+
+ delete(s.sessionsBySID, sid)
+ delete(s.sessionsByToken, session.Token)
+ return nil
+}
+
+func generateSessionToken() string {
+ b := make([]byte, 100)
+ if _, err := rand.Read(b); err != nil {
+ return ""
+ }
+ return hex.EncodeToString(b)
+}