Web Status ========== .. _Jinja-Web-Templates: Jinja Web Templates ~~~~~~~~~~~~~~~~~~~ Buildbot uses Jinja2 to render its web interface. The authoritative source for this templating engine is `its own documentation `_, of course, but a few notes are in order for those who are making only minor modifications. Whitespace ++++++++++ Jinja directives are enclosed in ``{% .. %}``, and sometimes also have dashes. These dashes strip whitespace in the output. For example: .. code-block:: none {% for entry in entries %}
  • {{ entry }}
  • {% endfor %} will produce output with too much whitespace: .. code-block:: html
  • pigs
  • cows
  • But adding the dashes will collapse that whitespace completely: .. code-block:: none {% for entry in entries -%}
  • {{ entry }}
  • {%- endfor %} yields .. code-block:: html
  • pigs
  • cows
  • .. _Web-Authorization-Framework: Web Authorization Framework ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Whenever any part of the web framework wants to perform some action on the buildmaster, it should check the user's authorization first. Always check authorization twice: once to decide whether to show the option to the user (link, button, form, whatever); and once before actually performing the action. To check whether to display the option, you'll usually want to pass an authz object to the Jinja template in your :class:`HtmlResource` subclass:: def content(self, req, cxt): # ... cxt['authz'] = self.getAuthz(req) template = ... return template.render(**cxt) and then determine whether to advertise the action in the template: .. code-block:: none {{ if authz.advertiseAction('myNewTrick') }}
    ... {{ endif }} Actions can optionally require authentication, so use ``needAuthForm`` to determine whether to require a 'username' and 'passwd' field in the generated form. These fields are usually generated by :meth:`authFormIfNeeded()`: .. code-block:: none {{ authFormIfNeeded(authz, 'myNewTrick') }} Once the POST request comes in, it's time to check authorization again. This usually looks something like :: res = yield self.getAuthz(req).actionAllowed('myNewTrick', req, someExtraArg) if not res: defer.returnValue(Redirect(path_to_authfail(req))) return The ``someExtraArg`` is optional (it's handled with ``*args``, so you can have several if you want), and is given to the user's authorization function. For example, a build-related action should pass the build status, so that the user's authorization function could ensure that devs can only operate on their own builds. Note that ``actionAllowed`` returns a ``Deferred`` instance, so you must wait for the ``Deferred`` and yield the ``Redirect`` instead of returning it. The available actions are described in :bb:status:`WebStatus`.