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

Version 49 (modified by fredlin, 13 years ago) (diff)

Visit/Identity? changes

Identity Management

Version: 0.92a4

TurboGears identity management architecture was originally from  Jeff Watkins, Here is a Tutorial for getting TurboGears identity management support up and running.

Identity Management can be used in either controller or templates.

For better understanding, The document has been split to 3 part, and covers following topics

PART 1

Add identity user and group
Use Identity in Controller
Identity Management API

PART 2

Use Identity in Template
Restrict Group Access

PART 3

Customize ORM classes
Retrieve logged users' identity infomation

This Tutorial is written from the perspective of a fresh quick-started project, but most everything applies for existing projects.

PART 1

Add identity user and group

There are two ways to add identity user and group.

  • Add user and group by Catwalk
  • Add user and group by tg-admin shell

Using Catwalk is probably the easiest way to create user/group/permissions.

We'll show you this way to add User/Group?, and append "Add user and group by tg-admin shell" on the button of PART 1.

Step 1 - Create new project

$ tg-admin quickstart 

Name your project as your "project_name" and set the database uri in "project_name/dev.cfg" to point to a server and database you want to use. refer  here

Step 2 - Edit project_name/config/app.cfg

Edit app.cfg. uncomment and edit the following to turn on identity management. Edit the failure url as well.

# visit.on=False
visit.on=True

# identity.on=False
identity.on = True

# identity.failure_url=None
identity.failure_url = "/login"

Step 3 - Testing the login

Start the project:

$ start-project_name

The database will be created by this commands, visit login page  http://localhost:8080/login and login with any username and password. It should fail with the message since you haven't add user/group/permision.

You can access any other pages without trouble, because we haven't "protect" those pages by identity decorator.

Step 4 - Create user and group

We just learn howto protect our page, but for now we can't access those protected pages any more.

Since we haven't specify any user or groups for permissions, we need to add some user/group/admission to login to the protected pages.

1. Import identity models

Modify the project_name/model.py

# Uncomment the following line if you wish to use Identity and SO_Provider
from turbogears.identity.soprovider import TG_User, TG_Group, TG_Permission

to import the TG_User, TG_Group, TG_Permission model classes.

2. Use Catwalk to create user and group

Start Turbogears toolbox

$tg-admin toolbox

Enter catwalk, Now you can see TG_Group, TG_Permission, TG_User classes in left side. use following steps to add proper group and user:

1. Add Group

Select TG_Group.

Click "Add TG_Group+" button.

Then add the display_name and group_name

ex: 
group_name :admin
display_name : Administrators

Press "Save" button

2. Add a new User

Select TG_User.

Click "Add TG_User+" button.

Then add user infomations

ex: 
user_name : root
email_address : ooo@xxx.oo
display_name : Fred Lin
password : ooxx

Press "Save" button

3. Add the user to admin group

Now we are in the "Browse" tag, click the arrow sign in front of "groups".

It will show a drop down list. In example, click "Manage Relations" to select the "administrators" group from right field to the "root" user.

Click "Add Selected" to move selected group from right to left. Then click "Save" to confirm the process.


Use Identity in Controller

Step 1 - protect your pages

You can protect your pages by using identity decorator(decorator usage is as the expose decorator "@turbogears.expose()" you've learned)

1. Edit controllers.py

Add this code on the top of the file:

from turbogears import identity

2. Protect Pages

If you want to protect any method(page is just a python method), add an identity decorator over the method.

The following example use "@identity.require()" to protect the index page:

    @turbogears.expose(template=".templates.welcome")
    @identity.require( identity.in_group( "admin" ))
    def index(self):
        ....

The decorator checked whether the visitor was a member of the admin group.

Let's visit the  http://localhost:8080/, now the index page is protected.

There are many @identity.require decorator parameters for you to fit your identity requirements.

See the API section below.

Step 2 - Revisit protected page and login

Browse to  http://localhost:8080/ again and login, this time you should see the content of index page


API

Single Permission Control

You need to use the permission control functions in the identity namespace. For example:

Restrict access groups

@identity.require( identity.in_group( "admin" ) )

Many people wanted something more flexible, any of the following are valid require decorators:

@identity.require( identity.in_all_groups( "admin", "editor" ) )

@identity.require( identity.in_any_group( "admin", "editor" ) )

@identity.require( identity.not_anonymous() )


Restrict access permissions

@identity.require( identity.has_permission( "edit" ) )

@identity.require( identity.has_all_permissions( "edit", "delete", "update" ) )

@identity.require( identity.has_any_permission( "edit", "delete", "update" ) )

Restrict access host

@identity.require( identity.from_host( "127.0.0.1" ))

@identity.require( identity.from_any_host( , , ))

Combination Permission Control

You can combine several permissions by "Any" or "All":

     @identity.require( Any( identity.in_group( "admin" ), identity.has_permission( "edit" ) ) )

The require decorator checked whether the visitor was a member of the "admin" group or had the "edit" permission.

     @identity.require( All( identity.from_host( "127.0.0.1" ), identity.has_permission( "edit" ) ) )

     @identity.require( All( identity.from_any_host( "127.0.0.1", "10.0.0.1"), identity.in_group("editor" ) ) )

Add user and group by tg-admin shell

Use "tg-admin shell" if you can't get Catwalk set up.

$ tg-admin shell

>>> from turbogears.identity.soprovider import *
>>> hub.begin()
>>> u=TG_User( user_name="jeff", email_address="jeff@metrocat.org",
            display_name="Jeff Watkins", password="xxxxx" )
>>> g=TG_Group( group_name="admin", display_name="Administrators" )
>>> hub.commit()
>>>

Add the user to admin group

$ tg-admin shell

>>> from turbogears.identity.model.somodel import *
>>> hub.begin()
>>> u=TG_User.get(1)
>>> g=TG_Group.get(1)
>>> u.addTG_Group(g)
>>> hub.commit()
>>>

PART 2

Use Identity in templates

Identity checks can also be used in kid templates to control the present of stricted areas or links(within any html element).

Step 1. Import turbogears.identity

Make sure you import turbogears.identity in your template (anywhere before you call the turbogears.identity)

<?python from turbogears import identity ?>

Step 2. Control the stricted areas

We Control the stricted areas by using "py:if" statements:

Restrict access groups

<a py:if="'admin' in identity.current.groups" href="/test">This is a link for admin</a>

Restrict access permissions

<div py:if="'write' in identity.current.permissions">This is a write permissions area</div>

Restrict the group Access

There are three ways to Strict the group Access:

1. Protect your sub-directory

To turn on identity login for an entire controller(restrict access to whole subdirectory), you should be able to derive your Controller from identity.SecureResource? and define a require attribute at the class level.

class MySecureController( turbogears.Controller,  identity.SecureResource ):
        require= identity.in_group( "admin" )

        # etc... 

You can apply whatever decorators you want on the methods of the MySecureController? instance. So each method could have additional restrictions. And MySecureController? could have SecureObjects? as well. However, access to exposed methods of MySecureController? and any SecureObjects? would have to satisfy the authorisation requirements for MySecureController?.

2. Check the permissions explicitly

Derive your Controller from identity.SecureResource? and define a require attribute at the method level

class MyController( controllers.Controller, identity.SecureResource ):

     @turbogears.expose( html="mytemplate" )
     def myFunction( self ):
         if not ("admin" in identity.current.groups or \
                 "super" in identity.current.groups):
             raise identity.GroupMembershipRequiredException( ("admin", "super") )

This will work because SecureResource? wraps all exposed methods with code that checks permissions and traps IdentityExceptions?. So if your code throws, er, raises an IdentityException?, everything will be handled correctly.

Of course, you can then pull your authorisation logic out into a function that you call rather than copying and pasting into each function that requires it.

You can also use these similar predicates in your own code:

     if identity.in_group( "admin" ) and identity.has_permission( "edit" ):
         pass
     else:
         pass

3. Write your own decorator function

This is not for the faint at heart. But it gives you absolute flexibility.

Take a look at the decorators in turbogears/identity/conditions.py. They'll give you a head-start on what you'll have to do.


PART 3

Modify Identity classes or updating Identity-related tables

You can use your own class to access database on Identity Management.

1. Create SQL tables

Run the application as Step 3. All TG_* tables will be created

2. Edit project_name/config/app.cfg

Edit app.cfg, remove the comments from "identity.soprovider" lines.

# The classes you wish to use for your Identity model. Leave these commented out
# to use the default classes for SqlObjectIdentityProvider. Or set them to the
# classes in your model. NOTE: These aren't TG_* because the TG prefix is
# reserved for classes created by TurboGears.
identity.soprovider.model.user="project_name.model.User"
identity.soprovider.model.group="project_name.model.Group"
identity.soprovider.model.permission="project_name.model.Permission"

Change model."User", "Group", "Permission" to whatever you prefer.

3. Run the application

Run the application

$ start-project_name

Then you can use your classes to manipulate TurboGear? Identity Management.


Retrieve logged users' identity infomation

Retrieve user identity infomation

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.

Retrieve users’ group identity infomation

There are two ways to access the group information.

1. Via the current identity object:

from turbogears import identity
if 'admin' in identity.current.groups:
    pass

2. Via the user object on the current identity:

from turbogears import identity
if 'admin' in [g.group_name for g in identity.current.user.groups]:
    pass

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.


Notes

Setting identity by config has not implement yet.

Using tg-admin shell to add identity user/group is not work under 0.9a2. patch is  here


#TODO using SQLAlchemy instead of SQLObject

#TODO LdapIdentityProvider?

Attachments