# HG changeset patch # User Goffi # Date 1491174026 -7200 # Node ID 16d1084d1371ab19250277e127ce8fd5af57c36c # Parent cf527974a0fa156c97b872c67501bc516fc42f37 server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data diff -r cf527974a0fa -r 16d1084d1371 src/server/constants.py --- 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 diff -r cf527974a0fa -r 16d1084d1371 src/server/server.py --- 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)