implement primary keys
This commit is contained in:
parent
b395940d2d
commit
bb3070aa1a
|
@ -2,11 +2,18 @@ from __future__ import annotations
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import List
|
from typing import List
|
||||||
|
from enum import StrEnum
|
||||||
|
|
||||||
from grung.types import BackReference, Collection, DateTime, Dict, 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
|
||||||
|
|
||||||
|
|
||||||
|
class Permissions(StrEnum):
|
||||||
|
READ = "r"
|
||||||
|
WRITE = "w"
|
||||||
|
DELETE = "d"
|
||||||
|
|
||||||
|
|
||||||
class Page(Record):
|
class Page(Record):
|
||||||
"""
|
"""
|
||||||
A page in the wiki. Just about everything in the databse is either a Page or a subclass of a Page.
|
A page in the wiki. Just about everything in the databse is either a Page or a subclass of a Page.
|
||||||
|
@ -16,7 +23,7 @@ class Page(Record):
|
||||||
def fields(cls):
|
def fields(cls):
|
||||||
# fmt: off
|
# fmt: off
|
||||||
return [
|
return [
|
||||||
*super().fields(), # Pick up the UID and whatever other non-optional fields exist
|
*super().fields(),
|
||||||
Field("uri", unique=True), # The URI for the page, relative to the app's VIEW_URI
|
Field("uri", unique=True), # The URI for the page, relative to the app's VIEW_URI
|
||||||
Field("name"), # The portion of the URI after the last /
|
Field("name"), # The portion of the URI after the last /
|
||||||
Field("title"), # The page title
|
Field("title"), # The page title
|
||||||
|
@ -74,7 +81,7 @@ class Page(Record):
|
||||||
|
|
||||||
def get_child(self, obj: Record):
|
def get_child(self, obj: Record):
|
||||||
for page in self.members:
|
for page in self.members:
|
||||||
if page.uid == obj.uid:
|
if page[page._metadata.primary_key] == obj[obj._metadata.primary_key]:
|
||||||
return page
|
return page
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -104,8 +111,9 @@ class Page(Record):
|
||||||
|
|
||||||
group_grants = {}
|
group_grants = {}
|
||||||
for ref, grant in obj.acl.items():
|
for ref, grant in obj.acl.items():
|
||||||
if ref.startswith("Group::"):
|
(table_name, pkey, pval) = ref.split("::")
|
||||||
group = app.db.Group.get(where("uid") == ref.split("::")[1], recurse=False)
|
if table_name == "Group":
|
||||||
|
group = app.db.Group.get(where(pkey) == pval, recurse=False)
|
||||||
if entity.reference in group.members:
|
if entity.reference in group.members:
|
||||||
group_grants[ref] = grant
|
group_grants[ref] = grant
|
||||||
if group_grants:
|
if group_grants:
|
||||||
|
@ -119,6 +127,18 @@ class Page(Record):
|
||||||
|
|
||||||
|
|
||||||
class Entity(Page):
|
class Entity(Page):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fields(cls):
|
||||||
|
inherited = [
|
||||||
|
field
|
||||||
|
for field in super().fields()
|
||||||
|
if field.name not in ("members", "uid")
|
||||||
|
]
|
||||||
|
return inherited + [
|
||||||
|
Field("name", primary_key=True),
|
||||||
|
]
|
||||||
|
|
||||||
def has_permission(self, record: Record, requested: str) -> bool | None:
|
def has_permission(self, record: Record, requested: str) -> bool | None:
|
||||||
for entity, grants in record.get_acl_for_entity(self).items():
|
for entity, grants in record.get_acl_for_entity(self).items():
|
||||||
if requested in grants:
|
if requested in grants:
|
||||||
|
@ -140,39 +160,29 @@ class User(Entity):
|
||||||
A website user, editable as a wiki page.
|
A website user, editable as a wiki page.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def check_credentials(self, username: str, password: str) -> bool:
|
|
||||||
return username == self.name and self._metadata.fields["password"].compare(password, self.password)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fields(cls):
|
def fields(cls):
|
||||||
return [
|
return super().fields() + [
|
||||||
field
|
|
||||||
for field in [
|
|
||||||
*super().fields(),
|
|
||||||
Field("email", unique=True),
|
Field("email", unique=True),
|
||||||
Password("password"),
|
Password("password"),
|
||||||
]
|
]
|
||||||
if field.name != "members"
|
|
||||||
]
|
def check_credentials(self, username: str, password: str) -> bool:
|
||||||
|
return username == self.name and self._metadata.fields["password"].compare(password, self.password)
|
||||||
|
|
||||||
|
|
||||||
class Group(Entity):
|
class Group(Entity):
|
||||||
"""
|
"""
|
||||||
A set of users, editable as a wiki page.
|
A set of users, editable as a wiki page.
|
||||||
"""
|
"""
|
||||||
|
@classmethod
|
||||||
|
def fields(cls):
|
||||||
|
return super().fields() + [
|
||||||
|
Collection("members", Entity)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class NPC(Page):
|
class NPC(Page):
|
||||||
"""
|
"""
|
||||||
An NPC, editable as a wiki page.
|
An NPC, editable as a wiki page.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Permissions(Record):
|
|
||||||
READ = "r"
|
|
||||||
WRITE = "w"
|
|
||||||
DELETE = "d"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def fields(cls):
|
|
||||||
return [*super().fields(), Pointer("entity", Entity), Field("grants")]
|
|
||||||
|
|
|
@ -48,8 +48,8 @@ def get_page(path: str = "", table: str = "Page", create_okay: bool = False):
|
||||||
if hasattr(page, "members"):
|
if hasattr(page, "members"):
|
||||||
subpages = []
|
subpages = []
|
||||||
for pointer in page.members:
|
for pointer in page.members:
|
||||||
table, uid = pointer.split("::")
|
table, pkey, pval = pointer.split("::")
|
||||||
subpages += app.db.table(table).search(where("uid") == uid, recurse=False)
|
subpages += app.db.table(table).search(where(pkey) == pval, recurse=False)
|
||||||
page.members = subpages
|
page.members = subpages
|
||||||
|
|
||||||
return page
|
return page
|
||||||
|
@ -105,6 +105,7 @@ def logout():
|
||||||
if "user_id" in session:
|
if "user_id" in session:
|
||||||
del session["user_id"]
|
del session["user_id"]
|
||||||
del g.user
|
del g.user
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
|
|
||||||
@app.web.route(f"{app.config.VIEW_URI}/<path:table>/<path:path>", methods=["GET"])
|
@app.web.route(f"{app.config.VIEW_URI}/<path:table>/<path:path>", methods=["GET"])
|
||||||
|
|
Loading…
Reference in New Issue
Block a user