1# Copyright 2015 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Simple Request handler using Jinja2 templates."""
6
7import logging
8import os
9
10import jinja2
11import webapp2
12
13from google.appengine.api import users
14
15from dashboard import utils
16from dashboard import xsrf
17
18JINJA2_ENVIRONMENT = jinja2.Environment(
19    loader=jinja2.FileSystemLoader(
20        [os.path.join(os.path.dirname(__file__), 'templates')]),
21    # Security team suggests that autoescaping be enabled.
22    autoescape=True,
23    extensions=['jinja2.ext.autoescape'])
24
25
26class RequestHandler(webapp2.RequestHandler):
27  """Base class for requests. Does common template and error handling tasks."""
28
29  def RenderHtml(self, template_file, template_values, status=200):
30    """Renders HTML given template and values.
31
32    Args:
33      template_file: string. File name under templates directory.
34      template_values: dict. Mapping of template variables to corresponding.
35          values.
36      status: int. HTTP status code.
37    """
38    self.response.set_status(status)
39    template = JINJA2_ENVIRONMENT.get_template(template_file)
40    self.GetDynamicVariables(template_values)
41    self.response.out.write(template.render(template_values))
42
43  def RenderStaticHtml(self, filename):
44    filename = os.path.join(os.path.dirname(__file__), 'static', filename)
45    contents = open(filename, 'r')
46    self.response.out.write(contents.read())
47    contents.close()
48
49  def GetDynamicVariables(self, template_values, request_path=None):
50    """Gets the values that vary for every page.
51
52    Args:
53      template_values: dict of name/value pairs.
54      request_path: path for login urls, None if using the current path.
55    """
56    user_info = ''
57    xsrf_token = ''
58    user = users.get_current_user()
59    display_username = 'Sign in'
60    title = 'Sign in to an account'
61    is_admin = False
62    if user:
63      display_username = user.email()
64      title = 'Switch user'
65      xsrf_token = xsrf.GenerateToken(user)
66      is_admin = users.is_current_user_admin()
67    try:
68      login_url = users.create_login_url(request_path or self.request.path_qs)
69    except users.RedirectTooLongError:
70      # On the bug filing pages, the full login URL can be too long. Drop
71      # the correct redirect URL, since the user should already be logged in at
72      # this point anyway.
73      login_url = users.create_login_url('/')
74    user_info = '<a href="%s" title="%s">%s</a>' % (
75        login_url, title, display_username)
76    template_values['login_url'] = login_url
77    template_values['display_username'] = display_username
78    template_values['user_info'] = user_info
79    template_values['is_admin'] = is_admin
80    template_values['is_internal_user'] = utils.IsInternalUser()
81    template_values['xsrf_token'] = xsrf_token
82    template_values['xsrf_input'] = (
83        '<input type="hidden" name="xsrf_token" value="%s">' % xsrf_token)
84    template_values['login_url'] = login_url
85    return template_values
86
87  def ReportError(self, error_message, status=500):
88    """Reports the given error to the client and logs the error.
89
90    Args:
91      error_message: The message to log and send to the client.
92      status: The HTTP response code to use.
93    """
94    logging.error(error_message)
95    self.response.set_status(status)
96    self.response.out.write('%s\nrequest_id:%s\n' %
97                            (error_message, utils.GetRequestId()))
98
99  def ReportWarning(self, warning_message, status=200):
100    """Reports a warning to the client and logs the warning.
101
102    Args:
103      warning_message: The warning message to log (as an error).
104      status: The http response code to use.
105    """
106    logging.warning(warning_message)
107    self.response.set_status(status)
108    self.response.out.write('%s\nrequest_id:%s\n' %
109                            (warning_message, utils.GetRequestId()))
110
111
112class InvalidInputError(Exception):
113  """An error class for invalid user input query parameter values."""
114  pass
115