diff --git a/asgi_webdav/page/__init__.py b/asgi_webdav/page/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/asgi_webdav/page/base.py b/asgi_webdav/page/base.py new file mode 100644 index 00000000..998a9be2 --- /dev/null +++ b/asgi_webdav/page/base.py @@ -0,0 +1,73 @@ +from collections.abc import Callable +from dataclasses import dataclass + +from asgi_webdav.request import DAVRequest +from asgi_webdav.response import DAVResponse + + +@dataclass +class PageURL: + path: str + view: Callable + require_user: bool = True + require_admin: bool = False + + +class PageResponseBase: + pass + + +class PageResponseHTML(PageResponseBase): + pass + + +class PageResponseJSON(PageResponseBase): + pass + + +class PageResponseRedirect(PageResponseBase): + pass + + +""" +HttpResponseBadRequest +HttpResponseNotAllowed +HttpResponseNotFound +HttpResponseForbidden +HttpResponseServerError +""" + + +class PageView: + async def __call__(self, request: DAVRequest) -> DAVResponse: + status, content = self._get_response(request) + return DAVResponse(status=status, content=content.encode("utf-8")) + + def _get_response(self, request: DAVRequest) -> (int, str): + raise NotImplementedError() + + +class PageTemplateView(PageView): + pass + + +class PageEntry: + urls: list[PageURL] + + def __init__(self): + self._data = dict() + for url_obj in self.urls: + self._data[url_obj.path] = url_obj + + async def enter(self, request: DAVRequest) -> DAVResponse: + url_obj = self._data.get(request.path.raw) + if url_obj is None: + return DAVResponse(404) + + if url_obj.require_user and request.user is None: + return DAVResponse(403, content=b"Requires user privileges") + + if url_obj.require_admin and not request.user.admin: + return DAVResponse(403, content=b"Requires administrator privileges") + + return await url_obj.view(request) diff --git a/asgi_webdav/page/inside.py b/asgi_webdav/page/inside.py new file mode 100644 index 00000000..07784466 --- /dev/null +++ b/asgi_webdav/page/inside.py @@ -0,0 +1,42 @@ +from jinja2 import DictLoader, Environment + +from asgi_webdav.log import get_log_messages +from asgi_webdav.page.base import PageEntry, PageURL, PageView +from asgi_webdav.request import DAVRequest + +jinja_template_mapping = { + "info.html": """System Info: +Session Info: +User: {{ username }} +""" +} +env = Environment(loader=DictLoader(jinja_template_mapping)) + + +class IndexView(PageView): + def _get_response(self, request: DAVRequest) -> (int, str): + return 200, 'Logging page' + + +class InfoView(PageView): + def _get_response(self, request: DAVRequest) -> (int, str): + return 200, env.get_template("info.html").render(username=request.user.username) + + +class LoggingView(PageView): + def _get_response(self, request: DAVRequest) -> (int, str): + data = "" + for message in get_log_messages(): + data += message + "
" + return 200, data + + +urls = [ + PageURL("/_", IndexView()), + PageURL("/_/info", InfoView(), require_admin=True), + PageURL("/_/admin/logging", LoggingView()), +] + + +class InsidePage(PageEntry): + urls = urls diff --git a/asgi_webdav/server.py b/asgi_webdav/server.py index fd71de61..e815aa82 100644 --- a/asgi_webdav/server.py +++ b/asgi_webdav/server.py @@ -14,14 +14,14 @@ init_config_from_file, init_config_from_obj, ) -from asgi_webdav.constants import AppEntryParameters, ASGIScope, DAVMethod, DevMode +from asgi_webdav.constants import AppEntryParameters, ASGIScope, DevMode from asgi_webdav.exception import DAVExceptionProviderInitFailed from asgi_webdav.log import get_dav_logging_config from asgi_webdav.middleware.cors import ASGIMiddlewareCORS +from asgi_webdav.page.inside import InsidePage from asgi_webdav.request import DAVRequest from asgi_webdav.response import DAVResponse from asgi_webdav.web_dav import WebDAV -from asgi_webdav.web_page import WebPage logger = getLogger(__name__) @@ -41,7 +41,7 @@ def __init__(self, config: Config): logger.info(_service_abnormal_exit_message) sys.exit(1) - self.web_page = WebPage() + self.inside_page = InsidePage() async def __call__(self, scope: ASGIScope, receive, send) -> None: request, response = await self.handle(scope, receive, send) @@ -70,18 +70,11 @@ async def handle( logger.debug(request) return request, self.dav_auth.create_response_401(request, message) - # process Admin request - if ( - request.method == DAVMethod.GET - and request.src_path.count >= 1 - and request.src_path.parts[0] == "_" - ): + # route to inside page + if request.src_path.count >= 1 and request.src_path.parts[0] == "_": # route /_ - status, data = await self.web_page.enter(request) - return request, DAVResponse( - status=status, - content=data.encode("utf-8"), - ) + response = await self.inside_page.enter(request) + return request, response # process WebDAV request try: diff --git a/asgi_webdav/web_page.py b/asgi_webdav/web_page.py deleted file mode 100644 index 469a6b98..00000000 --- a/asgi_webdav/web_page.py +++ /dev/null @@ -1,41 +0,0 @@ -from asgi_webdav.log import get_log_messages -from asgi_webdav.request import DAVRequest - - -class WebPage: - async def enter(self, request: DAVRequest): - if request.path.count <= 2: - # route - # /_ - # /_/admin - # /_/??? - return 200, self.get_index_page() - - # request.path.count > 2 - if not request.user.admin: - return 403, "Requires administrator privileges" - - if request.path.parts[1] != "admin": - return 404, "" - - # request.path == "/_/admin/???" - if request.path.parts[2] == "logging": - # route /_/admin/logging - status, data = await self.get_logging_page() - - else: - status, data = 500, "something wrong" - - return status, data - - @staticmethod - def get_index_page() -> str: - return 'Logging page' - - @staticmethod - async def get_logging_page() -> (int, str): - # return 200, "this is page /_/admin/logs" - data = "" - for message in get_log_messages(): - data += message + "
" - return 200, data diff --git a/build_docker_and_test.sh b/build_docker_and_test.sh index 1ab8814b..c491d37e 100755 --- a/build_docker_and_test.sh +++ b/build_docker_and_test.sh @@ -17,5 +17,6 @@ docker run -dit --restart unless-stopped \ -e DEBUG=true \ -e WEBDAV_LOGGING_LEVEL=DEBUG \ --name asgi-webdav cr.h.rexzhang.com/ray1ex/asgi-webdav + docker image prune -f docker container logs -f asgi-webdav diff --git a/requirements/standalone.txt b/requirements/standalone.txt index 1c982f05..94caa2fd 100644 --- a/requirements/standalone.txt +++ b/requirements/standalone.txt @@ -6,3 +6,6 @@ httptools # response compress brotli # c runtime + +# inside page +jinja2