Skip to content

Commit

Permalink
config: setup RootFactory and traversal
Browse files Browse the repository at this point in the history
First of all get rid of the "home" view, which gets replaced by the top node in the RootFactory.

As a side effect, that means we need to refer to "/" directly in the login and logout views, we can't use request.route_url("home") anymore as I have not figured out a way to name the top node of the RootFactory, and I don't think you can.

For now add a single view handler for all Resource rather than a specific one for UserResource etc. Perhaps that come later, but added UserResource to the code as an example.

This view handler always produces json.

The scope= argument of Model.query hasn't landed in Samba yet, but I'll see it gets added, as it's clearly needed to override the default.

Closes #4
  • Loading branch information
robvdl committed Mar 11, 2024
1 parent 7f24610 commit b8f156c
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 3 deletions.
5 changes: 5 additions & 0 deletions src/sambal/resources/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .base import Resource
from .root import RootFactory
from .user import UserResource

__all__ = ("Resource", "RootFactory", "UserResource")
15 changes: 15 additions & 0 deletions src/sambal/resources/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from ldb import SCOPE_ONELEVEL
from samba.netcmd.domain.models import Model


class Resource(dict):
model = Model

def __init__(self, request, obj):
if request.samdb:
qs = self.model.query(request.samdb, base_dn=obj.dn, scope=SCOPE_ONELEVEL)
data = {model.name: model.as_dict() for model in qs if model}
else:
data = {}

super().__init__(**data)
17 changes: 17 additions & 0 deletions src/sambal/resources/root.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from ldb import SCOPE_ONELEVEL
from samba.netcmd.domain.models import Model

from .base import Resource


class RootFactory(dict):
model = Model

def __init__(self, request):
if request.samdb:
qs = self.model.query(request.samdb, scope=SCOPE_ONELEVEL)
data = {obj.name: Resource(request, obj) for obj in qs if obj}
else:
data = {}

super().__init__(**data)
7 changes: 7 additions & 0 deletions src/sambal/resources/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from samba.netcmd.domain.models import User

from .base import Resource


class UserResource(Resource):
model = User
5 changes: 4 additions & 1 deletion src/sambal/routes.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from sambal.resources import RootFactory


def includeme(config):
config.add_static_view("static", "static", cache_max_age=3600)
config.add_route("home", "/")
config.set_root_factory(RootFactory)
config.add_route("login", "/login/")
config.add_route("logout", "/logout/")
4 changes: 2 additions & 2 deletions src/sambal/views/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def login(request):
# Avoid looping the login page if accessed directly.
# Also, as the app uses traversal request.matched_route can be None.
if request.matched_route and request.matched_route.name == "login":
return_url = request.route_path("home")
return_url = "/"
else:
return_url = request.path

Expand All @@ -47,5 +47,5 @@ def login(request):
def logout(request):
"""Logout user."""
headers = request.logout()
redirect_url = request.route_url("home")
redirect_url = "/"
return HTTPFound(location=redirect_url, headers=headers)
14 changes: 14 additions & 0 deletions src/sambal/views/domain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from pyramid.view import view_config

from sambal.resources import Resource, RootFactory


@view_config(context=Resource, permission="read", renderer="json")
@view_config(context=RootFactory, permission="read", renderer="json")
def resource_view(context, request):
"""Temporary view to produce JSON for every node.
For this to work a custom JSON encoder is used to deal with the
various objects that aren't JSON encode-able out of the box.
"""
return context

0 comments on commit b8f156c

Please sign in to comment.