import gws
import gws.tools.json2
import gws.types as t
from . import sqlite
[docs]class Error(gws.Error):
"""Generic storage error"""
pass
[docs]class NotFound(Error):
"""Storage entry not found"""
pass
[docs]class AccessDenied(Error):
"""No permission to read or write the entry"""
pass
[docs]class Backend(t.Enum):
sqlite = 'sqlite'
[docs]class Mode(t.Enum):
read = 'read' #: an object can be read
write = 'write' #: an object can be written and deleted
all = 'all' #: an object can be read and written
[docs]class PermissionRule(t.WithAccess):
category: str #: storage category name
mode: Mode #: allowed mode (read/write)
[docs]class Config(t.WithType):
"""Storage"""
backend: Backend
path: t.Optional[str]
permissions: t.Optional[t.List[PermissionRule]]
#:export
[docs]class StorageEntry(t.Data):
category: str
name: str
#:export
[docs]class StorageDirectory(t.Data):
category: str
writable: bool
readable: bool
entries: t.List[StorageEntry]
#:export
[docs]class StorageElement(t.Data):
entry: StorageEntry
data: dict
#:export
[docs]class StorageRecord(t.Data):
category: str
name: str
user_fid: str
data: str
created: int
updated: int
[docs]class Object(gws.Object):
def __init__(self):
super().__init__()
self.backend = None
self.permissions: t.List[PermissionRule] = []
[docs] def read(self, entry: StorageEntry, user: t.IUser) -> StorageElement:
if not self.can_read_category(entry.category, user):
raise AccessDenied()
rec: StorageRecord = self.backend.read(entry)
if not rec:
raise NotFound()
return StorageElement(
entry=StorageEntry(category=rec.category, name=rec.name),
data=gws.tools.json2.from_string(rec.data))
[docs] def write(self, entry: StorageEntry, user: t.IUser, data: dict) -> StorageEntry:
if not self.can_write_category(entry.category, user):
raise AccessDenied()
rec = self.backend.write(entry, user, gws.tools.json2.to_string(data))
return StorageEntry(category=rec.category, name=rec.name)
[docs] def dir(self, category: str, user: t.IUser) -> t.List[t.StorageEntry]:
if not self.can_read_category(category, user):
raise AccessDenied()
return self.backend.dir(category)
[docs] def delete(self, entry: StorageEntry, user: t.IUser):
if not self.can_write_category(entry.category, user):
raise AccessDenied()
self.backend.delete(entry.category, entry.name)
[docs] def reset(self):
self.backend.reset()
[docs] def can_read_category(self, category: str, user: t.IUser) -> bool:
return self._can_use(category, user, Mode.read)
[docs] def can_write_category(self, category: str, user: t.IUser) -> bool:
return self._can_use(category, user, Mode.write)
def _can_use(self, category: str, user: t.IUser, mode):
for p in self.permissions:
if p.category in (category, '*') and p.mode in (mode, Mode.all) and user.can_use(p):
return True
return False