tools
Module¶
Auth, Mail, PluginManager and various utilities¶
-
class
gluon.tools.
Mail
(server=None, sender=None, login=None, tls=True)[source]¶ Bases:
object
Class for configuring and sending emails with alternative text / html body, multiple attachments and encryption support
Works with SMTP and Google App Engine.
Parameters: - server – SMTP server address in address:port notation
- sender – sender email address
- login – sender login name and password in login:password notation or None if no authentication is required
- tls – enables/disables encryption (True by default)
In Google App Engine use
server='gae'
For sake of backward compatibility all fields are optional and default to None, however, to be able to send emails at least server and sender must be specified. They are available under following fields:
mail.settings.server mail.settings.sender mail.settings.login mail.settings.timeout = 60 # seconds (default)
When server is ‘logging’, email is logged but not sent (debug mode)
Optionally you can use PGP encryption or X509:
mail.settings.cipher_type = None mail.settings.gpg_home = None mail.settings.sign = True mail.settings.sign_passphrase = None mail.settings.encrypt = True mail.settings.x509_sign_keyfile = None mail.settings.x509_sign_certfile = None mail.settings.x509_sign_chainfile = None mail.settings.x509_nocerts = False mail.settings.x509_crypt_certfiles = None cipher_type : None gpg - need a python-pyme package and gpgme lib x509 - smime gpg_home : you can set a GNUPGHOME environment variable to specify home of gnupg sign : sign the message (True or False) sign_passphrase : passphrase for key signing encrypt : encrypt the message (True or False). It defaults to True ... x509 only ... x509_sign_keyfile : the signers private key filename or string containing the key. (PEM format) x509_sign_certfile: the signers certificate filename or string containing the cert. (PEM format) x509_sign_chainfile: sets the optional all-in-one file where you can assemble the certificates of Certification Authorities (CA) which form the certificate chain of email certificate. It can be a string containing the certs to. (PEM format) x509_nocerts : if True then no attached certificate in mail x509_crypt_certfiles: the certificates file or strings to encrypt the messages with can be a file name / string or a list of file names / strings (PEM format)
Examples
Create Mail object with authentication data for remote server:
mail = Mail('example.com:25', 'me@example.com', 'me:password')
- Notice for GAE users:
- attachments have an automatic content_id=’attachment-i’ where i is progressive number in this way the can be referenced from the HTML as <img src=”cid:attachment-0” /> etc.
-
class
Attachment
(payload, filename=None, content_id=None, content_type=None, encoding='utf-8')[source]¶ Bases:
email.mime.base.MIMEBase
Email attachment
Parameters: - payload – path to file or file-like object with read() method
- filename – name of the attachment stored in message; if set to None, it will be fetched from payload path; file-like object payload must have explicit filename specified
- content_id – id of the attachment; automatically contained within < and >
- content_type – content type of the attachment; if set to None, it will be fetched from filename using gluon.contenttype module
- encoding – encoding of all strings passed to this function (except attachment body)
Content ID is used to identify attachments within the html body; in example, attached image with content ID ‘photo’ may be used in html message as a source of img tag <img src=”cid:photo” />.
- Example::
Create attachment from text file:
attachment = Mail.Attachment('/path/to/file.txt') Content-Type: text/plain MIME-Version: 1.0 Content-Disposition: attachment; filename="file.txt" Content-Transfer-Encoding: base64 SOMEBASE64CONTENT=
Create attachment from image file with custom filename and cid:
attachment = Mail.Attachment('/path/to/file.png', filename='photo.png', content_id='photo') Content-Type: image/png MIME-Version: 1.0 Content-Disposition: attachment; filename="photo.png" Content-Id: <photo> Content-Transfer-Encoding: base64 SOMEOTHERBASE64CONTENT=
-
send
(to, subject='[no subject]', message='[no message]', attachments=None, cc=None, bcc=None, reply_to=None, sender=None, encoding='utf-8', raw=False, headers={}, from_address=None, cipher_type=None, sign=None, sign_passphrase=None, encrypt=None, x509_sign_keyfile=None, x509_sign_chainfile=None, x509_sign_certfile=None, x509_crypt_certfiles=None, x509_nocerts=None)[source]¶ Sends an email using data specified in constructor
Parameters: - to – list or tuple of receiver addresses; will also accept single object
- subject – subject of the email
- message –
email body text; depends on type of passed object:
- if 2-list or 2-tuple is passed: first element will be source of plain text while second of html text;
- otherwise: object will be the only source of plain text and html source will be set to None
If text or html source is:
- None: content part will be ignored,
- string: content part will be set to it,
- file-like object: content part will be fetched from it using it’s read() method
- attachments – list or tuple of Mail.Attachment objects; will also accept single object
- cc – list or tuple of carbon copy receiver addresses; will also accept single object
- bcc – list or tuple of blind carbon copy receiver addresses; will also accept single object
- reply_to – address to which reply should be composed
- encoding – encoding of all strings passed to this method (including message bodies)
- headers – dictionary of headers to refine the headers just before sending mail, e.g. {‘X-Mailer’ : ‘web2py mailer’}
- from_address – address to appear in the ‘From:’ header, this is not the envelope sender. If not specified the sender will be used
- cipher_type – gpg - need a python-pyme package and gpgme lib x509 - smime
- gpg_home – you can set a GNUPGHOME environment variable to specify home of gnupg
- sign – sign the message (True or False)
- sign_passphrase – passphrase for key signing
- encrypt – encrypt the message (True or False). It defaults to True. … x509 only …
- x509_sign_keyfile – the signers private key filename or string containing the key. (PEM format)
- x509_sign_certfile – the signers certificate filename or string containing the cert. (PEM format)
- x509_sign_chainfile – sets the optional all-in-one file where you can assemble the certificates of Certification Authorities (CA) which form the certificate chain of email certificate. It can be a string containing the certs to. (PEM format)
- x509_nocerts – if True then no attached certificate in mail
- x509_crypt_certfiles – the certificates file or strings to encrypt the messages with can be a file name / string or a list of file names / strings (PEM format)
Examples
Send plain text message to single address:
mail.send('you@example.com', 'Message subject', 'Plain text body of the message')
Send html message to single address:
mail.send('you@example.com', 'Message subject', '<html>Plain text body of the message</html>')
Send text and html message to three addresses (two in cc):
mail.send('you@example.com', 'Message subject', ('Plain text body', '<html>html body</html>'), cc=['other1@example.com', 'other2@example.com'])
Send html only message with image attachment available from the message by ‘photo’ content id:
mail.send('you@example.com', 'Message subject', (None, '<html><img src="cid:photo" /></html>'), Mail.Attachment('/path/to/photo.jpg' content_id='photo'))
Send email with two attachments and no body text:
mail.send('you@example.com, 'Message subject', None, [Mail.Attachment('/path/to/fist.file'), Mail.Attachment('/path/to/second.file')])
Returns: True on success, False on failure. Before return, method updates two object’s fields:
- self.result: return value of smtplib.SMTP.sendmail() or GAE’s mail.send_mail() method
- self.error: Exception message or None if above was successful
-
class
gluon.tools.
Auth
(environment=None, db=None, mailer=True, hmac_key=None, controller='default', function='user', cas_provider=None, signature=True, secure=False, csrf_prevention=True, propagate_extension=None, url_index=None, jwt=None, host_names=None)[source]¶ Bases:
object
-
accessible_query
(name, table, user_id=None)[source]¶ 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
Use as:
db(auth.accessible_query('read', db.mytable)).select(db.mytable.ALL)
-
add_membership
(group_id=None, user_id=None, role=None)[source]¶ Gives user_id membership of group_id or role if user is None than user_id is that of current logged in user
-
add_permission
(group_id, name='any', table_name='', record_id=0)[source]¶ Gives group_id ‘name’ access to ‘table_name’ and ‘record_id’
-
static
archive
(form, archive_table=None, current_record='current_record', archive_current=False, fields=None)[source]¶ 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'))
-
basic
(basic_auth_realm=False)[source]¶ Performs basic login.
Parameters: basic_auth_realm – optional basic http authentication realm. Can take str or unicode or function or callable or boolean. reads current.request.env.http_authorization and returns basic_allowed,basic_accepted,user.
if basic_auth_realm is defined is a callable it’s return value is used to set the basic authentication realm, if it’s a string its content is used instead. Otherwise basic authentication realm is set to the application name. If basic_auth_realm is None or False (the default) the behavior is to skip sending any challenge.
-
bulk_register
(max_emails=100)[source]¶ Creates a form for ther user to send invites to other users to join
-
cas_login
(next=<function <lambda>>, onvalidation=<function <lambda>>, onaccept=<function <lambda>>, log=<function <lambda>>, version=2)[source]¶
-
change_password
(next=<function <lambda>>, onvalidation=<function <lambda>>, onaccept=<function <lambda>>, log=<function <lambda>>)[source]¶ Returns a form that lets the user change password
-
confirm_registration
(next=<function <lambda>>, onvalidation=<function <lambda>>, onaccept=<function <lambda>>, log=<function <lambda>>)[source]¶ Returns a form to confirm user registration
-
default_messages
= {'access_denied': 'Insufficient privileges', 'add_group_log': 'Group %(group_id)s created', 'add_membership_log': None, 'add_permission_log': None, 'bulk_invite_body': 'You have been invited to join %(site)s, click %(link)s to complete the process', 'bulk_invite_subject': 'Invitation to join %(site)s', 'change_password_log': 'User %(id)s Password changed', 'del_group_log': 'Group %(group_id)s deleted', 'del_membership_log': None, 'del_permission_log': None, 'delete_label': 'Check to delete', 'email_sent': 'Email sent', 'email_taken': 'This email already has an account', 'email_verified': 'Email verified', 'function_disabled': 'Function disabled', 'group_description': 'Group uniquely assigned to user %(id)s', 'has_membership_log': None, 'has_permission_log': None, 'impersonate_log': 'User %(id)s is impersonating %(other_id)s', 'invalid_email': 'Invalid email', 'invalid_login': 'Invalid login', 'invalid_password': 'Invalid password', 'invalid_reset_password': 'Invalid reset password', 'invalid_two_factor_code': 'Incorrect code. {0} more attempt(s) remaining.', 'invalid_user': 'Invalid user', 'invalid_username': 'Invalid username', 'is_empty': 'Cannot be empty', 'label_client_ip': 'Client IP', 'label_description': 'Description', 'label_email': 'E-mail', 'label_first_name': 'First name', 'label_group_id': 'Group ID', 'label_last_name': 'Last name', 'label_name': 'Name', 'label_origin': 'Origin', 'label_password': 'Password', 'label_record_id': 'Record ID', 'label_registration_id': 'Registration identifier', 'label_registration_key': 'Registration key', 'label_remember_me': 'Remember me (for 30 days)', 'label_reset_password_key': 'Reset Password key', 'label_role': 'Role', 'label_table_name': 'Object or table name', 'label_time_stamp': 'Timestamp', 'label_two_factor': 'Authentication code', 'label_user_id': 'User ID', 'label_username': 'Username', 'logged_in': 'Logged in', 'logged_out': 'Logged out', 'login_button': 'Log In', 'login_disabled': 'Login disabled by administrator', 'login_failed_log': None, 'login_log': 'User %(id)s Logged-in', 'logout_log': 'User %(id)s Logged-out', 'mismatched_password': "Password fields don't match", 'new_password': 'New password', 'new_password_sent': 'A new password was emailed to you', 'old_password': 'Old password', 'password_change_button': 'Change password', 'password_changed': 'Password changed', 'password_reset_button': 'Request reset password', 'profile_log': 'User %(id)s Profile updated', 'profile_save_button': 'Apply changes', 'profile_updated': 'Profile updated', 'register_button': 'Sign Up', 'register_log': 'User %(id)s Registered', 'registration_pending': 'Registration is pending approval', 'registration_successful': 'Registration successful', 'registration_verifying': 'Registration needs verification', 'reset_password': 'Click on the link %(link)s to reset your password', 'reset_password_log': 'User %(id)s Password reset', 'reset_password_subject': 'Password reset', 'retrieve_password': 'Your password is: %(password)s', 'retrieve_password_log': 'User %(id)s Password retrieved', 'retrieve_password_subject': 'Password retrieve', 'retrieve_two_factor_code': 'Your temporary login code is {0}', 'retrieve_two_factor_code_subject': 'Two-step Login Authentication Code', 'retrieve_username': 'Your username is: %(username)s', 'retrieve_username_log': 'User %(id)s Username retrieved', 'retrieve_username_subject': 'Username retrieve', 'submit_button': 'Submit', 'two_factor_comment': 'This code was emailed to you and is required for login.', 'unable_send_email': 'Unable to send email', 'unable_to_send_email': 'Unable to send email', 'username_sent': 'Your username was emailed to you', 'username_taken': 'Username already taken', 'verify_email': 'Welcome %(username)s! Click on the link %(link)s to verify your email', 'verify_email_log': 'User %(id)s Verification email sent', 'verify_email_subject': 'Email verification', 'verify_password': 'Verify Password', 'verify_password_comment': 'please input your password again'}¶ 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
Parameters: - 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 mailer) 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)
Authentication Example:
from gluon.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 ...
-
default_settings
= {'allow_basic_login': False, 'allow_basic_login_only': False, 'allow_delete_accounts': False, 'alternate_requires_registration': False, 'auth_manager_role': None, 'auth_two_factor_enabled': False, 'auth_two_factor_tries_left': 3, 'bulk_register_enabled': False, 'captcha': None, 'cas_maps': None, 'client_side': True, 'create_user_groups': 'user_%(id)s', 'email_case_sensitive': True, 'everybody_group_id': None, 'expiration': 3600, 'formstyle': None, 'hideerror': False, 'keep_session_onlogin': True, 'keep_session_onlogout': False, 'label_separator': None, 'logging_enabled': True, 'login_after_password_change': True, 'login_after_registration': False, 'login_captcha': None, 'login_email_validate': True, 'login_userfield': None, 'logout_onlogout': None, 'long_expiration': 2592000, 'manager_actions': {}, 'multi_login': False, 'on_failed_authentication': <function <lambda> at 0x7ff7038f5578>, 'ondelete': 'CASCADE', 'password_field': 'password', 'password_min_length': 4, 'pre_registration_div': None, 'prevent_open_redirect_attacks': True, 'prevent_password_reset_attacks': True, 'profile_fields': None, 'register_captcha': None, 'register_fields': None, 'register_verify_password': True, 'registration_requires_approval': False, 'registration_requires_verification': False, 'remember_me_form': True, 'renew_session_onlogin': True, 'renew_session_onlogout': True, 'reset_password_requires_verification': False, 'retrieve_password_captcha': None, 'retrieve_username_captcha': None, 'showid': False, 'table_cas': None, 'table_cas_name': 'auth_cas', 'table_event': None, 'table_event_name': 'auth_event', 'table_group': None, 'table_group_name': 'auth_group', 'table_membership': None, 'table_membership_name': 'auth_membership', 'table_permission': None, 'table_permission_name': 'auth_permission', 'table_token_name': 'auth_token', 'table_user': None, 'table_user_name': 'auth_user', 'two_factor_authentication_group': None, 'update_fields': ['email'], 'use_username': False, 'username_case_sensitive': True, 'wiki': <Storage {}>}¶
-
define_tables
(username=None, signature=None, enable_tokens=False, migrate=None, fake_migrate=None)[source]¶ To be called unless tables are defined manually
Examples
Use as:
# 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)
-
del_membership
(group_id=None, user_id=None, role=None)[source]¶ Revokes membership from group_id to user_id if user_id is None than user_id is that of current logged in user
-
del_permission
(group_id, name='any', table_name='', record_id=0)[source]¶ Revokes group_id ‘name’ access to ‘table_name’ and ‘record_id’
-
email_registration
(subject, body, user)[source]¶ Sends and email invitation to a user informing they have been registered with the application
-
enable_record_versioning
(tables, archive_db=None, archive_names='%(tablename)s_archive', current_record='current_record', current_record_label=None)[source]¶ Used 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
Note
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.
-
get_or_create_user
(keys, update_fields=['email'], login=True, get=True)[source]¶ 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.
-
has_membership
(group_id=None, user_id=None, role=None)[source]¶ Checks if user is member of group_id or role
-
has_permission
(name='any', table_name='', record_id=0, user_id=None, group_id=None)[source]¶ 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
-
impersonate
(user_id=<function <lambda>>)[source]¶ To use this make a 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)
-
is_logged_in
()[source]¶ 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
-
jwt
()[source]¶ To use JWT authentication: 1) instantiate auth with:
auth = Auth(db, jwt = {'secret_key':'secret'})
where ‘secret’ is your own secret string.
Decorate functions that require login but should accept the JWT token credentials:
@auth.allows_jwt() @auth.requires_login() def myapi(): return 'hello %s' % auth.user.email
Notice jwt is allowed but not required. if user is logged in, myapi is accessible.
- Use it!
Now API users can obtain a token with
(returns json object with a token attribute) API users can refresh an existing token with
they can authenticate themselves when calling http:/…/myapi by injecting a header
Authorization: Bearer <the jwt token>Any additional attributes in the jwt argument of Auth() below:
auth = Auth(db, jwt = {...})
are passed to the constructor of class AuthJWT. Look there for documentation.
-
log_event
(description, vars=None, origin='auth')[source]¶ Examples
Use as:
auth.log_event(description='this happened', origin='auth')
-
login
(next=<function <lambda>>, onvalidation=<function <lambda>>, onaccept=<function <lambda>>, log=<function <lambda>>)[source]¶ Returns a login form
-
login_bare
(username, password)[source]¶ Logins user as specified by username (or email) and password
-
logout
(next=<function <lambda>>, onlogout=<function <lambda>>, log=<function <lambda>>)[source]¶ Logouts and redirects to login
Navbar with support for more templates This uses some code from the old navbar.
Parameters: mode – see options for list of
You can change the view for this page to make it look as you like
-
profile
(next=<function <lambda>>, onvalidation=<function <lambda>>, onaccept=<function <lambda>>, log=<function <lambda>>)[source]¶ Returns a form that lets the user change his/her profile
-
register
(next=<function <lambda>>, onvalidation=<function <lambda>>, onaccept=<function <lambda>>, log=<function <lambda>>)[source]¶ Returns a registration form
-
register_bare
(**fields)[source]¶ Registers a user as specified by username (or email) and a raw password.
-
request_reset_password
(next=<function <lambda>>, onvalidation=<function <lambda>>, onaccept=<function <lambda>>, log=<function <lambda>>)[source]¶ Returns a form to reset the user password
-
requires
(condition, requires_login=True, otherwise=None)[source]¶ Decorator that prevents access to action if not logged in
-
requires_membership
(role=None, group_id=None, otherwise=None)[source]¶ 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_permission
(name, table_name='', record_id=0, otherwise=None)[source]¶ 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’.
-
requires_signature
(otherwise=None, hash_vars=True)[source]¶ 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.
-
reset_password
(next=<function <lambda>>, onvalidation=<function <lambda>>, onaccept=<function <lambda>>, log=<function <lambda>>)[source]¶ Returns a form to reset the user password
-
reset_password_deprecated
(next=<function <lambda>>, onvalidation=<function <lambda>>, onaccept=<function <lambda>>, log=<function <lambda>>)[source]¶ Returns a form to reset the user password (deprecated)
-
retrieve_password
(next=<function <lambda>>, onvalidation=<function <lambda>>, onaccept=<function <lambda>>, log=<function <lambda>>)[source]¶
-
retrieve_username
(next=<function <lambda>>, onvalidation=<function <lambda>>, onaccept=<function <lambda>>, log=<function <lambda>>)[source]¶ Returns a form to retrieve the user username (only if there is a username field)
-
select_host
(host, host_names=None)[source]¶ checks that host is valid, i.e. in the list of glob host_names if the host is missing, then is it selects the first entry from host_names read more here: https://github.com/web2py/web2py/issues/1196
-
user_group
(user_id=None)[source]¶ Returns the group_id of the group uniquely associated to this user i.e. role=user:[user_id]
-
user_id
¶ user.id or None
-
verify_email
(next=<function <lambda>>, onaccept=<function <lambda>>, log=<function <lambda>>)[source]¶ Action used to verify the registration email
-
when_is_logged_in_bypass_next_in_url
(next, session)[source]¶ This function should be use when someone want to avoid asking for user credentials when loaded page contains “user/login?_next=NEXT_COMPONENT” in the URL is refresh but user is already authenticated.
-
wiki
(slug=None, env=None, render='markmin', manage_permissions=False, force_prefix='', restrict_search=False, resolve=True, extra=None, menu_groups=None, templates=None, migrate=True, controller=None, function=None, force_render=False, groups=None)[source]¶
To be used in menu.py for app wide wiki menus
-
-
class
gluon.tools.
Recaptcha
(request=None, public_key='', private_key='', use_ssl=False, error=None, error_message='invalid', label='Verify:', options='', comment='', ajax=False)[source]¶ Bases:
gluon.html.DIV
Examples
Use as:
form = FORM(Recaptcha(public_key='...', private_key='...'))
or:
form = SQLFORM(...) form.append(Recaptcha(public_key='...', private_key='...'))
-
API_SERVER
= 'http://www.google.com/recaptcha/api'¶
-
API_SSL_SERVER
= 'https://www.google.com/recaptcha/api'¶
-
VERIFY_SERVER
= 'http://www.google.com/recaptcha/api/verify'¶
-
-
class
gluon.tools.
Recaptcha2
(request=None, public_key='', private_key='', error_message='invalid', label='Verify:', options=None, comment='')[source]¶ Bases:
gluon.html.DIV
Experimental: Creates a DIV holding the newer Recaptcha from Google (v2)
Parameters: - request – the request. If not passed, uses current request
- public_key – the public key Google gave you
- private_key – the private key Google gave you
- error_message – the error message to show if verification fails
- label – the label to use
- options (dict) –
takes these parameters
- hl
- theme
- type
- tabindex
- callback
- expired-callback
see https://developers.google.com/recaptcha/docs/display for docs about those
- comment – the comment
Examples
Use as:
form = FORM(Recaptcha2(public_key='...', private_key='...'))
or:
form = SQLFORM(...) form.append(Recaptcha2(public_key='...', private_key='...'))
to protect the login page instead, use:
from gluon.tools import Recaptcha2 auth.settings.captcha = Recaptcha2(request, public_key='...', private_key='...')
-
API_URI
= 'https://www.google.com/recaptcha/api.js'¶
-
VERIFY_SERVER
= 'https://www.google.com/recaptcha/api/siteverify'¶
-
class
gluon.tools.
Crud
(environment, db=None, controller='default')[source]¶ Bases:
object
-
create
(table, next=<function <lambda>>, onvalidation=<function <lambda>>, onaccept=<function <lambda>>, log=<function <lambda>>, message=<function <lambda>>, formname=<function <lambda>>, **attributes)[source]¶
-
search
(*tables, **args)[source]¶ Creates a search form and its results for a table .. rubric:: Examples
Use as:
form, results = crud.search(db.test, queries = ['equals', 'not equal', 'contains'], query_labels={'equals':'Equals', 'not equal':'Not equal'}, fields = ['id','children'], field_labels = { 'id':'ID','children':'Children'}, zero='Please choose', query = (db.test.id > 0)&(db.test.id != 3) )
-
-
class
gluon.tools.
Service
(environment=None)[source]¶ Bases:
object
-
amfrpc
(f)[source]¶ Example
Use as:
service = Service() @service.amfrpc def myfunction(a, b): return a + b def call(): return service()
Then call it with:
wget http://..../app/default/call/amfrpc/myfunction?a=hello&b=world
-
amfrpc3
(domain='default')[source]¶ Example
Use as:
service = Service() @service.amfrpc3('domain') def myfunction(a, b): return a + b def call(): return service()
Then call it with:
-
csv
(f)[source]¶ Example
Use as:
service = Service() @service.csv def myfunction(a, b): return a + b def call(): return service()
Then call it with:
wget http://..../app/default/call/csv/myfunction?a=3&b=4
-
json
(f)[source]¶ Example
Use as:
service = Service() @service.json def myfunction(a, b): return [{a: b}] def call(): return service()
Then call it with:;
-
jsonrpc
(f)[source]¶ Example
Use as:
service = Service() @service.jsonrpc def myfunction(a, b): return a + b def call(): return service()
Then call it with:
-
jsonrpc2
(f)[source]¶ Example
Use as:
service = Service() @service.jsonrpc2 def myfunction(a, b): return a + b def call(): return service()
Then call it with:
wget –post-data ‘{“jsonrpc”: “2.0”, “id”: 1, “method”: “myfunction”, “params”: {“a”: 1, “b”: 2}}’ http://…./app/default/call/jsonrpc2
-
jsonrpc_errors
= {-32700: ('Parse error. Invalid JSON was received by the server.', 'An error occurred on the server while parsing the JSON text.'), -32603: ('Internal error', 'Internal JSON-RPC error.'), -32602: ('Invalid params', 'Invalid method parameter(s).'), -32601: ('Method not found', 'The method does not exist / is not available.'), -32600: ('Invalid Request', 'The JSON sent is not a valid Request object.'), -32099: ('Server error', 'Reserved for implementation-defined server-errors.')}¶
-
rss
(f)[source]¶ Example
Use as:
service = Service() @service.rss def myfunction(): return dict(title=..., link=..., description=..., created_on=..., entries=[dict(title=..., link=..., description=..., created_on=...]) def call(): return service()
Then call it with:
-
run
(f)[source]¶ Example
Use as:
service = Service() @service.run def myfunction(a, b): return a + b def call(): return service()
Then call it with:
wget http://..../app/default/call/run/myfunction?a=3&b=4
-
soap
(name=None, returns=None, args=None, doc=None)[source]¶ Example
Use as:
service = Service() @service.soap('MyFunction',returns={'result':int},args={'a':int,'b':int,}) def myfunction(a, b): return a + b def call(): return service()
Then call it with:
from gluon.contrib.pysimplesoap.client import SoapClient client = SoapClient(wsdl="http://..../app/default/call/soap?WSDL") response = client.MyFunction(a=1,b=2) return response['result']
It also exposes online generated documentation and xml example messages at http://…./app/default/call/soap
-
-
class
gluon.tools.
Wiki
(auth, env=None, render='markmin', manage_permissions=False, force_prefix='', restrict_search=False, extra=None, menu_groups=None, templates=None, migrate=True, controller=None, function=None, groups=None)[source]¶ Bases:
object
adds the menu if not present
-
static
component
(text)[source]¶ In wiki docs allows @{component:controller/function/args} which renders as a LOAD(…, ajax=True)
-
everybody
= 'everybody'¶
-
rows_page
= 25¶
-
class
gluon.tools.
PluginManager
(plugin=None, **defaults)[source]¶ Bases:
object
Plugin Manager is similar to a storage object but it is a single level singleton. This means that multiple instances within the same thread share the same attributes. Its constructor is also special. The first argument is the name of the plugin you are defining. The named arguments are parameters needed by the plugin with default values. If the parameters were previous defined, the old values are used.
Example
in some general configuration file:
plugins = PluginManager() plugins.me.param1=3
within the plugin model:
_ = PluginManager('me',param1=5,param2=6,param3=7)
where the plugin is used:
>>> print plugins.me.param1 3 >>> print plugins.me.param2 6 >>> plugins.me.param3 = 8 >>> print plugins.me.param3 8
Here are some tests:
>>> a=PluginManager() >>> a.x=6 >>> b=PluginManager('check') >>> print b.x 6 >>> b=PluginManager() # reset settings >>> print b.x <Storage {}> >>> b.x=7 >>> print a.x 7 >>> a.y.z=8 >>> print b.y.z 8 >>> test_thread_separation() 5 >>> plugins=PluginManager('me',db='mydb') >>> print plugins.me.db mydb >>> print 'me' in plugins True >>> print plugins.me.installed True
-
instances
= {}¶
-