Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Changes between Version 78 and Version 79 of IdentityManagement


Ignore:
Timestamp:
08/30/06 11:26:43 (13 years ago)
Author:
tlesher
Comment:

Updated to 1.0rc; fixed formatting.

Legend:

Unmodified
Added
Removed
Modified
  • IdentityManagement

    v78 v79  
    11= Identity Management = 
    22 
    3 Here is a Tutorial for getting TurboGears identity management support up and running. 
    4  
    5 This Tutorial is written from the perspective of a fresh quick-started project 
    6  
    7 = Part I: Identity Basics = 
    8  
    9 == A. Quick-Start == 
    10  
    11 To begin with the tutorial, let's quick-start a learning project "identity_tutorial". Of course, everything you learn in the tutorial applies to existing projects as well. 
    12  
    13 TurboGears currently support two provider: SQLObject and SQLAlchemy. 
    14  
    15 To start with SQLObject, type 
    16  
    17 {{{ 
    18 #!python 
    19 $ tg-admin quickstart identity_tutorial 
    20 }}} 
    21  
    22 To start with SQLAlchemy, type 
    23  
    24 {{{ 
    25 #!python 
    26 $ tg-admin quickstart -s identity_tutorial 
    27 }}} 
    28  
    29 "-s" option is used to indicate the SQLAlchemy support. 
    30  
    31  
    32 After you specified the project name. a identity prompt will pop up: 
    33  
    34 {{{ 
    35 Do you need Identity (usernames/passwords) in this project? [no]y 
    36 }}} 
    37  
    38 This tutorial wouldn't go very far if we didn't enable identity, so go ahead and type "y"(or type "Yes").  
    39 The quickstart will generate the new project(if not exist) and append the identity-related code.  
    40  
    41 Now You can use the full power of identity management. You can set the database uri in "identity_tutorial/dev.cfg" to point to a server and database you want to use.   
    42  
    43 == B. Setting up Identity == 
    44  
    45 Identity Management can be used in controllers and in templates: 
     3TurboGears provides user- and permission-based identity (authentication and authorization) support right out of the box. 
     4 
     5Identity Management can be used in both controllers and in templates: 
    466 * In ''controllers'' to implement access restrictions 
    477 * In ''templates'' to adapt the appearance depending on the user's identity 
    488 
    49 To take advantage of identity, we need enable it. 
    50  
    51  
    52  
    53 === Step 1 - Testing the login === 
     9This tutorial will show you how to enable and use identity support in a new quickstarted project. We'll use the SQLObject object-relational mapper, and the default SQLite database, but the same principles apply when using the SQLAlchemy object-relational mapper or other database back-ends. 
     10 
     11== Getting Started == 
     12 
     13=== Create the Project === 
     14First, let's create a new project called "identity_tutorial": 
     15 
     16{{{ 
     17$ tg-admin quickstart --identity identity_tutorial 
     18}}} 
     19 
     20Accept the default package name of "identity_tutorial", and {{{TurboGears}}} will generate the project skeleton for you, including identity-specific data objects and controllers. 
     21 
     22Now initialize the database: 
     23 
     24{{{ 
     25$ tg-admin sql create 
     26}}} 
     27 
     28You now have an empty database called "devdata.sqlite", which contains the empty tables needed by identity management. 
     29 
     30=== Test the Login Page === 
     31 
    5432Now let's check whether we have all set up correctly so far. Start the project as usual: 
    5533 
    5634{{{ 
    57 #!python 
    5835$ start-identity_tutorial 
    5936}}} 
    6037 
    61 Visit the login page http://localhost:8080/login. You should see a pretty login page with username and password fields. Try to log in. It should fail with an error message since you haven't added any users/groups/permisions yet. 
    62  
    63 You can access any other page without trouble, because we haven't protected those pages yet. 
    64  
    65 === Step 2 - Adding an initial user and group === 
    66  
    67 Of course, we will need at least one group and one user account to work with.  
    68  
    69 You can adding user and group via tg-admin shell. If you choose SQLObject, you can create user and group with CatWalk.  
    70  
    71 Start {{{Turbogears}}} toolbox 
     38Visit the login page http://localhost:8080/login. You should see a pretty login page with username and password fields. Try to log in.  
     39 
     40It will fail with an error message, because you haven't added any users yet. 
     41 
     42=== Add a User and Group === 
     43 
     44If you chose SQLObject for database support, you can use either the {{{TurboGears}}} shell or CatWalk to add your first users.  CatWalk does not yet support SQLAlchemy, so if you use that ORM, then you'll need to use the {{{TurboGears}}} shell. 
     45 
     46==== Using CatWalk ==== 
     47 
     48Start the {{{TurboGears}}} toolbox: 
    7249 
    7350{{{ 
     
    7552}}} 
    7653 
    77 Enter CatWalk. You should see the TG_Group, TG_Permission, and TG_User classes on the left side. 
    78  
    79 ==== a) Create a user ==== 
    80 Select TG_User. Click the "Add TG_User+" button, then enter the user information. For example: 
    81  
    82 {{{ 
    83 displayName : Jane Doe 
    84 userId : jdoe 
    85 emailAddress : jdoe@example.com 
     54Enter CatWalk (a browser window should open automatically; if it doesn't, go to http://localhost:7654/catwalk/).  
     55 
     56You will see the Identity-related classes listed on the left side of the page. 
     57 
     58===== Create a user ===== 
     59Select User. Click the "Add User+" button, then enter the user information. For example: 
     60 
     61{{{ 
     62email_address: jdoe@example.com 
     63display_name: Jane Doe 
     64user_name : jdoe 
    8665password : xxx 
    8766}}} 
    8867 
    89 Click "Save". 
    90  
    91 ==== b) Create an admin group ==== 
    92 Select TG_Group. Click the "Add TG_Group+" button. Enter the displayName and groupId, for example: 
    93  
    94 {{{ 
    95 displayName : Administrators 
    96 groupId :admin 
    97 }}} 
    98  
    99 Click "Save". 
    100  
    101 ==== c) Add the new user to the admin group ==== 
     68Click "Save". You've created your first user. 
     69 
     70===== Create an admin group ===== 
     71 
     72Select Group. Click the "Add Group+" button. Enter the display_name and group_name, for example: 
     73 
     74{{{ 
     75display_name : Administrators 
     76group_name :admin 
     77}}} 
     78 
     79Click "Save". Now you have a group and a user; let's combine them: 
     80 
     81===== Add the new user to the admin group ===== 
    10282Note that we are now in the "Browse" tab, with the new group displayed. 
    103 Click the expansion triangle in front of "groups". This will reveal a "Manage Relations" link. Click on it. CatWalk will display two lists. Select the new user on the right list and click on "Add Selected" to move it to the left list. Then click "Save" to confirm the change. 
    104  
    105  
    106 == C. Using Identity in the Controller == 
    107  
    108 If you want to protect any method, add an {{{@identity.require(...)}}} decorator to the method. This decorator has a single argument, the ''predicate'', which specifies the conditions to check. The identity module provides many predicates that you can use. 
    109  
    110 For example to protect the index page so that only members of the admin group can access it, we can use the {{{identity.in_group("admin")}}} predicate: 
     83 
     84Click the expansion triangle in front of "users". This will reveal a "Manage Relations" link. Click on it.  
     85 
     86CatWalk will display two lists. The list on the left-hand side shows the users currently assigned to this group; the list on the right-hand side contains all users. Select the new user on the right list and click on "Add Selected" to move it to the left list. Then click "Save" to confirm the change. 
     87 
     88==== Using the Shell ==== 
     89 
     90If you'd rather use the shell to create the user and group, or if you're using SQLAlchemy, you can do this from the top-level project directory: 
     91 
     92{{{ 
     93$ tg-admin shell 
     94}}} 
     95 
     96Recall that your model is always imported into the shell environment, as if you'd typed "from model import *". 
     97 
     98Now create the initial user: 
     99 
     100{{{ 
     101#!python 
     102u = User(user_name='jdoe', email_address='jdoe@example.com', display_name='Jane Doe', password='xxx') 
     103}}} 
     104 
     105You will see messages indicating that the shell has loaded identity models, and a warning that you're using plaintext passwords.  That's fine for now, but in a production environment, you'll want to specify a password encryption scheme (see below). 
     106 
     107Similarly, create the group: 
     108{{{ 
     109#!python 
     110g = Group(group_name='admin', display_name='Administrators') 
     111}}} 
     112 
     113Now add the user to the group: 
     114{{{ 
     115#!python 
     116g.addUser(u) 
     117}}} 
     118 
     119You can see that the user is indeed part of the group: 
     120{{{ 
     121#!python 
     122>>> g.users 
     123[<User 1 user_name=u'jdoe' email_address=u'jdoe@example.com' display_name=u'Jane Doe' password=u'xxx' created='datetime.datetime...)'>] 
     124 
     125>>> u.groups 
     126[<Group 1 group_name=u'admin' display_name=u'Administrators' created='datetime.datetime...)'>] 
     127}}} 
     128 
     129Now exit the shell (using Ctrl-Z on Windows, or Ctrl-D on other systems).  You'll be asked whether you want to commit you database changes; choose "yes". 
     130 
     131= Using Identity in the Controller = 
     132 
     133If you want to protect a controller method, add an {{{@identity.require(...)}}} decorator to the method. This decorator has a single argument, the ''predicate'', which specifies the conditions to check.  
     134 
     135The identity module provides many predicates that you can use. For example to protect the index page so that only members of the admin group can access it, we can use the {{{identity.in_group("admin")}}} predicate: 
    111136 
    112137{{{ 
     
    118143}}} 
    119144 
    120 Let's try this now. Visit  http://localhost:8080/. As the index page is protected, you will be redirected to the login page. Log in using the name and password of the account which you previosly created. Now you should see the index page. 
    121  
    122 Note that identity has added a small "Welcome, Jane Doe. Logout" at the top of the page. 
    123  
    124 == D. Identity Predicates == 
     145Let's try this now. Visit  http://localhost:8080/. As the index page is protected, you will be redirected to the login page. Log in using the name and password of the account you created. Now you should see the index page, with "Welcome, Jane Doe." and a "Logout" link at the top of the page. This is created for you in the master.kid template. 
     146 
     147== Identity Predicates == 
     148 
     149Here are a few commonly-used identity predicates: 
    125150 
    126151=== Single Permission Checks === 
     
    132157}}} 
    133158 
    134  
    135159==== Checking access groups ==== 
    136160{{{ 
     
    139163}}} 
    140164 
    141 Many people wanted something more flexible, any of the following are valid require decorators: 
     165You can also specify multiple groups: 
    142166 
    143167{{{ 
     
    185209}}} 
    186210 
    187  
    188 ---- 
    189  
    190  
    191  
    192 = Part II: Fine-Tuning Identity = 
    193  
    194 == A. Using Identity in Templates == 
    195 Identity checks can also be used in kid templates to customize the appearance of the page depending on the user's identity. For example, you might show links to administrative functions only if the user is an administrator. 
    196  
    197 '''Note''':  Identity checks in the template don't provide any security, as it is always possible to enter URLs directly.  
    198 Therefore you shouldn't rely on identity checks in the template for your site's security. Always check the identity in the controller as described above. 
    199  
    200 === Step 1. Import turbogears.identity === 
    201  
    202 Make sure you import turbogears.identity in your template (anywhere before you call the turbogears.identity) 
    203  
    204 {{{ 
    205 <?python from turbogears import identity ?> 
    206 }}} 
    207  
    208 ===  Step 2. Conditional display  === 
    209  
    210 Now we can use for example "py:if" attributes to display parts of the page depending on identity information: 
    211  
    212 ==== Using access groups ==== 
    213 {{{ 
    214 <a py:if="'admin' in identity.current.groups" href="/admin">This is a link for admin</a> 
    215 }}} 
    216  
    217 ==== Using access permissions ==== 
    218 {{{ 
    219 <div py:if="'write' in identity.current.permissions">This is a write permissions area</div> 
    220 }}} 
    221  
    222 #TODO: Describe how to display user information 
    223  
    224 ===  Step 3. Displaying user information  === 
    225  
    226  
    227 == B. More Access Checking Options == 
    228  
     211= Using Identity checks in templates = 
     212 
     213Identity checks can also be used in Kid templates to customize the appearance of the page depending on the user's identity. For example, you might show links to administrative functions only if the user is an administrator.  (Naturally, you will also need to check identity in the controllers that handle those links, since just hiding them doesn't prevent a knowledgeable user from accessing those URIs directly.) 
     214 
     215Within a template, 'tg.identity' is an alias for 'turbogears.identity.current'. 
     216 
     217== Checking access groups == 
     218{{{ 
     219<a py:if="'admin' in tg.identity.groups" href="/admin">This is a link for admins</a> 
     220}}} 
     221 
     222== Checking access permissions == 
     223{{{ 
     224<div py:if="'write' in tg.identity.permissions">This is a write permissions area</div> 
     225}}} 
     226 
     227== Displaying user-specific information == 
     228{{{ 
     229  <div py:if="tg.identity.anonymous">Welcome, guest!</div> 
     230  <div py:if="not tg.identity.anonymous">Welcome, ${tg.identity.user.display_name}!</div> 
     231}}} 
     232 
     233 
     234= Additional Identity Recipes = 
    229235Sometimes, just restricting access to individual methods (pages) isn't enough. 
    230236For example, you might want to protect an entire controller, or maybe your access permissions depend on the data viewed. 
    231237 
    232 === 1. Protect your sub-directory === 
     238== Protecting a Directory == 
    233239 
    234240To restrict access to an entire controller (subdirectory), derive your Controller from identity.SecureResource and add a require attribute at the class level. 
     
    245251 
    246252 
    247 === 2. Check the permissions explicitly === 
     253== Explicit Permission Checking == 
    248254 
    249255Let's say you are creating a web site where users can add their own content, like a blogging tool or a photo sharing site. Users should be able to edit their own content, but not the content added by other users. 
     
    279285 
    280286 
    281 === 3. Write your own decorator function === 
    282  
    283 This is not for the faint at heart. But it gives you absolute flexibility.  
     287== Writing your own decorator function == 
     288 
     289This is not for the faint at heart, but it does give you absolute flexibility.  
    284290 
    285291Take a look at the decorators in turbogears/identity/conditions.py. They'll give you a head-start on what you'll have to do. 
    286292 
    287 Also, to make your life easier, remember using turbogears.decorator.  It will give you a solid basis and is used in other default decorators as well. 
    288  
    289 ---- 
    290  
    291  
    292 = Part III: Advanced Identity = 
    293  
    294 == A. Using a Custom Identity Model == 
    295  
    296 Identity model classes are now placed directly into the "model.py" of a quickstarted project. 
     293Also, to make your life easier, remember to base you decorator on turbogears.decorator.  It will give you a solid basis and is used in other default decorators as well. 
     294 
     295== Customizing the Identity Model == 
     296 
    297297You can customize your own classes for users, groups, and/or permissions -- to add a few attributes to the user class, say an image of the user and a phone number -- or even a complete replacement. 
    298298 
    299 There are some elements of the tables that you should not remove or rename.    
    300  
    301 == B. Retrieve logged users' identity infomation == 
    302  
    303 === 1. Retrieve user identity infomation === 
    304  
    305 We can access the entire User object by accessing "turbogears.identity.current.user" to get user identity infomation. This gives you access to the user_name, display_name, email_address, and creation date. 
    306  
    307 === 2. Retrieve users’ group identity infomation === 
    308  
    309 There are two ways to access the group information. 
    310  
    311 '''1'''. Via the current identity object: 
    312 {{{ 
    313 #!python 
    314 from turbogears import identity 
    315 if 'admin' in identity.current.groups: 
    316     pass 
    317 }}} 
    318  
    319 '''2'''. Via the user object on the current identity: 
    320 {{{ 
    321 #!python 
    322 from turbogears import identity 
    323 if 'admin' in [g.group_name for g in identity.current.user.groups]: 
    324     pass 
    325 }}} 
    326  
    327 ''Option number 2 only works if your using a Model that supports groups on the user object. So, with the default model you’ll be set. Other models might not work so well.'' 
    328 ---- 
    329  
    330 == C. Adding user and group via tg-admin shell == 
    331  
    332 Use "tg-admin shell" if you can't get Catwalk set up. 
    333  
    334 This section can also serve as an example how to add users and groups programmatically.   
    335  
    336  
    337 {{{ 
    338 #!python 
    339 $ tg-admin shell 
    340  
    341 >>> from turbogears.identity.soprovider import * 
    342 >>> hub.begin() 
    343 >>> u=TG_User(user_name="jeff", email_address="jeff@metrocat.org", 
    344             display_name="Jeff Watkins", password="xxxxx") 
    345 >>> g=TG_Group(group_name="admin", display_name="Administrators") 
    346 >>> hub.commit() 
    347 >>> 
    348 }}} 
    349  
    350 === Add the user to admin group === 
    351 {{{ 
    352 #!python 
    353 $ tg-admin shell 
    354  
    355 >>> from turbogears.identity.model.somodel import * 
    356 >>> hub.begin() 
    357 >>> u=TG_User.get(1) 
    358 >>> g=TG_Group.get(1) 
    359 >>> u.addTG_Group(g) 
    360 >>> hub.commit() 
    361 >>> 
    362 }}} 
    363  
    364 == D. Authenticating against an external password source == 
     299However, identity references the automatically-generated classes and their elements by name, so you should not remove or rename them. 
     300 
     301== Authenticating against an external password source == 
    365302 
    366303In some cases, you may want to authenticate against an