Files
mnemosyne/mnemosyne/mcp_server/tests/test_token.py
Robert Helewka 93639188d3
Some checks failed
CVE Scan & Docker Build / build-and-push (push) Has been cancelled
CVE Scan & Docker Build / security-scan (push) Has been cancelled
Build & Deploy Docs / build-and-deploy (push) Successful in 1m10s
feat: rework auth model with UserToken and Daedalus/Pallas integration
- Rename MCPToken to UserToken across models, views, and tests
- Update URL names from mcp-token-* to token-*
- Add Daedalus/Pallas integration design doc (v2)
- Switch docker-compose to build local mnemosyne:local image via shared
  build config instead of pulling from git.helu.ca
2026-05-23 19:50:29 -04:00

78 lines
2.9 KiB
Python

"""Tests for the UserToken model."""
from datetime import timedelta
from django.contrib.auth import get_user_model
from django.test import TestCase
from django.utils import timezone
from mcp_server.models import UserToken, hash_token
User = get_user_model()
class UserTokenModelTest(TestCase):
def setUp(self):
self.user = User.objects.create_user(
username="alice", email="alice@example.com", password="pw"
)
def test_create_token_returns_plaintext_and_stores_hash(self):
token, plaintext = UserToken.objects.create_token(user=self.user, name="t")
self.assertTrue(plaintext)
self.assertGreater(len(plaintext), 20)
# Database stores hash, not plaintext
self.assertEqual(len(token.token_hash), 64)
self.assertNotEqual(token.token_hash, plaintext)
self.assertEqual(token.token_hash, hash_token(plaintext))
def test_token_hash_never_equals_plaintext(self):
# Regression guard: if anyone ever wires plaintext back into token_hash,
# this fails.
token, plaintext = UserToken.objects.create_token(user=self.user, name="t")
self.assertNotIn(plaintext, token.token_hash)
def test_active_token_is_valid(self):
token, _ = UserToken.objects.create_token(user=self.user, name="t")
self.assertTrue(token.is_valid)
def test_inactive_token_not_valid(self):
token, _ = UserToken.objects.create_token(user=self.user, name="t")
token.is_active = False
token.save()
self.assertFalse(token.is_valid)
def test_expired_token_not_valid(self):
token, _ = UserToken.objects.create_token(
user=self.user,
name="t",
expires_at=timezone.now() - timedelta(hours=1),
)
self.assertFalse(token.is_valid)
def test_unrestricted_permits_all(self):
token, _ = UserToken.objects.create_token(user=self.user, name="t")
self.assertTrue(token.can_use_tool("anything"))
def test_tool_whitelist(self):
token, _ = UserToken.objects.create_token(
user=self.user, name="t", allowed_tools=["search"]
)
self.assertTrue(token.can_use_tool("search"))
self.assertFalse(token.can_use_tool("get_chunk"))
def test_record_usage(self):
token, _ = UserToken.objects.create_token(user=self.user, name="t")
self.assertIsNone(token.last_used_at)
token.record_usage()
token.refresh_from_db()
self.assertIsNotNone(token.last_used_at)
def test_masked_token_is_hash_prefix(self):
token, plaintext = UserToken.objects.create_token(user=self.user, name="t")
masked = token.get_masked_token()
self.assertTrue(masked.startswith("tok_…"))
self.assertIn(token.token_hash[:8], masked)
# Plaintext must never leak through the masked display
self.assertNotIn(plaintext, masked)