move ACL to Dict field
This commit is contained in:
parent
2064890ea5
commit
b395940d2d
|
@ -1,10 +1,9 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from functools import cache
|
||||
from typing import List
|
||||
|
||||
from grung.types import BackReference, Collection, DateTime, Field, Password, Pointer, Record, Timestamp
|
||||
from grung.types import BackReference, Collection, DateTime, Dict, Field, Password, Pointer, Record, Timestamp
|
||||
from tinydb import where
|
||||
|
||||
|
||||
|
@ -27,7 +26,7 @@ class Page(Record):
|
|||
Pointer("author", value_type=User), # The last user to touch the page.
|
||||
DateTime("created"), # When the page was created
|
||||
Timestamp("last_modified"), # The last time the page was modified.
|
||||
Collection("acl", Permissions), # The access control list
|
||||
Dict("acl"),
|
||||
]
|
||||
# fmt: on
|
||||
|
||||
|
@ -79,18 +78,17 @@ class Page(Record):
|
|||
return page
|
||||
return None
|
||||
|
||||
def set_permissions(self, entity: Entity, permissions: List) -> Record:
|
||||
def set_permissions(self, entity: Entity, permissions: List) -> str:
|
||||
from ttfrog import app
|
||||
|
||||
app.check_state()
|
||||
|
||||
perms = app.db.save(Permissions(entity=entity, grants="".join(permissions)))
|
||||
self.acl = list(set(self.acl + [perms]))
|
||||
perms = "".join(permissions)
|
||||
self.acl[entity.reference] = perms
|
||||
app.db.save(self)
|
||||
return perms
|
||||
|
||||
@cache
|
||||
def get_acl_for_entity(self, entity) -> list:
|
||||
def get_acl_for_entity(self, entity) -> (str, str | None):
|
||||
"""
|
||||
Search upward through the page hierarchy looking for one with an ACL that either
|
||||
has a grant for the entity we care about, or at least one group in which the entity is a member.
|
||||
|
@ -101,36 +99,29 @@ class Page(Record):
|
|||
|
||||
def find_acl(obj):
|
||||
if hasattr(obj, "acl"):
|
||||
# examine each entry in the ACL and see if one refers to the entity we care about
|
||||
group_grants = []
|
||||
for entry in obj.acl:
|
||||
if type(entry) == str:
|
||||
entry = app.db.Permissions.get(where("uid") == entry.split("::")[1], recurse=False)
|
||||
if entity.reference in obj.acl:
|
||||
return {entity.reference: obj.acl[entity.reference]}
|
||||
|
||||
# grants specific to the entity always take precedence
|
||||
if entry.entity.uid == entity.uid:
|
||||
return [entry]
|
||||
|
||||
# keep track of grants to groups containing the entity
|
||||
elif entity.reference in getattr(entry.entity, "members", []):
|
||||
group_grants.append(entry)
|
||||
|
||||
# if we found group grants, return them
|
||||
group_grants = {}
|
||||
for ref, grant in obj.acl.items():
|
||||
if ref.startswith("Group::"):
|
||||
group = app.db.Group.get(where("uid") == ref.split("::")[1], recurse=False)
|
||||
if entity.reference in group.members:
|
||||
group_grants[ref] = grant
|
||||
if group_grants:
|
||||
return group_grants
|
||||
|
||||
# no ACL on this object, so check its parent, if there is one
|
||||
if not hasattr(obj, "parent"):
|
||||
return []
|
||||
return find_acl(obj.parent)
|
||||
if hasattr(obj, "parent"):
|
||||
return find_acl(obj.parent)
|
||||
return {"": ""}
|
||||
|
||||
return find_acl(self)
|
||||
|
||||
|
||||
class Entity(Page):
|
||||
def has_permission(self, record: Record, requested: str) -> bool | None:
|
||||
for acl in record.get_acl_for_entity(self):
|
||||
if requested in acl.grants:
|
||||
for entity, grants in record.get_acl_for_entity(self).items():
|
||||
if requested in grants:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
|
|
@ -58,7 +58,6 @@ def test_permissions(app):
|
|||
# set to rw, no delete
|
||||
notes.set_permissions(players, [schema.Permissions.READ, schema.Permissions.WRITE])
|
||||
notes = app.db.Page.get(doc_id=notes.doc_id)
|
||||
|
||||
assert players.can_read(notes)
|
||||
assert players.can_write(notes)
|
||||
assert not players.can_delete(notes)
|
||||
|
|
Loading…
Reference in New Issue
Block a user