Files
mnemosyne/mnemosyne/mcp_server/tests/test_backfill_library_memberships.py
Robert Helewka 6a4fecf488
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 50s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m16s
fix(mcp): disable audience verification in resolve_mcp_jwt
Team JWTs include `aud=mnemosyne` while per-turn JWTs omit `aud`
entirely. Since `iss` + `typ` already partition the two token
populations, explicitly skip audience verification to avoid rejecting
valid tokens.

Also expand test coverage for the MCP auth surface to exercise all
three credential types (opaque MCPToken, per-turn JWT, team JWT),
including replay cache behavior and Neo4j-backed library resolution
via mocked cypher queries.
2026-05-10 12:32:58 -04:00

162 lines
5.2 KiB
Python

"""Tests for the ``backfill_library_memberships`` management command.
The command queries ``library.models.Library.nodes`` (Neo4j), which we
don't want to exercise in unit tests. We substitute a lightweight fake
library iterable onto ``Library.nodes.filter`` via ``unittest.mock``.
"""
from __future__ import annotations
from io import StringIO
from unittest import mock
from django.contrib.auth import get_user_model
from django.core.management import call_command
from django.core.management.base import CommandError
from django.test import TestCase
from mcp_server.models import LibraryMembership
User = get_user_model()
class _FakeLibrary:
def __init__(self, uid: str, workspace_id=None):
self.uid = uid
self.workspace_id = workspace_id
class _FakeNodes:
"""Stand-in for the neomodel ``Library.nodes`` node set."""
def __init__(self, all_libs):
self._all = list(all_libs)
def filter(self, **kwargs):
out = list(self._all)
if "workspace_id__isnull" in kwargs:
want = kwargs["workspace_id__isnull"]
out = [l for l in out if (l.workspace_id is None) == want]
return out
def _run(*cli_args):
"""Invoke the command with stdout/stderr buffered. Returns stdout."""
buf = StringIO()
call_command(
"backfill_library_memberships", *cli_args, stdout=buf, stderr=StringIO()
)
return buf.getvalue()
class BackfillCommandTest(TestCase):
def setUp(self):
self.superuser = User.objects.create_superuser(
username="admin", password="pw", email="a@b.c"
)
self.patcher = mock.patch(
"library.models.Library.nodes",
new=_FakeNodes(
[
_FakeLibrary("lib-a"), # global
_FakeLibrary("lib-b"), # global
_FakeLibrary("lib-ws", "ws-1"), # workspace-scoped
]
),
)
self.patcher.start()
self.addCleanup(self.patcher.stop)
def test_assigns_owner_to_all_global_libraries(self):
_run()
owners = LibraryMembership.objects.filter(user=self.superuser)
self.assertEqual(
sorted(owners.values_list("library_uid", flat=True)),
["lib-a", "lib-b"],
)
self.assertTrue(
all(
m.role == LibraryMembership.Role.OWNER
for m in owners
)
)
def test_skips_workspace_scoped_libraries(self):
_run()
self.assertFalse(
LibraryMembership.objects.filter(library_uid="lib-ws").exists()
)
def test_idempotent(self):
_run()
count_after_first = LibraryMembership.objects.count()
_run()
self.assertEqual(LibraryMembership.objects.count(), count_after_first)
def test_skips_libraries_with_existing_membership(self):
# Pre-seed someone else as manager on lib-a; the command should
# not overwrite or add a second row.
other = User.objects.create_user(username="other", password="pw")
LibraryMembership.objects.create(
user=other,
library_uid="lib-a",
role=LibraryMembership.Role.MANAGER,
)
_run()
# lib-a keeps its original manager-row; the superuser is NOT
# granted on it because any membership existing is an opt-out.
memberships_for_lib_a = LibraryMembership.objects.filter(
library_uid="lib-a"
)
self.assertEqual(memberships_for_lib_a.count(), 1)
self.assertEqual(memberships_for_lib_a.first().user, other)
# lib-b had none, so the superuser got it.
self.assertTrue(
LibraryMembership.objects.filter(
library_uid="lib-b", user=self.superuser
).exists()
)
def test_dry_run_does_not_persist(self):
out = _run("--dry-run")
self.assertIn("would insert", out)
self.assertEqual(LibraryMembership.objects.count(), 0)
def test_user_arg_overrides_default_superuser(self):
target = User.objects.create_user(username="librarian", password="pw")
_run("--user", "librarian")
self.assertTrue(
LibraryMembership.objects.filter(user=target).exists()
)
self.assertFalse(
LibraryMembership.objects.filter(user=self.superuser).exists()
)
def test_unknown_user_raises_command_error(self):
with self.assertRaises(CommandError):
_run("--user", "nobody")
def test_no_superuser_raises_command_error(self):
self.superuser.is_superuser = False
self.superuser.save(update_fields=["is_superuser"])
with self.assertRaises(CommandError):
_run()
class BackfillCommandEmptyNeo4jTest(TestCase):
def setUp(self):
self.superuser = User.objects.create_superuser(
username="admin", password="pw", email="a@b.c"
)
self.patcher = mock.patch(
"library.models.Library.nodes", new=_FakeNodes([])
)
self.patcher.start()
self.addCleanup(self.patcher.stop)
def test_no_libraries_is_noop(self):
_run()
self.assertEqual(LibraryMembership.objects.count(), 0)