changeset 922:16d1084d1371

server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
author Goffi <goffi@goffi.org>
date Mon, 03 Apr 2017 01:00:26 +0200
parents cf527974a0fa
children edb322c87ea4
files src/server/constants.py src/server/server.py
diffstat 2 files changed, 58 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/server/constants.py	Mon Apr 03 00:53:09 2017 +0200
+++ b/src/server/constants.py	Mon Apr 03 01:00:26 2017 +0200
@@ -52,7 +52,13 @@
 
     ## Libervia pages ##
     PAGES_META_FILE = u"page_meta.py"
+    PAGES_ACCESS_NONE = u"none"  # no access to this page (using its path will return a 404 error)
     PAGES_ACCESS_PUBLIC = u"public"
     PAGES_ACCESS_PROFILE = u"profile"  # a session with an existing profile must be started
     PAGES_ACCESS_ADMIN = u"admin"  # only profiles set in admins_list can access the page
-    PAGES_ACCESS_ALL = (PAGES_ACCESS_PUBLIC, PAGES_ACCESS_PROFILE, PAGES_ACCESS_ADMIN)
+    PAGES_ACCESS_ALL = (PAGES_ACCESS_NONE, PAGES_ACCESS_PUBLIC, PAGES_ACCESS_PROFILE, PAGES_ACCESS_ADMIN)
+
+    ## HTTP codes ##
+    HTTP_BAD_REQUEST = 400
+    HTTP_UNAUTHORIZED = 401
+    HTTP_NOT_FOUND = 404
--- a/src/server/server.py	Mon Apr 03 00:53:09 2017 +0200
+++ b/src/server/server.py	Mon Apr 03 01:00:26 2017 +0200
@@ -1459,12 +1459,16 @@
             self.named_pages[name] = self
         if access is None:
             access = C.PAGES_ACCESS_PUBLIC
-        if access != C.PAGES_ACCESS_PUBLIC:
-            raise NotImplementedError(u"Non public access are not implemented yet")
+        if access not in (C.PAGES_ACCESS_PUBLIC, C.PAGES_ACCESS_PROFILE, C.PAGES_ACCESS_NONE):
+            raise NotImplementedError(_(u"{} access is not implemented yet").format(access))
+        self.access = access
         self.parse_url = parse_url
         self.prepare_render = prepare_render
         self.template = template
         self.render_method = render
+        if access == C.PAGES_ACCESS_NONE:
+            # none pages just return a 404, no further check is needed
+            return
         if template is None:
             if not callable(render):
                 log.error(_(u"render must be implemented and callable if template is not set"))
@@ -1525,7 +1529,7 @@
         request.prepath.append(pathElement)
         return urllib.unquote(pathElement).decode('utf-8')
 
-    def pageError(self, request, code=404):
+    def pageError(self, request, code=C.HTTP_NOT_FOUND):
         """generate an error page and terminate the request
 
         @param request(server.Request): HTTP request
@@ -1584,13 +1588,57 @@
         """don't raise error on CancelError"""
         failure_.trap(exceptions.CancelError)
 
+    def getProfile(self, request):
+        """helper method to easily get current profile
+
+        @return (unicode, None): current profile
+            None if no profile session is started
+        """
+        sat_session = self.host.getSessionData(request, session_iface.ISATSession)
+        return sat_session.profile
+
+    def getRData(self, request):
+        """helper method to get request data dict
+
+        this dictionnary if for the request only, it is not saved in session
+        It is mainly used to pass data between pages/methods called during request workflow
+        @return (dict): request data
+        """
+        try:
+            return request.data
+        except AttributeError:
+            request.data = {}
+            return request.data
+
+    def _checkAccess(self, data, request):
+        """Check access according to self.access
+
+        if access is not granted, show a HTTP_UNAUTHORIZED pageError and stop request,
+        else return data (so it can be inserted in deferred chain
+        """
+        if self.access == C.PAGES_ACCESS_PUBLIC:
+            pass
+        elif self.access == C.PAGES_ACCESS_PROFILE:
+            profile = self.getProfile(request)
+            if not profile:
+                # no session started, access is not granted
+                self.pageError(request, C.HTTP_UNAUTHORIZED)
+
+        return data
+
     def render_GET(self, request):
         if not hasattr(request, 'template_data'):
             request.template_data = {}
+
+            # XXX: here is the code which need to be executed once
+            #      at the beginning of the request hanling
             if request.postpath and not request.postpath[-1]:
                 # we don't differenciate URLs finishing with '/' or not
                 del request.postpath[-1]
+
         d = defer.Deferred()
+        d.addCallback(self._checkAccess, request)
+
         if self.parse_url is not None:
             d.addCallback(self.parse_url, request)