| 107 | | @TODO: Improve these contents. |
|---|
| 108 | | |
|---|
| 109 | | You then write code like this to require authorization:: |
|---|
| 110 | | |
|---|
| 111 | | from tgext.authorization import authorize |
|---|
| | 101 | To implement authorization in your TurboGears project, you need to add some |
|---|
| | 102 | WSGI middleware to your application, which is automatically done for you if |
|---|
| | 103 | you are using the quickstart (:mod:`tgext.authorization.quickstart`). |
|---|
| | 104 | |
|---|
| | 105 | Using authentication and authorization without the quickstart |
|---|
| | 106 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| | 107 | If you're not using the quickstart, then you have to add the required |
|---|
| | 108 | middleware in your application. This gives you more flexibility, such as being |
|---|
| | 109 | able not to use a database to store your users' credentials, your groups |
|---|
| | 110 | and/or your permissions. |
|---|
| | 111 | |
|---|
| | 112 | You are highly encouraged to add such a middleware with a function defined in, |
|---|
| | 113 | say, ``{yourproject}.config.middleware`` and called, say, ``add_auth``. Then |
|---|
| | 114 | such a function may look like this:: |
|---|
| | 115 | |
|---|
| | 116 | def add_auth(app, config): |
|---|
| | 117 | from repoze.who.plugins.htpasswd import HTPasswdPlugin, crypt_check |
|---|
| | 118 | from tgext.authorization.middleware import setup_auth |
|---|
| | 119 | # Please note that the plugins below have not been created; want to |
|---|
| | 120 | # jump in? |
|---|
| | 121 | from tgext.authorization.plugins.htgroups import HtgroupsAdapter |
|---|
| | 122 | from tgext.authorization.plugins.ini import IniPermissionAdapter |
|---|
| | 123 | |
|---|
| | 124 | # Defining the group adapters; you may add as much as you want: |
|---|
| | 125 | groups = {'all_groups': HtgroupsAdapter('/path/to/groups.htgroups')} |
|---|
| | 126 | |
|---|
| | 127 | # Defining the permission adapters; you may add as much as you want: |
|---|
| | 128 | permissions = {'all_perms': IniPermissionAdapter('/path/to/perms.ini')} |
|---|
| | 129 | |
|---|
| | 130 | # repoze.who authenticators: |
|---|
| | 131 | htpasswd_auth = HTPasswdPlugin('/path/to/users.htpasswd', crypt_check) |
|---|
| | 132 | authenticators = [('htpasswd', htpasswd_auth)] |
|---|
| | 133 | |
|---|
| | 134 | app_with_auth = setup_auth( |
|---|
| | 135 | app, |
|---|
| | 136 | config, |
|---|
| | 137 | groups, |
|---|
| | 138 | permissions, |
|---|
| | 139 | authenticators) |
|---|
| | 140 | return app_with_auth |
|---|
| | 141 | |
|---|
| | 142 | Of course, there are other things you may customize; such as adding repoze.who |
|---|
| | 143 | identifiers, more authenticators, challengers and metadata providers, which |
|---|
| | 144 | is explained later in this documentation. |
|---|
| | 145 | |
|---|
| | 146 | Now you're ready to add the middleware. Go to ``{yourproject}.config.middleware`` |
|---|
| | 147 | and edit ``make_auth`` to make it look like this:: |
|---|
| | 148 | |
|---|
| | 149 | def make_app(global_conf, full_stack=True, **app_conf): |
|---|
| | 150 | app = make_base_app(global_conf, full_stack=True, **app_conf) |
|---|
| | 151 | #Wrap your base turbogears app with custom middleware |
|---|
| | 152 | app = add_auth(app, config) |
|---|
| | 153 | return app |
|---|
| 141 | | @TODO |
|---|
| 142 | | |
|---|
| | 184 | If you want that all the actions from a given controller meet a common |
|---|
| | 185 | authorization criteria, then you may define the ``require`` attribute of |
|---|
| | 186 | your controller class:: |
|---|
| | 187 | |
|---|
| | 188 | class Admin(SecureController): |
|---|
| | 189 | require = authorize.has_permission('manage') |
|---|
| | 190 | |
|---|
| | 191 | @expose('yourproject.templates.index') |
|---|
| | 192 | def index(self): |
|---|
| | 193 | flash(_("Secure Controller here")) |
|---|
| | 194 | return dict(page='index') |
|---|
| | 195 | |
|---|
| | 196 | @expose('yourproject.templates.index') |
|---|
| | 197 | def some_where(self): |
|---|
| | 198 | """This are is protected too. |
|---|
| | 199 | |
|---|
| | 200 | Only those with "manage" permissions may access. |
|---|
| | 201 | |
|---|
| | 202 | """ |
|---|
| | 203 | return dict() |
|---|
| | 204 | |
|---|
| | 205 | Where your ``SecureController`` class may look like this:: |
|---|
| | 206 | |
|---|
| | 207 | class SecureController(BaseController): |
|---|
| | 208 | """SecureController implementation for the tgext.authorization extension. |
|---|
| | 209 | |
|---|
| | 210 | it will permit to protect whole controllers with a single predicate |
|---|
| | 211 | placed at the controller level. |
|---|
| | 212 | The only thing you need to have is a 'require' attribute which must |
|---|
| | 213 | be a callable. This callable will only be authorized to return True |
|---|
| | 214 | if the user is allowed and False otherwise. This may change to convey info |
|---|
| | 215 | when securecontroller is fully debugged... |
|---|
| | 216 | """ |
|---|
| | 217 | |
|---|
| | 218 | def check_security(self): |
|---|
| | 219 | errors = [] |
|---|
| | 220 | environ = request.environ |
|---|
| | 221 | identity = environ.get('repoze.who.identity') |
|---|
| | 222 | if not hasattr(self, "require") or \ |
|---|
| | 223 | self.require is None or \ |
|---|
| | 224 | self.require.eval_with_object(identity, errors): |
|---|
| | 225 | return True |
|---|
| | 226 | |
|---|
| | 227 | # if we did not return this is an error :) |
|---|
| | 228 | # TODO: do something with the errors variable like informing our user... |
|---|
| | 229 | return False |
|---|
| | 230 | |
|---|
| | 231 | If you enabled authentication/authorization in your project when it was created, |
|---|
| | 232 | then this class is defined in ``{yourproject}.lib.base``. |
|---|