# Path: zoe_api/custom_request_handler.py
# class ZoeRequestHandler(tornado.web.RequestHandler):
#     """Customized request handler."""
# 
#     def initialize(self, **kwargs):
#         """Initializes the request handler."""
#         super().initialize()
#         self.api_endpoint = kwargs['api_endpoint']  # type: APIEndpoint
# 
#     def get_current_user(self):
#         """Get the user making the request from one of several possible locations."""
#         auth_header = self.request.headers.get('Authorization')
#         if self.get_secure_cookie('zoe'):  # cookie auth
#             username = tornado.escape.xhtml_escape(self.get_secure_cookie('zoe'))
#             user = self.api_endpoint.user_by_name(username)
#         elif auth_header is not None and auth_header.startswith('Basic '):  # basic auth
#             auth_decoded = base64.decodebytes(bytes(auth_header[6:], 'ascii')).decode('utf-8')
#             username, password = auth_decoded.split(':', 2)
#             user = BaseAuthenticator().full_auth(username, password)
#         else:
#             user = None
# 
#         if user is None:
#             raise ZoeAuthException('Invalid username or password')
#         if not user.enabled:
#             raise ZoeAuthException('User has been disabled by the administrator')
# 
#         return user
# 
#     def on_finish(self):
#         """Log request."""
#         try:
#             user = ZoeRequestHandler.get_current_user(self)
#         except ZoeAuthException:
#             user = "not authenticated"
#         log.info("{} {} {} ({}, {}) {:.2f}ms".format(self.get_status(), self.request.method, self.request.path, self.request.remote_ip, user, self.request.request_time()))
# 
#     def data_received(self, chunk):
#         """Not implemented as we do not use stream uploads"""
# 
# Path: zoe_api/exceptions.py
# class ZoeAuthException(ZoeException):
#     """An authentication error."""
#     def __init__(self, message=None):
#         super().__init__()
#         if message is None:
#             self.message = 'Unauthorized'
#         else:
#             self.message = message
#         self.status_code = 401


import json
import datetime
import logging
import zoe_lib.config
import zoe_lib.version
from jinja2 import Environment, FileSystemLoader, Markup, TemplateSyntaxError
from tornado.escape import squeeze, linkify, url_escape, xhtml_escape
from zoe_api.custom_request_handler import ZoeRequestHandler
from zoe_api.exceptions import ZoeAuthException
    """RequestHandler class for Zoe Web interface."""

    def initialize(self, **kwargs):
        """Initialize the Jinja template system."""
        super().initialize(**kwargs)
        if 'jinja_environment' not in self.application.settings:
            raise RuntimeError("Needs jinja2 Environment. Initialize with JinjaApp.init_app first")
        else:
            self._jinja_env = self.application.settings['jinja_environment']

    def _render(self, template, **kwargs):
        """ todo: support multiple template preprocessors """

        ctx = {
            'request': self.request,
            'path_args': self.path_args,
            'path_kwargs': self.path_kwargs,
            'settings': self.application.settings,
            'reverse_url': self.application.reverse_url,
            'static_url': self.static_url,
            'xsrf_form_html': self.xsrf_form_html,
            'datetime': datetime,
            'locale': self.locale,
            'handler': self,
            'zoe_version': zoe_lib.version.ZOE_VERSION,
            'server_address': self.request.host,
        }

        try:
            ctx['user'] = super().get_current_user()

# Path: zoe_api/custom_request_handler.py
# class ZoeRequestHandler(tornado.web.RequestHandler):
#     """Customized request handler."""
# 
#     def initialize(self, **kwargs):
#         """Initializes the request handler."""
#         super().initialize()
#         self.api_endpoint = kwargs['api_endpoint']  # type: APIEndpoint
# 
#     def get_current_user(self):
#         """Get the user making the request from one of several possible locations."""
#         auth_header = self.request.headers.get('Authorization')
#         if self.get_secure_cookie('zoe'):  # cookie auth
#             username = tornado.escape.xhtml_escape(self.get_secure_cookie('zoe'))
#             user = self.api_endpoint.user_by_name(username)
#         elif auth_header is not None and auth_header.startswith('Basic '):  # basic auth
#             auth_decoded = base64.decodebytes(bytes(auth_header[6:], 'ascii')).decode('utf-8')
#             username, password = auth_decoded.split(':', 2)
#             user = BaseAuthenticator().full_auth(username, password)
#         else:
#             user = None
# 
#         if user is None:
#             raise ZoeAuthException('Invalid username or password')
#         if not user.enabled:
#             raise ZoeAuthException('User has been disabled by the administrator')
# 
#         return user
# 
#     def on_finish(self):
#         """Log request."""
#         try:
#             user = ZoeRequestHandler.get_current_user(self)
#         except ZoeAuthException:
#             user = "not authenticated"
#         log.info("{} {} {} ({}, {}) {:.2f}ms".format(self.get_status(), self.request.method, self.request.path, self.request.remote_ip, user, self.request.request_time()))
# 
#     def data_received(self, chunk):
#         """Not implemented as we do not use stream uploads"""
# 
# Path: zoe_api/exceptions.py
# class ZoeAuthException(ZoeException):
#     """An authentication error."""
#     def __init__(self, message=None):
#         super().__init__()
#         if message is None:
#             self.message = 'Unauthorized'
#         else:
#             self.message = message
#         self.status_code = 401


# Path: zoe_api/web/request_handler.py
import json
import datetime
import logging
import zoe_lib.config
import zoe_lib.version
from jinja2 import Environment, FileSystemLoader, Markup, TemplateSyntaxError
from tornado.escape import squeeze, linkify, url_escape, xhtml_escape
from zoe_api.custom_request_handler import ZoeRequestHandler
from zoe_api.exceptions import ZoeAuthException

    """RequestHandler class for Zoe Web interface."""

    def initialize(self, **kwargs):
        """Initialize the Jinja template system."""
        super().initialize(**kwargs)
        if 'jinja_environment' not in self.application.settings:
            raise RuntimeError("Needs jinja2 Environment. Initialize with JinjaApp.init_app first")
        else:
            self._jinja_env = self.application.settings['jinja_environment']

    def _render(self, template, **kwargs):
        """ todo: support multiple template preprocessors """

        ctx = {
            'request': self.request,
            'path_args': self.path_args,
            'path_kwargs': self.path_kwargs,
            'settings': self.application.settings,
            'reverse_url': self.application.reverse_url,
            'static_url': self.static_url,
            'xsrf_form_html': self.xsrf_form_html,
            'datetime': datetime,
            'locale': self.locale,
            'handler': self,
            'zoe_version': zoe_lib.version.ZOE_VERSION,
            'server_address': self.request.host,
        }

        try:
            ctx['user'] = super().get_current_user()

        except ZoeAuthException: