Add system user, prevent circular refs in author

This commit is contained in:
evilchili 2025-10-30 20:51:24 -07:00
parent 5fffbf59f5
commit f6efbeb54a
3 changed files with 33 additions and 24 deletions

View File

@ -39,6 +39,9 @@ def bootstrap():
"""
app.check_state()
# the system user does not get added to the list of Users.
app.db.save(schema.User(name="__system__"))
# create the top-level pages
root = app.db.save(schema.Page(name=app.config.VIEW_URI, body=b"This is the home page", uri=""))

View File

@ -30,13 +30,11 @@ class Form:
def prepare(self):
for key, value in self.data.items():
# filter out fields that cannot be set by the user
if key in self.read_only:
continue
if self.record[key] != value:
logger.debug(f"Updating {self.record.__class__.__name__}[{self.record.doc_id}] {key}={value}")
self.record[key] = value
self.record.author = g.user
self.record.author = None if self.record == g.user else g.user
return self.record

View File

@ -20,6 +20,13 @@ from grung.types import (
from tinydb import where
def app_context():
import ttfrog.app
ttfrog.app.check_state()
return ttfrog.app
class Permissions(StrEnum):
READ = "r"
WRITE = "w"
@ -58,20 +65,21 @@ class Page(Record):
]
# fmt: on
def parent(self, db):
def parent(self):
if self.uri == "":
return None
app = app_context()
parent_uri = ""
if "/" in self.uri:
parent_uri = self.uri.rsplit("/", 1)[0]
print(f"Checking for parent at {parent_uri=}")
for table_name in db.tables():
page = db.table(table_name).get(where('uri') == parent_uri, recurse=False)
for table_name in app.db.tables():
page = app.db.table(table_name).get(where("uri") == parent_uri, recurse=False)
if page:
return page
def before_insert(self, db):
def before_insert(self, *args, **kwargs):
"""
Make the following adjustments before saving this record:
* Derive the URI from the hierarchy of the parent.
@ -79,16 +87,20 @@ class Page(Record):
if not self.name:
raise Exception("Must provide a name")
super().before_insert(db)
app = app_context()
super().before_insert(app.db)
if not self.author:
self.author = app.db.User.get(where('name') == '__system__')
now = datetime.utcnow()
if not self.doc_id and self.created < now:
self.created = now
def add_member(self, child: Record):
from ttfrog import app
app = app_context()
app.check_state()
prefix = (self.uri + "/") if self.uri else ""
new_uri = f"{prefix}{child.name}"
if child.uri != new_uri:
@ -105,9 +117,7 @@ class Page(Record):
return None
def set_permissions(self, entity: Entity, permissions: List) -> str:
from ttfrog import app
app.check_state()
app = app_context()
perms = "".join(permissions)
self.acl[entity.reference] = perms
@ -119,9 +129,7 @@ class Page(Record):
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.
"""
from ttfrog import app
app.check_state()
app = app_context()
def find_acl(obj):
if hasattr(obj, "acl"):
@ -139,7 +147,7 @@ class Page(Record):
return group_grants
if hasattr(obj, "parent"):
return find_acl(obj.parent(app.db))
return find_acl(obj.parent())
return {"": ""}
return find_acl(self)
@ -184,20 +192,20 @@ class User(Entity):
def check_credentials(self, username: str, password: str) -> bool:
return username == self.name and self._metadata.fields["password"].compare(password, self.password)
def after_insert(self, db):
def after_insert(self, *args, **kwargs):
"""
After saving this record, ensure that any page in the members collection is updated with the
correct URI. This ensures that if a page is moved from one collection to another, the URI is updated.
"""
super().after_insert(db)
for name, _field in self._metadata.fields.items():
_field.after_insert(db, self)
app = app_context()
super().after_insert(app.db)
if not hasattr(self, "members"):
return
for child in self.members:
obj = BackReference.dereference(child, db, recurse=False)
obj = BackReference.dereference(child, app.db, recurse=False)
obj.uri = f"{self.uri}/{obj.name}"
child = db.save(obj)
child = app.db.save(obj)
class Group(Entity):