Web Status¶
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:
{% for entry in entries %}
<li>{{ entry }}</li>
{% endfor %}
will produce output with too much whitespace:
<li>pigs</li>
<li>cows</li>
But adding the dashes will collapse that whitespace completely:
{% for entry in entries -%}
<li>{{ entry }}</li>
{%- endfor %}
yields
<li>pigs</li><li>cows</li>
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 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:
{{ if authz.advertiseAction('myNewTrick') }}
<form action="{{ myNewTrick_url }}"> ...
{{ 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 the auth form:
{% if authz.needAuthForm('myNewTrick') %}
{{ auth() }}
{% endif %}
Once the POST request comes in, it's time to check authorization again. This usually looks something like
d = self.getAuthz(req).actionAllowed('myNewTrick', req, someExtraArg)
wfd = defer.waitForDeferred(d)
yield wfd
res = wfd.getResult()
if not res:
yield 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 WebStatus.