diff --git a/internal/mcp/session.go b/internal/mcp/session.go new file mode 100644 index 0000000..8fa44a6 --- /dev/null +++ b/internal/mcp/session.go @@ -0,0 +1,40 @@ +package mcp + +import ( + "crypto/rand" + "encoding/hex" + "sync" +) + +type SessionStore struct { + mu sync.RWMutex + m map[string]struct{} +} + +func NewSessionStore() *SessionStore { + return &SessionStore{m: make(map[string]struct{})} +} + +func (s *SessionStore) Issue() string { + b := make([]byte, 16) + _, _ = rand.Read(b) + id := hex.EncodeToString(b) + + s.mu.Lock() + s.m[id] = struct{}{} + s.mu.Unlock() + return id +} + +func (s *SessionStore) Valid(id string) bool { + s.mu.RLock() + defer s.mu.RUnlock() + _, ok := s.m[id] + return ok +} + +func (s *SessionStore) Drop(id string) { + s.mu.Lock() + delete(s.m, id) + s.mu.Unlock() +} diff --git a/internal/mcp/session_test.go b/internal/mcp/session_test.go new file mode 100644 index 0000000..9880e44 --- /dev/null +++ b/internal/mcp/session_test.go @@ -0,0 +1,22 @@ +package mcp_test + +import ( + "testing" + + "gitea.d-ma.be/mathias/gitea-mcp/internal/mcp" + "github.com/stretchr/testify/assert" +) + +func TestSessionStoreIssueAndCheck(t *testing.T) { + s := mcp.NewSessionStore() + + id := s.Issue() + assert.NotEmpty(t, id) + assert.Len(t, id, 32) + + assert.True(t, s.Valid(id)) + assert.False(t, s.Valid("bogus")) + + s.Drop(id) + assert.False(t, s.Valid(id)) +}