package session import ( "crypto/rand" "encoding/base64" "fmt" "sync" ) type UserSession struct { Token string Team string } // implemtation adapted from // https://git.leonardobishop.net/confplanner/tree/pkg/session/memory.go // TODO add expiry type MemoryStore struct { sessions map[string]*UserSession lock sync.RWMutex } func NewMemoryStore() *MemoryStore { return &MemoryStore{ sessions: make(map[string]*UserSession), } } func (s *MemoryStore) GetByToken(token string) *UserSession { if token == "" { return nil } s.lock.RLock() defer s.lock.RUnlock() return s.sessions[token] } func (s *MemoryStore) Create(team string) (*UserSession, error) { s.lock.Lock() defer s.lock.Unlock() var token string for { token = generateSessionToken() _, tokenExists := s.sessions[token] if !tokenExists { break } } session := &UserSession{ Token: token, Team: team, } s.sessions[token] = session return session, nil } func (s *MemoryStore) Destroy(token string) error { s.lock.Lock() defer s.lock.Unlock() session := s.sessions[token] if session == nil { return fmt.Errorf("session does not exist") } delete(s.sessions, token) return nil } func generateSessionToken() string { b := make([]byte, 100) if _, err := rand.Read(b); err != nil { return "" } return base64.StdEncoding.EncodeToString(b) }