Package web2py :: Package gluon :: Module tools :: Class Auth
[hide private]
[frames] | no frames]

Class Auth

source code

object --+
         |
        Auth

Instance Methods [hide private]
 
url(self, f=threading.local(), args=threading.local(), vars=threading.local(), scheme=True) source code
 
here(self) source code
 
__init__(self, environment=threading.local(), db=threading.local(), mailer=True, hmac_key=threading.local(), controller='default', function='user', cas_provider=threading.local(), signature=True, secure=True)
auth=Auth(db)...
source code
 
_get_user_id(self)
accessor for auth.user_id
source code
 
table_user(self) source code
 
table_group(self) source code
 
table_membership(self) source code
 
table_permission(self) source code
 
table_event(self) source code
 
table_cas(self) source code
 
_HTTP(self, *a, **b)
only used in lambda: self._HTTP(404)
source code
 
__call__(self)
usage:
source code
 
navbar(self, prefix='Welcome', action=threading.local(), separators=(' [ ', ' | ', ' ] '), user_identifier=<function <lambda> at 0x422dde8>, referrer_actions=<function <lambda> at 0x422dde8>, mode='default') source code
 
__get_migrate(self, tablename, migrate=True) source code
 
enable_record_versioning(self, tables, archive_db=threading.local(), archive_names='%(tablename)s_archive', current_record='current_record')
to enable full record versioning (including auth tables):
source code
 
define_signature(self) source code
 
define_tables(self, username=threading.local(), signature=threading.local(), migrate=True, fake_migrate=True)
to be called unless tables are defined manually usages: # defines all needed tables and table files # 'myprefix_auth_user.table', ...
source code
 
log_event(self, description, vars=threading.local(), origin='auth')
usage:...
source code
 
get_or_create_user(self, keys, update_fields=['email'])
Used for alternate login methods: If the user exists already then password is updated.
source code
 
basic(self)
perform basic login.
source code
 
login_user(self, user)
login the user = db.auth_user(id)
source code
 
login_bare(self, username, password)
logins user as specified by usernname (or email) and password
source code
 
cas_login(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>, version=threading.local()) source code
 
cas_validate(self, version=threading.local(), proxy=True) source code
 
login(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)
returns a login form...
source code
 
logout(self, next=<function <lambda> at 0x422dde8>, onlogout=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)
logout and redirects to login...
source code
 
register(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)
returns a registration form...
source code
 
is_logged_in(self)
checks if the user is logged in and returns True/False.
source code
 
verify_email(self, next=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)
action user to verify the registration email, XXXXXXXXXXXXXXXX...
source code
 
retrieve_username(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)
returns a form to retrieve the user username...
source code
 
random_password(self) source code
 
reset_password_deprecated(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)
returns a form to reset the user password (deprecated)...
source code
 
reset_password(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)
returns a form to reset the user password...
source code
 
request_reset_password(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)
returns a form to reset the user password...
source code
 
email_reset_password(self, user) source code
 
retrieve_password(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>) source code
 
change_password(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)
returns a form that lets the user change password...
source code
 
profile(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)
returns a form that lets the user change his/her profile...
source code
 
is_impersonating(self) source code
 
impersonate(self, user_id=<function <lambda> at 0x422dde8>)
usage: POST TO http://..../impersonate request.post_vars.user_id=<id> set request.post_vars.user_id to 0 to restore original user.
source code
 
update_groups(self) source code
 
groups(self)
displays the groups and their roles for the logged in user
source code
 
not_authorized(self)
you can change the view for this page to make it look as you like
source code
 
requires(self, condition, requires_login=True, otherwise=threading.local())
decorator that prevents access to action if not logged in
source code
 
requires_login(self, otherwise=threading.local())
decorator that prevents access to action if not logged in
source code
 
requires_membership(self, role=threading.local(), group_id=threading.local(), otherwise=threading.local())
decorator that prevents access to action if not logged in or if user logged in is not a member of group_id.
source code
 
requires_permission(self, name, table_name='', record_id=0, otherwise=threading.local())
decorator that prevents access to action if not logged in or if user logged in is not a member of any group (role) that has 'name' access to 'table_name', 'record_id'.
source code
 
requires_signature(self, otherwise=threading.local())
decorator that prevents access to action if not logged in or if user logged in is not a member of group_id.
source code
 
add_group(self, role, description='')
creates a group associated to a role
source code
 
del_group(self, group_id)
deletes a group
source code
 
id_group(self, role)
returns the group_id of the group specified by the role
source code
 
user_group(self, user_id=threading.local())
returns the group_id of the group uniquely associated to this user i.e.
source code
 
user_group_role(self, user_id=threading.local()) source code
 
has_membership(self, group_id=threading.local(), user_id=threading.local(), role=threading.local())
checks if user is member of group_id or role
source code
 
add_membership(self, group_id=threading.local(), user_id=threading.local(), role=threading.local())
gives user_id membership of group_id or role if user is None than user_id is that of current logged in user
source code
 
del_membership(self, group_id=threading.local(), user_id=threading.local(), role=threading.local())
revokes membership from group_id to user_id if user_id is None than user_id is that of current logged in user
source code
 
has_permission(self, name='any', table_name='', record_id=0, user_id=threading.local(), group_id=threading.local())
checks if user_id or current logged in user is member of a group that has 'name' permission on 'table_name' and 'record_id' if group_id is passed, it checks whether the group has the permission
source code
 
add_permission(self, group_id, name='any', table_name='', record_id=0)
gives group_id 'name' access to 'table_name' and 'record_id'
source code
 
del_permission(self, group_id, name='any', table_name='', record_id=0)
revokes group_id 'name' access to 'table_name' and 'record_id'
source code
 
accessible_query(self, name, table, user_id=threading.local())
returns a query with all accessible records for user_id or...
source code
 
wiki(self, slug=threading.local(), env=threading.local(), render='markmin', manage_permissions=True, force_prefix='', restrict_search=True, resolve=True, extra=threading.local(), menugroups=threading.local()) source code

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Static Methods [hide private]
 
get_or_create_key(filename=threading.local(), alg='sha512') source code
 
archive(form, archive_table=threading.local(), current_record='current_record', archive_current=True, fields=threading.local())
If you have a table (db.mytable) that needs full revision history you can just do: form=crud.update(db.mytable,myrecord,onaccept=auth.archive) or form=SQLFORM(db.mytable,myrecord).process(onaccept=auth.archive) crud.archive will define a new table "mytable_archive" and store a copy of the current record (if archive_current=True) or a copy of the previous record (if archive_current=False) in the newly created table including a reference to the current record.
source code
Class Variables [hide private]
  default_settings = {'allow_basic_login': False, 'allow_basic_l...
  default_messages = {'access_denied': 'Insufficient privileges'...
Class for authentication, authorization, role based access control.
Properties [hide private]
  user_id
user.id or None

Inherited from object: __class__

Method Details [hide private]

__init__(self, environment=threading.local(), db=threading.local(), mailer=True, hmac_key=threading.local(), controller='default', function='user', cas_provider=threading.local(), signature=True, secure=True)
(Constructor)

source code 

auth=Auth(db)

- environment is there for legacy but unused (awful)
- db has to be the database where to create tables for authentication
- mailer=Mail(...) or None (no mailed) or True (make a mailer)
- hmac_key can be a hmac_key or hmac_key=Auth.get_or_create_key()
- controller (where is the user action?)
- cas_provider (delegate authentication to the URL, CAS2)

Overrides: object.__init__

__call__(self)
(Call operator)

source code 

usage:

def authentication(): return dict(form=auth())

enable_record_versioning(self, tables, archive_db=threading.local(), archive_names='%(tablename)s_archive', current_record='current_record')

source code 

to enable full record versioning (including auth tables):

auth = Auth(db) auth.define_tables(signature=True) # define our own tables db.define_table('mything',Field('name'),auth.signature) auth.enable_record_versioning(tables=db)

tables can be the db (all table) or a list of tables. only tables with modified_by and modified_on fiels (as created by auth.signature) will have versioning. Old record versions will be in table 'mything_archive' automatically defined.

when you enable enable_record_versioning, records are never deleted but marked with is_active=False.

enable_record_versioning enables a common_filter for every table that filters out records with is_active = False

Important: If you use auth.enable_record_versioning, do not use auth.archive or you will end up with duplicates. auth.archive does explicitly what enable_record_versioning does automatically.

define_tables(self, username=threading.local(), signature=threading.local(), migrate=True, fake_migrate=True)

source code 

to be called unless tables are defined manually

usages:

    # defines all needed tables and table files
    # 'myprefix_auth_user.table', ...
    auth.define_tables(migrate='myprefix_')

    # defines all needed tables without migration/table files
    auth.define_tables(migrate=False)

log_event(self, description, vars=threading.local(), origin='auth')

source code 

usage:

    auth.log_event(description='this happened', origin='auth')

get_or_create_user(self, keys, update_fields=['email'])

source code 

Used for alternate login methods:
    If the user exists already then password is updated.
    If the user doesn't yet exist, then they are created.

basic(self)

source code 
perform basic login. reads current.request.env.http_authorization and returns basic_allowed,basic_accepted,user

login(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)

source code 

returns a login form

method: Auth.login([next=DEFAULT [, onvalidation=DEFAULT
    [, onaccept=DEFAULT [, log=DEFAULT]]]])

logout(self, next=<function <lambda> at 0x422dde8>, onlogout=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)

source code 

logout and redirects to login

method: Auth.logout ([next=DEFAULT[, onlogout=DEFAULT[,
    log=DEFAULT]]])

register(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)

source code 

returns a registration form

method: Auth.register([next=DEFAULT [, onvalidation=DEFAULT
    [, onaccept=DEFAULT [, log=DEFAULT]]]])

is_logged_in(self)

source code 
checks if the user is logged in and returns True/False. if so user is in auth.user as well as in session.auth.user

verify_email(self, next=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)

source code 

action user to verify the registration email, XXXXXXXXXXXXXXXX

method: Auth.verify_email([next=DEFAULT [, onvalidation=DEFAULT
    [, onaccept=DEFAULT [, log=DEFAULT]]]])

retrieve_username(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)

source code 

returns a form to retrieve the user username
(only if there is a username field)

method: Auth.retrieve_username([next=DEFAULT
    [, onvalidation=DEFAULT [, onaccept=DEFAULT [, log=DEFAULT]]]])

reset_password_deprecated(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)

source code 

returns a form to reset the user password (deprecated)

method: Auth.reset_password_deprecated([next=DEFAULT
    [, onvalidation=DEFAULT [, onaccept=DEFAULT [, log=DEFAULT]]]])

reset_password(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)

source code 

returns a form to reset the user password

method: Auth.reset_password([next=DEFAULT
    [, onvalidation=DEFAULT [, onaccept=DEFAULT [, log=DEFAULT]]]])

request_reset_password(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)

source code 

returns a form to reset the user password

method: Auth.reset_password([next=DEFAULT
    [, onvalidation=DEFAULT [, onaccept=DEFAULT [, log=DEFAULT]]]])

change_password(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)

source code 

returns a form that lets the user change password

method: Auth.change_password([next=DEFAULT[, onvalidation=DEFAULT[,
    onaccept=DEFAULT[, log=DEFAULT]]]])

profile(self, next=<function <lambda> at 0x422dde8>, onvalidation=<function <lambda> at 0x422dde8>, onaccept=<function <lambda> at 0x422dde8>, log=<function <lambda> at 0x422dde8>)

source code 

returns a form that lets the user change his/her profile

method: Auth.profile([next=DEFAULT [, onvalidation=DEFAULT
    [, onaccept=DEFAULT [, log=DEFAULT]]]])

impersonate(self, user_id=<function <lambda> at 0x422dde8>)

source code 

usage: POST TO http://..../impersonate request.post_vars.user_id=<id> set request.post_vars.user_id to 0 to restore original user.

requires impersonator is logged in and has_permission('impersonate', 'auth_user', user_id)

requires_membership(self, role=threading.local(), group_id=threading.local(), otherwise=threading.local())

source code 
decorator that prevents access to action if not logged in or if user logged in is not a member of group_id. If role is provided instead of group_id then the group_id is calculated.

requires_signature(self, otherwise=threading.local())

source code 
decorator that prevents access to action if not logged in or if user logged in is not a member of group_id. If role is provided instead of group_id then the group_id is calculated.

user_group(self, user_id=threading.local())

source code 
returns the group_id of the group uniquely associated to this user i.e. role=user:[user_id]

accessible_query(self, name, table, user_id=threading.local())

source code 

returns a query with all accessible records for user_id or
the current logged in user
this method does not work on GAE because uses JOIN and IN

example:

   db(auth.accessible_query('read', db.mytable)).select(db.mytable.ALL)

archive(form, archive_table=threading.local(), current_record='current_record', archive_current=True, fields=threading.local())
Static Method

source code 

If you have a table (db.mytable) that needs full revision history you can just do:

    form=crud.update(db.mytable,myrecord,onaccept=auth.archive)

or

    form=SQLFORM(db.mytable,myrecord).process(onaccept=auth.archive)

crud.archive will define a new table "mytable_archive" and store
a copy of the current record (if archive_current=True)
or a copy of the previous record (if archive_current=False)
in the newly created table including a reference
to the current record.

fields allows to specify extra fields that need to be archived.

If you want to access such table you need to define it yourself
in a model:

    db.define_table('mytable_archive',
        Field('current_record',db.mytable),
        db.mytable)

Notice such table includes all fields of db.mytable plus one: current_record.
crud.archive does not timestamp the stored record unless your original table
has a fields like:

    db.define_table(...,
        Field('saved_on','datetime',
             default=request.now,update=request.now,writable=False),
        Field('saved_by',auth.user,
             default=auth.user_id,update=auth.user_id,writable=False),

there is nothing special about these fields since they are filled before
the record is archived.

If you want to change the archive table name and the name of the reference field
you can do, for example:

    db.define_table('myhistory',
        Field('parent_record',db.mytable),
        db.mytable)

and use it as:

    form=crud.update(db.mytable,myrecord,
                     onaccept=lambda form:crud.archive(form,
                     archive_table=db.myhistory,
                     current_record='parent_record'))


Class Variable Details [hide private]

default_settings

Value:
{'allow_basic_login': False,
 'allow_basic_login_only': False,
 'alternate_requires_registration': False,
 'captcha': None,
 'cas_maps': None,
 'create_user_groups': 'user_%(id)s',
 'email_case_sensitive': True,
 'everybody_group_id': None,
...

default_messages


Class for authentication, authorization, role based access control.

Includes:

- registration and profile
- login and logout
- username and password retrieval
- event logging
- role creation and assignment
- user defined group/role based permission

Authentication Example:

    from contrib.utils import *
    mail=Mail()
    mail.settings.server='smtp.gmail.com:587'
    mail.settings.sender='you@somewhere.com'
    mail.settings.login='username:password'
    auth=Auth(db)
    auth.settings.mailer=mail
    # auth.settings....=...
    auth.define_tables()
    def authentication():
        return dict(form=auth())

exposes:

- http://.../{application}/{controller}/authentication/login
- http://.../{application}/{controller}/authentication/logout
- http://.../{application}/{controller}/authentication/register
- http://.../{application}/{controller}/authentication/verify_email
- http://.../{application}/{controller}/authentication/retrieve_username
- http://.../{application}/{controller}/authentication/retrieve_password
- http://.../{application}/{controller}/authentication/reset_password
- http://.../{application}/{controller}/authentication/profile
- http://.../{application}/{controller}/authentication/change_password

On registration a group with role=new_user.id is created
and user is given membership of this group.

You can create a group with:

    group_id=auth.add_group('Manager', 'can access the manage action')
    auth.add_permission(group_id, 'access to manage')

Here "access to manage" is just a user defined string.
You can give access to a user:

    auth.add_membership(group_id, user_id)

If user id is omitted, the logged in user is assumed

Then you can decorate any action:

    @auth.requires_permission('access to manage')
    def manage():
        return dict()

You can restrict a permission to a specific table:

    auth.add_permission(group_id, 'edit', db.sometable)
    @auth.requires_permission('edit', db.sometable)

Or to a specific record:

    auth.add_permission(group_id, 'edit', db.sometable, 45)
    @auth.requires_permission('edit', db.sometable, 45)

If authorization is not granted calls:

    auth.settings.on_failed_authorization

Other options:

    auth.settings.mailer=None
    auth.settings.expiration=3600 # seconds

    ...

    ### these are messages that can be customized
    ...

Value:
{'access_denied': 'Insufficient privileges',
 'add_group_log': 'Group %(group_id)s created',
 'add_membership_log': None,
 'add_permission_log': None,
 'change_password_log': 'User %(id)s Password changed',
 'del_group_log': 'Group %(group_id)s deleted',
 'del_membership_log': None,
 'del_permission_log': None,
...

Property Details [hide private]

user_id

user.id or None
Get Method:
web2py.gluon.tools.Auth._get_user_id(self) - accessor for auth.user_id
Set Method:
threading.local()
Delete Method:
threading.local()