Files
mdrs-client-python/tests/test_folder_access_level.py
T
orrisroot a2bc9bb642 feat: build access level labels from their bits and project names
Labels came from a fixed table matched by subset, so Storage (no bits)
matched any level the table lacked, and a level was named after the first
entry it contained: the server's Brain/MINDS 2.0 folders (0x10000) showed
as Storage and 0x10104 as CBS or PW Open.

Labels are now composed from the bits. Projects (bit 16 and up) take the
names the server reports to their members through users/current/, and
otherwise Project<n>; restrict slot 1 is CBS and any other Restrict<n>.
A level with no meaning is shown as Unknown (0x...). chacl reads keys
built the same way, refuses public and storage before any request, and
lists the user's projects with their keys when given an invalid level.
2026-11-13 16:53:25 +09:00

155 lines
5.5 KiB
Python

import unittest
from unittest.mock import MagicMock, patch
from mdrsclient.api import UsersApi
from mdrsclient.models import FolderSimple
from mdrsclient.models.folder import FolderAccessLevel
from mdrsclient.services import MdrsService
TIMESTAMP = "2026-01-01T00:00:00+09:00"
BM2 = {0: "Brain/MINDS 2.0"}
def make_folder(access_level: int) -> FolderSimple:
return FolderSimple(
id="f1",
pid=None,
name="data",
access_level=access_level,
lock=False,
size=0,
laboratory_id=1,
description="",
created_at=TIMESTAMP,
updated_at=TIMESTAMP,
restrict_opened_at=None,
)
def current_user(projects: list[dict]) -> dict:
return {
"id": 1,
"username": "user",
"first_name": "",
"last_name": "",
"email": "",
"orcid_id": "",
"laboratories": [],
"is_staff": False,
"is_active": True,
"is_superuser": False,
"is_reviewer": False,
"last_login": TIMESTAMP,
"date_joined": TIMESTAMP,
"projects": projects,
}
class TestId2Label(unittest.TestCase):
def test_single_levels(self) -> None:
cases = {
0x0000: "Storage",
0x0001: "Private",
0x0002: "Public",
0x0004: "PW Open",
0x0100: "CBS Open",
0x0104: "CBS or PW Open",
}
for id, label in cases.items():
with self.subTest(id=hex(id)):
self.assertEqual(FolderAccessLevel.id2label(id), label)
def test_restrict_slot_without_a_name_is_numbered(self) -> None:
self.assertEqual(FolderAccessLevel.id2label(0x0200), "Restrict2 Open")
self.assertEqual(FolderAccessLevel.id2label(0x8000), "Restrict8 Open")
def test_project_is_named_from_the_server(self) -> None:
self.assertEqual(FolderAccessLevel.id2label(0x10000, BM2), "Brain/MINDS 2.0 Open")
self.assertEqual(FolderAccessLevel.id2label(0x10004, BM2), "Brain/MINDS 2.0 or PW Open")
def test_project_not_named_gets_its_bit_position(self) -> None:
self.assertEqual(FolderAccessLevel.id2label(0x10000), "Project0 Open")
self.assertEqual(FolderAccessLevel.id2label(0x20000, BM2), "Project1 Open")
def test_parts_are_restrict_then_project_then_password(self) -> None:
self.assertEqual(
FolderAccessLevel.id2label(0x30304, BM2), "CBS or Restrict2 or Brain/MINDS 2.0 or Project1 or PW Open"
)
def test_meaningless_levels_are_unlabelled(self) -> None:
# Private or Public mixed with another bit, a reserved bit, a negative value.
for id in (0x0003, 0x0006, 0x0102, 0x10001, 0x0008, 0x0080, -1):
with self.subTest(id=hex(id)):
self.assertIsNone(FolderAccessLevel.id2label(id))
class TestKey2Id(unittest.TestCase):
def test_keys(self) -> None:
cases = {
"storage": 0x0000,
"private": 0x0001,
"public": 0x0002,
"pw_open": 0x0004,
"cbs_open": 0x0100,
"cbs_or_pw_open": 0x0104,
"restrict1_open": 0x0100,
"restrict2_open": 0x0200,
"project0_open": 0x10000,
"project1_or_pw_open": 0x20004,
}
for key, id in cases.items():
with self.subTest(key=key):
self.assertEqual(FolderAccessLevel.key2id(key), id)
def test_unknown_keys(self) -> None:
for key in ("5kikan_open", "restrict9_open", "restrict0_open", "project01_open", "cbs", "_open", "pw_or_open"):
with self.subTest(key=key):
self.assertIsNone(FolderAccessLevel.key2id(key))
class TestAccessLevelLabel(unittest.TestCase):
def test_known_level(self) -> None:
self.assertEqual(make_folder(0x0100).access_level_name, "CBS Open")
def test_project_names_are_used(self) -> None:
self.assertEqual(make_folder(0x10000).access_level_label(BM2), "Brain/MINDS 2.0 Open")
self.assertEqual(make_folder(0x10000).access_level_name, "Project0 Open")
def test_meaningless_level_shows_its_value(self) -> None:
self.assertEqual(make_folder(0x0008).access_level_name, "Unknown (0x8)")
class TestProjectNames(unittest.TestCase):
def test_anonymous_user_asks_nothing(self) -> None:
connection = MagicMock()
connection.token = None
with patch("mdrsclient.services.UsersApi") as users_api:
self.assertEqual(MdrsService(connection).project_names(), {})
users_api.assert_not_called()
def test_names_by_bit_position(self) -> None:
connection = MagicMock()
connection.get.return_value.json.return_value = current_user(
[
{"id": 1, "name": "Brain/MINDS 2.0", "bit_position": 0},
{"id": 2, "name": "B", "bit_position": 3},
{"id": 3, "name": "A", "bit_position": 3},
{"id": 4, "name": None, "bit_position": 5},
]
)
with patch.object(UsersApi, "_raise_response_error"):
names = UsersApi(connection).project_names()
self.assertEqual(names, {0: "Brain/MINDS 2.0", 3: "A, B"})
def test_server_without_projects(self) -> None:
connection = MagicMock()
user = current_user([])
del user["projects"]
connection.get.return_value.json.return_value = user
with patch.object(UsersApi, "_raise_response_error"):
self.assertEqual(UsersApi(connection).project_names(), {})
if __name__ == "__main__":
unittest.main()