44 lines
1.3 KiB
Python
44 lines
1.3 KiB
Python
"""Generation-based write boundaries. Viewing and role grants are separate."""
|
|
from collections import deque
|
|
|
|
LIMIT = 5
|
|
|
|
|
|
def generations(people, links, self_id):
|
|
ids = {p['id'] for p in people}
|
|
if self_id not in ids:
|
|
return {}, False
|
|
graph = {key: [] for key in ids}
|
|
for edge in links:
|
|
a, b = edge.get('fromId'), edge.get('toId')
|
|
if not edge.get('active') or a not in ids or b not in ids:
|
|
continue
|
|
delta = 1 if edge.get('kind') == 'parent' else 0
|
|
if edge.get('kind') not in ('parent', 'spouse'):
|
|
continue
|
|
graph[a].append((b, delta))
|
|
graph[b].append((a, -delta))
|
|
levels, pending, conflict = {self_id: 0}, deque([self_id]), False
|
|
while pending:
|
|
current = pending.popleft()
|
|
for other, delta in graph[current]:
|
|
level = levels[current] + delta
|
|
if other in levels:
|
|
conflict |= levels[other] != level
|
|
else:
|
|
levels[other] = level
|
|
pending.append(other)
|
|
return levels, conflict
|
|
|
|
|
|
def within(levels, person_id):
|
|
return person_id in levels and abs(levels[person_id]) <= LIMIT
|
|
|
|
|
|
def targets(kind, item):
|
|
if kind == 'person':
|
|
return [item['id']]
|
|
if kind == 'link':
|
|
return [item['fromId'], item['toId']]
|
|
return item.get('personIds', [])
|