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