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() 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 # create the top-level pages
root = app.db.save(schema.Page(name=app.config.VIEW_URI, body=b"This is the home page", uri="")) 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): def prepare(self):
for key, value in self.data.items(): for key, value in self.data.items():
# filter out fields that cannot be set by the user
if key in self.read_only: if key in self.read_only:
continue continue
if self.record[key] != value: 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[key] = value
self.record.author = g.user self.record.author = None if self.record == g.user else g.user
return self.record return self.record

View File

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