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 th 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
if not self.getAuthz(req).actionAllowed('myNewTrick', req, someExtraArg): return Redirect(path_to_authfail(req))
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.
The available actions are listed in see WebStatus Configuration Parameters.