Changeset 5605

Show
Ignore:
Timestamp:
10/24/08 14:55:09 (3 months ago)
Author:
Gustavo
Message:

Added more documentation for tgext.authorization, but it's still unfinished

Files:

Legend:

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

    r5577 r5605  
    6767~~~~~~~~~~~~~~ 
    6868Below 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 ``group source`` of type 
    70 ``htgroups``:: 
     69your TG2 application. In other words, such a file is a :term:`group source` of 
     70type ``htgroups``:: 
    7171 
    7272    developers: rms, linus, guido 
     
    7474    users: gustavo, maribel 
    7575     
    76 And below are the contents of a mock ``*.ini`` file that defines the permissions 
     76And below are the contents of a mock ``.ini`` file that defines the permissions 
    7777of the groups in your TG2 application. In other words, such a file is a  
    78 ``permission source`` of type ``Ini``:: 
     78:term:`permission source` of type ``Ini``:: 
    7979 
    8080    [manage-site] 
     
    9292 
    9393  * The tables where you store your groups and users are the sections and the 
    94     section items, respectively, of the group source. They form a many-to-many 
    95     relationship in which the children of a group (aka "section") are the 
    96     users (aka "items") that belong to the group/section, and the children of 
    97     a user are the groups she belongs to. 
     94    section items, respectively, of the ``group source``. 
    9895  * The tables where you store your permissions and groups are the sections and  
    99     the section items, respectively, of the permission source. They form a  
    100     many-to-many relationship in which the children of a permission (aka  
    101     "section") are the group (aka "items") that are granted the permission, and 
    102     the children of a group are the permissions granted to the group. 
     96    the section items, respectively, of the ``permission source``. 
    10397 
    10498 
    10599Implementing authorization 
    106100-------------------------- 
    107 @TODO: Improve these contents. 
    108  
    109 You then write code like this to require authorization:: 
    110  
    111    from tgext.authorization import authorize 
     101To implement authorization in your TurboGears project, you need to add some 
     102WSGI middleware to your application, which is automatically done for you if 
     103you are using the quickstart (:mod:`tgext.authorization.quickstart`). 
     104 
     105Using authentication and authorization without the quickstart 
     106~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     107If you're not using the quickstart, then you have to add the required  
     108middleware in your application. This gives you more flexibility, such as being 
     109able not to use a database to store your users' credentials, your groups 
     110and/or your permissions. 
     111 
     112You are highly encouraged to add such a middleware with a function defined in, 
     113say, ``{yourproject}.config.middleware`` and called, say, ``add_auth``. Then 
     114such 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 
     142Of course, there are other things you may customize; such as adding repoze.who 
     143identifiers, more authenticators, challengers and metadata providers, which 
     144is explained later in this documentation. 
     145 
     146Now you're ready to add the middleware. Go to ``{yourproject}.config.middleware`` 
     147and 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 
    112154 
    113155 
     
    118160Add the following methods to your controllers.root:RootController class:: 
    119161 
    120     @expose('whotg.templates.about') 
     162    @expose('yourproject.templates.about') 
    121163    @authorize.require(authorize.has_permission('manage')) 
    122164    def manage_permission_only(self, **kw): 
    123165        return dict(now=now, page='about') 
    124166     
    125     @expose('whotg.templates.about') 
     167    @expose('yourproject.templates.about') 
    126168    @authorize.require(authorize.is_user('editor')) 
    127169    def editor_user_only(self, **kw): 
    128170        return dict(now=now, page='about') 
    129171 
    130     @expose('whotg.templates.login') 
     172    @expose('yourproject.templates.login') 
    131173    def login(self, **kw): 
    132174        came_from = kw.get('came_from', '/') 
     
    137179checks that the currently logged in user is logged in user is 'editor'.   
    138180 
     181 
    139182Controller-level authorization 
    140183~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    141 @TODO 
    142  
     184If you want that all the actions from a given controller meet a common 
     185authorization criteria, then you may define the ``require`` attribute of 
     186your 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 
     205Where 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 
     231If you enabled authentication/authorization in your project when it was created, 
     232then this class is defined in ``{yourproject}.lib.base``. 
    143233 
    144234Predicates 
     
    167257If a user is not logged in or does not have the proper permissions the  
    168258predicate checks throw a 403 (HTTP Not Authorized) which is caught by the  
    169 tg.ext.repoze.who middleware which displays the login page allowing the user 
     259tgext.authorization middleware which displays the login page allowing the user 
    170260to login, and redirecting the user back to the proper page when they are done. 
    171261 
     
    174264------- 
    175265 
    176 @TODO: Most probably Gustavo's job because this is the most important change 
    177 from tg.ext.repoze.who. 
    178  
    179 Groups handling plugins 
    180 ~~~~~~~~~~~~~~~~~~~~~~~ 
    181 @TODO: Most probably Gustavo's job. 
    182  
    183 Permissions handling plugins 
    184 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    185 @TODO: Most probably Gustavo's job. 
     266Plugins extend the functionality of :mod:`tgext.authorization` and the most 
     267common type of plugins are those that add support for more type of group and 
     268permission sources. 
     269 
     270Groups handling adapters 
     271~~~~~~~~~~~~~~~~~~~~~~~~ 
     272@TODO 
     273 
     274Permissions handling adapters 
     275~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     276@TODO 
    186277 
    187278