Changeset 5613

Show
Ignore:
Timestamp:
10/25/08 08:09:34 (3 months ago)
Author:
Gustavo
Message:

Finish the introduction to tgext.authorization.

Working on the other documentation for this extension...

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • docs/2.0/docs/main/Extensions/Authorization/index.rst

    r5605 r5613  
    77.. moduleauthor:: Agendaless Consulting and Contributors 
    88 
    9 :Status: Work in progress 
     9:Status: Official 
     10 
     11 
     12This document introduces :mod:`tgext.authorization` and also explains how to 
     13get started. For more information about :mod:`tgext.authorization`, you may  
     14want to check the `advanced topics`_. 
     15 
     16.. contents:: Table of Contents 
     17    :depth: 2 
    1018 
    1119 
     
    6775~~~~~~~~~~~~~~ 
    6876Below are the contents of a mock ``.htgroups`` file that defines the groups of  
    69 your TG2 application. In other words, such a file is a :term:`group source` of 
     77a TG2 application. In other words, such a file is a :term:`group source` of 
    7078type ``htgroups``:: 
    7179 
     
    7381    admins: rms, linus 
    7482    users: gustavo, maribel 
    75      
     83 
     84It has three sections and five items: "developers" (made up of the items "rms", 
     85"linus" and "guido"), "admins" (made up of the items "rms" and "linus") and  
     86"users (made up of the items "gustavo" and "maribel"). 
     87 
    7688And below are the contents of a mock ``.ini`` file that defines the permissions 
    77 of the groups in your TG2 application. In other words, such a file is a  
     89of the groups in a TG2 application. In other words, such a file is a  
    7890:term:`permission source` of type ``Ini``:: 
    7991 
     
    8193    admins 
    8294    [release-software] 
    83     developers 
    84     [add-users] 
    8595    admins 
    8696    developers 
     
    8898    users 
    8999 
     100It has four sections and three items: "manage-site" (made up one item, 
     101"admins"), "release-software" (made up of the items "admins" and "developers") 
     102and "contact-us" (made up of the item "users"). 
     103 
    90104If you use a database to store your users, groups and permissions, then such a 
    91105database is both the group and permission source: 
     
    97111 
    98112 
    99 Implementing authorization 
    100 -------------------------- 
    101 To implement authorization in your TurboGears project, you need to add some 
     113.. _add-auth-middleware: 
     114 
     115Setting up authentication and authorization 
     116------------------------------------------- 
     117 
     118To enable authorization in your TurboGears project, you need to add some 
    102119WSGI middleware to your application, which is automatically done for you if 
    103120you are using the quickstart (:mod:`tgext.authorization.quickstart`). 
    104121 
     122When you enable authorization with :mod:`tgext.authorization`, authentication 
     123with :mod:`repoze.who` is automatically enabled. 
     124 
     125.. note:: 
     126    The `quickstart` is enabled when in ``{yourproject}.config.app_cfg`` you 
     127    have ``base_config.auth_backend`` set. To disable it, it's enough to 
     128    remove that line -- and you may also want to delete those like 
     129    ``base_config.sa_auth.*``. 
     130 
     131 
    105132Using authentication and authorization without the quickstart 
    106133~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     134 
    107135If you're not using the quickstart, then you have to add the required  
    108136middleware in your application. This gives you more flexibility, such as being 
     
    117145        from repoze.who.plugins.htpasswd import HTPasswdPlugin, crypt_check 
    118146        from tgext.authorization.middleware import setup_auth 
    119         # Please note that the plugins below have not been created; want to 
     147        # Please note that the plugins below have not been created yet; want to 
    120148        # jump in? 
    121149        from tgext.authorization.plugins.htgroups import HtgroupsAdapter 
    122150        from tgext.authorization.plugins.ini import IniPermissionAdapter 
    123151         
    124         # Defining the group adapters; you may add as much as you want
     152        # Defining the group adapters; you may add as much as you need
    125153        groups = {'all_groups': HtgroupsAdapter('/path/to/groups.htgroups')} 
    126154         
    127         # Defining the permission adapters; you may add as much as you want
     155        # Defining the permission adapters; you may add as much as you need
    128156        permissions = {'all_perms': IniPermissionAdapter('/path/to/perms.ini')} 
    129157         
    130         # repoze.who authenticators
     158        # repoze.who authenticators; you may add as much as you need
    131159        htpasswd_auth = HTPasswdPlugin('/path/to/users.htpasswd', crypt_check) 
    132160        authenticators = [('htpasswd', htpasswd_auth)] 
     
    140168        return app_with_auth 
    141169 
    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. 
     170Of course, there are other things you may customize, such as adding  
     171:mod:`repoze.who` identifiers, more authenticators, challengers and metadata  
     172providers -- read on! 
    145173 
    146174Now you're ready to add the middleware. Go to ``{yourproject}.config.middleware`` 
     
    149177    def make_app(global_conf, full_stack=True, **app_conf): 
    150178        app = make_base_app(global_conf, full_stack=True, **app_conf) 
    151         #Wrap your base turbogears app with custom middleware 
     179        # Wrap your base turbogears app with custom middleware 
    152180        app = add_auth(app, config) 
    153181        return app 
    154182 
    155183 
    156 Action-level authorization 
    157 ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    158 @TODO: Improve these contents. 
    159  
    160 Add the following methods to your controllers.root:RootController class:: 
    161  
    162     @expose('yourproject.templates.about') 
    163     @authorize.require(authorize.has_permission('manage')) 
    164     def manage_permission_only(self, **kw): 
    165         return dict(now=now, page='about') 
    166      
    167     @expose('yourproject.templates.about') 
    168     @authorize.require(authorize.is_user('editor')) 
    169     def editor_user_only(self, **kw): 
    170         return dict(now=now, page='about') 
    171  
    172     @expose('yourproject.templates.login') 
    173     def login(self, **kw): 
    174         came_from = kw.get('came_from', '/') 
    175         return dict(now=now, page='login', header=lambda *arg: None, 
    176                     footer=lambda *arg: None, came_from=came_from) 
    177  
    178 The important code to look at here is the @authorize.require decorator, which  
    179 checks that the currently logged in user is logged in user is 'editor'.   
    180  
    181  
    182 Controller-level authorization 
    183 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    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``. 
    233  
    234 Predicates 
    235 ~~~~~~~~~~ 
    236  
    237 @TODO: Elaborate more on them (more importantly, explain what they are first). 
    238  
    239 There authorize module contains various predicate checker functions: 
    240  
    241  * is_user  -- checks to see that the logged in user IS the specified user 
    242  * in_group  -- checks to see that the logged in user is in the specified group 
    243  * in_all_groups  -- is the user is all the groups specified 
    244  * in_any_group -- is the user in any of these groups 
    245  * not_anonymous -- any logged in user will do 
    246  * has_permission -- logged in user has the specified permission 
    247  * has_all_permissions -- has all the permissions listed 
    248  * has_any_permission -- has any of the listed permissions 
    249  
    250 There are also a couple of predicates you can use to aggregate the above  
    251 permissions.  
    252  
    253  * All -- used to combine the above predicate checks requiring that all of them  
    254    are true.  
    255  * Any -- same as All, but only requires that one of the checks return true.  
    256  
    257 If a user is not logged in or does not have the proper permissions the  
    258 predicate checks throw a 403 (HTTP Not Authorized) which is caught by the  
    259 tgext.authorization middleware which displays the login page allowing the user 
    260 to login, and redirecting the user back to the proper page when they are done. 
    261  
    262  
    263 Plugins 
    264 ------- 
    265  
    266 Plugins extend the functionality of :mod:`tgext.authorization` and the most 
    267 common type of plugins are those that add support for more type of group and 
    268 permission sources. 
    269  
    270 Groups handling adapters 
    271 ~~~~~~~~~~~~~~~~~~~~~~~~ 
    272 @TODO 
    273  
    274 Permissions handling adapters 
    275 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    276 @TODO 
     184What's next? 
     185------------ 
     186 
     187Once your application includes the required WSGI middleware for authentication 
     188and authorization, as explained in :ref:`add-auth-middleware`, you are ready 
     189to implement authorization in your controllers with  
     190:mod:`tgext.authorization.authorize`. 
    277191 
    278192 
     
    283197    :maxdepth: 2 
    284198 
     199    Authorize 
    285200    Quickstart 
    286201    Plugins 
    287202    ManagingSources 
    288203    WritingSourceAdapters 
     204    InnerWorkings