2023-07-19 21:47:47 +09:00
|
|
|
from typing import Any, Final, NamedTuple
|
2023-07-19 13:46:23 +09:00
|
|
|
from unicodedata import normalize
|
2023-05-01 20:00:32 +09:00
|
|
|
|
|
|
|
from pydantic.dataclasses import dataclass
|
|
|
|
|
2023-05-09 14:38:13 +09:00
|
|
|
from mdrsclient.models.file import File
|
2023-05-01 20:00:32 +09:00
|
|
|
from mdrsclient.models.utils import iso8601_to_user_friendly
|
|
|
|
|
2023-05-11 17:00:14 +09:00
|
|
|
|
|
|
|
class FolderAccessLevelItem(NamedTuple):
|
2023-10-04 12:49:13 +09:00
|
|
|
mask: int
|
2023-05-11 17:00:14 +09:00
|
|
|
key: str
|
|
|
|
label: str
|
|
|
|
|
|
|
|
|
|
|
|
class FolderAccessLevel:
|
2023-10-04 12:49:13 +09:00
|
|
|
# Bit Mask
|
2023-12-18 16:59:53 +09:00
|
|
|
# - bit 0: Is Private
|
2023-10-04 12:49:13 +09:00
|
|
|
# - bit 1: Is Public
|
|
|
|
# - bit 2: With Password
|
|
|
|
# - bit 3-7: (Reserved)
|
|
|
|
# - bit 8-15: Restricted Open
|
2023-05-11 17:00:14 +09:00
|
|
|
ACCESS_LEVELS: Final[list[FolderAccessLevelItem]] = [
|
2023-10-04 12:49:13 +09:00
|
|
|
FolderAccessLevelItem(0x0204, "5kikan_or_pw_open", "5Kikan or PW Open"),
|
|
|
|
FolderAccessLevelItem(0x0104, "cbs_or_pw_open", "CBS or PW Open"),
|
|
|
|
FolderAccessLevelItem(0x0200, "5kikan_open", "5Kikan Open"),
|
|
|
|
FolderAccessLevelItem(0x0100, "cbs_open", "CBS Open"),
|
|
|
|
FolderAccessLevelItem(0x0004, "pw_open", "PW Open"),
|
|
|
|
FolderAccessLevelItem(0x0002, "public", "Public"),
|
|
|
|
FolderAccessLevelItem(0x0001, "private", "Private"),
|
|
|
|
FolderAccessLevelItem(0x0000, "storage", "Storage"),
|
2023-05-11 17:00:14 +09:00
|
|
|
]
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def key2id(key: str) -> int | None:
|
|
|
|
acl = next((x for x in FolderAccessLevel.ACCESS_LEVELS if x.key == key), None)
|
2023-10-04 12:49:13 +09:00
|
|
|
return acl.mask if acl is not None else None
|
2023-05-11 17:00:14 +09:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def id2label(id: int) -> str | None:
|
2023-10-04 12:49:13 +09:00
|
|
|
acl = next((x for x in FolderAccessLevel.ACCESS_LEVELS if (x.mask & id) == x.mask), None)
|
2023-05-11 17:00:14 +09:00
|
|
|
return acl.label if acl is not None else None
|
2023-05-01 20:00:32 +09:00
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
class FolderSimple:
|
|
|
|
id: str
|
|
|
|
pid: str | None
|
|
|
|
name: str
|
|
|
|
access_level: int
|
|
|
|
lock: bool
|
2023-12-18 16:59:53 +09:00
|
|
|
size: int
|
2023-12-07 14:46:57 +09:00
|
|
|
laboratory_id: int
|
2023-05-01 20:00:32 +09:00
|
|
|
description: str
|
|
|
|
created_at: str
|
|
|
|
updated_at: str
|
|
|
|
restrict_opened_at: str | None
|
|
|
|
|
|
|
|
@property
|
|
|
|
def access_level_name(self) -> str:
|
2023-05-11 17:00:14 +09:00
|
|
|
label = FolderAccessLevel.id2label(self.access_level)
|
|
|
|
return label if label is not None else ""
|
2023-05-01 20:00:32 +09:00
|
|
|
|
|
|
|
@property
|
|
|
|
def lock_name(self) -> str:
|
|
|
|
return "locked" if self.lock else "unlocked"
|
|
|
|
|
|
|
|
@property
|
|
|
|
def created_at_name(self) -> str:
|
|
|
|
return iso8601_to_user_friendly(self.created_at)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def updated_at_name(self) -> str:
|
|
|
|
return iso8601_to_user_friendly(self.updated_at)
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
class Folder(FolderSimple):
|
2023-07-19 21:47:47 +09:00
|
|
|
metadata: list[dict[str, Any]]
|
2023-05-01 20:00:32 +09:00
|
|
|
sub_folders: list[FolderSimple]
|
|
|
|
files: list[File]
|
|
|
|
path: str
|
|
|
|
|
|
|
|
def find_sub_folder(self, name: str) -> FolderSimple | None:
|
2023-07-19 13:46:23 +09:00
|
|
|
_name = normalize("NFC", name).lower()
|
|
|
|
return next((x for x in self.sub_folders if x.name.lower() == _name), None)
|
2023-05-01 20:00:32 +09:00
|
|
|
|
|
|
|
def find_file(self, name: str) -> File | None:
|
2023-07-19 13:46:23 +09:00
|
|
|
_name = normalize("NFC", name).lower()
|
|
|
|
return next((x for x in self.files if x.name.lower() == _name), None)
|