web2pyTM Tools
Since version 1.56 web2py includes tools for authentication, authorization, CRUD, web services, and more. They are implemented so that they do not require JOINs and work on Google App Engine as well.
Authentication
The basic authentication tool is the Auth class. It provides methods that can be used as controller actions to register users (with optional Recaptcha support), log them in and out, allow email verification, password change, password reset and retrieval, editing user profile.
These functionalities can then be used as the basis for authorization.
The Auth calls can be extended, personalized, and replaced by other authentication mechanisms which expose a similar interface.
To use authentication, write something like this in a model file:
1. | from gluon.tools import Mail, Auth, Recaptcha |
In your controller (for example in default.py) expose the auth object (for example via a user action):
1. | def user(): |
The above action will expose the following URLs
- http://locahost:8000/application/default/user/register
- http://locahost:8000/application/default/user/login
- http://locahost:8000/application/default/user/logout
- http://locahost:8000/application/default/user/verify_email
- http://locahost:8000/application/default/user/profile
- http://locahost:8000/application/default/user/change_password
- http://locahost:8000/application/default/user/retrieve_password
- http://locahost:8000/application/default/user/groups
The groups page shows a list of roles and description for the groups the logged-in user is a member of (see authorization).
You can check if a user is logged in via auth.is_logged_in(). If a user is logged in its record information can be found in auth.user. By default a user is stored in a table called "auth_user" and has the following columns: first_name, last_name, email, password. Password is stored encrypted (md5 hashed or stronger). You can change the table name, define your own table with more fields, require additional validators.
All authentication events are logged in a table called "auth_event".
Custom Authentication
You can customize the auth object by changing its settings anf messages:
1. | auth.messages.access_denied = 'Insufficient privileges' |
Strings can be translated in the usual way even if there is not T operator
Views are handled the usual web2py way.
It also possible to use custom tables. For example a custom user table:
1. | # instantiate auth |
One can add any other field that is needed as long as the fields in the example are there.
Authorization
Once you have a user identified by user.id, you can create a group (for example "Manager")
group_id = auth.add_group(role = "Manager", description = "example of a group") |
make the user a member:
auth.add_membership(group_id,user_id) |
and assign permissions to all members of the group:
auth.add_permission(group_id,'create','tablename',record_id) |
Now you can enforce permissions using the following decorators:
1. | auth.settings.on_failed_authorization=URL(r=request,f='error') |
Group roles are conventional. Permission names are also conventional. If one group has a certain permission on record_id==0 (default), it means the user has the permission on any record.
Some permission names ("tables", "select", "create", "update", "delete", "read") have a special meaning because they can be automatically enforced by the CRUD tool described below.
Create/Read/Update/Delete and more
To use CRUD, in your model insert the following code:
1. | from gluon.tools import Crud |
and in a controller (for example in default.py) expose it via an action (for example data):
1. | def data(): |
This will expose the following URLs:
- http://locahost:8000/application/default/data/tables
- http://locahost:8000/application/default/data/select/tablename
- http://locahost:8000/application/default/data/create/tablename
- http://locahost:8000/application/default/data/read/tablename/record_id
- http://locahost:8000/application/default/data/update/tablename/record_id
- http://locahost:8000/application/default/data/delete/tablename/record_id
- http://locahost:8000/application/default/download/filename
"tables" list of current database tables.
"download" only allows to download uploaded files (whether they are in the uploads folder or in the database).
To enforce authorization on these CRUD URLs simply set
1. | crud.settings.auth=auth |
and the logged in user will only be able to "create" a record in table "tablename" if the user is a member of a group that has "create" permission on table "tablename". The same mechanism works for tables, select, read, update, and delete URLs.
Services
Web2py provides an interface to expose any function as a service (CSV, XML, JSON, XMLRPC, JSONRPC, AMF)
This is achieved in three steps:- Create an instance of the Service object in a model or controller
1.
2.from gluon.tools import Service
service = Service(globals()) - Expose the the object via an action called, for example, 'call'
1.
def call(): return service()
- Decorate all the functions that you want to expose, using one ore more of the following decorators
1.
2.
3.
4.
5.
6.
7.
8.@service.run
@service.csv
@service.xml
@service.json
@service.xmlrpc
@service.jsonrpc
@service.pyamf
def myfunction(a,b): return a+b
The function can now be called remotely using the syntax
1. | http://..../app/default/call/[method]/[function]/[arguments] |
1. | http://..../app/default/call/[method]/[function]?[arguments] |
1. | http://..../app/default/call/run/myfunction/2/3 |
1. | http://..../app/default/call/run/myfunction?a=2&b=3 |
Caveats: csv only works if the function returns a list of list. amfrpc only works if PyAMF is installed. In the case of xmlrpc, jsonrpc and amfrpc, the arguments (/myfunction/2/3) cannot be passed in the URI, they must be passed according to the respective protocol. For example for xmlrpc from another python program:
1. | >>> from xmlrpclib import ServerProxy |
Fetch a URL
The Python module urllib does not work well on the Google App Engine. For this reason we created a portable function for fetching url that works everywhere, including GAE:
1. | from gluon.tools import fetch |
Geocoding
Another very common need of modern web applications is that of converting an address into latitude and longitude. We also provide a portable function to do it that uses the Google Geocoding API:
1. | from gluon.tools import geocode |
It returns 0,0 on failure.