feat: add scoped device catalog and unlimited custom area hierarchy
This commit is contained in:
+36
-1
@@ -6,7 +6,7 @@ import secrets
|
||||
|
||||
|
||||
class Households:
|
||||
TABLES = ('sites', 'assets', 'recorders', 'cameras', 'people', 'family_links', 'family_events', 'users')
|
||||
TABLES = ('sites', 'assets', 'recorders', 'cameras', 'devices', 'people', 'family_links', 'family_events', 'users')
|
||||
|
||||
def __init__(self, app):
|
||||
self.a = app
|
||||
@@ -19,6 +19,7 @@ class Households:
|
||||
a = self.a
|
||||
with a.LOCK, a.DB:
|
||||
a.DB.execute('CREATE TABLE IF NOT EXISTS households (id TEXT PRIMARY KEY, body TEXT NOT NULL)')
|
||||
a.DB.execute('CREATE TABLE IF NOT EXISTS devices (id TEXT PRIMARY KEY, body TEXT NOT NULL)')
|
||||
default = a.setting('defaultHousehold')
|
||||
if not default:
|
||||
default = secrets.token_hex(8)
|
||||
@@ -69,6 +70,22 @@ class Households:
|
||||
family = self.scope(user)
|
||||
return [x for x in self.a.objects(table) if self.family_of(x) == family]
|
||||
|
||||
def site_ids(self, user):
|
||||
"""Optional branch grants, always restricted to the account's own organization."""
|
||||
sites = self.objects(user, 'sites')
|
||||
ids = {s['id'] for s in sites if s['id'] in user.get('siteIds', [])}
|
||||
if user.get('includeSubspaces', False):
|
||||
children = {}
|
||||
for site in sites:
|
||||
children.setdefault(site.get('parentId'), []).append(site['id'])
|
||||
queue = list(ids)
|
||||
for parent in queue:
|
||||
for child in children.get(parent, []):
|
||||
if child not in ids:
|
||||
ids.add(child)
|
||||
queue.append(child)
|
||||
return ids
|
||||
|
||||
def prepare(self, user, table, body, references=()):
|
||||
family = self.scope(user)
|
||||
if body.get('familyId', family) != family:
|
||||
@@ -137,8 +154,12 @@ class Households:
|
||||
raise a.Problem('家庭不存在', 404)
|
||||
if user['role'] != 'admin' and (not old or old['id'] != self.scope(user)):
|
||||
raise a.Problem('只能管理自己所属的家庭', 403)
|
||||
kind = data.get('kind', old.get('kind', 'home') if old else 'home')
|
||||
if kind not in ('home', 'office', 'factory'):
|
||||
raise a.Problem('请选择家庭、办公场所或工厂')
|
||||
item = dict(old or {}, id=old['id'] if old else secrets.token_hex(8),
|
||||
name=a.clean_text(data.get('name', ''), 80, True),
|
||||
kind=kind,
|
||||
note=a.clean_text(data.get('note', ''), 300),
|
||||
createdAt=old['createdAt'] if old else dt.datetime.now(dt.timezone.utc).isoformat())
|
||||
a.save_object('households', item)
|
||||
@@ -148,3 +169,17 @@ class Households:
|
||||
def revision_key(self, user):
|
||||
family = self.scope(user)
|
||||
return 'familyRevision' if family == self.a.setting('defaultHousehold') else 'familyRevision:' + family
|
||||
|
||||
def save_view(self, data, user):
|
||||
if not self.manager(user):
|
||||
raise self.a.Problem('需要场所管理员权限', 403)
|
||||
groups = data.get('groups')
|
||||
if (not isinstance(groups, list) or len(groups) > 5 or
|
||||
any(g not in ('type', 'space', 'manager', 'owner', 'tag') for g in groups) or len(set(groups)) != len(groups)):
|
||||
raise self.a.Problem('分组维度不可重复,请选择类型、区域、负责人、所有人或标签')
|
||||
with self.a.LOCK:
|
||||
home = self.a.get_object('households', self.scope(user))
|
||||
home['deviceGrouping'] = groups
|
||||
self.a.save_object('households', home)
|
||||
self.a.audit('更新设备分组方式', home['name'])
|
||||
return {'ok': True}
|
||||
|
||||
Reference in New Issue
Block a user