Update docs

This commit is contained in:
Matt Wright
2012-07-13 16:06:10 -04:00
parent fcab270f25
commit 507de82aba
2 changed files with 186 additions and 193 deletions
+176 -191
View File
@@ -3,32 +3,20 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Flask-Security
==============
Extending Flask-Security
========================
.. module:: flask_security
Simple security for Flask applications combining
`Flask-Login <http://packages.python.org/Flask-Login/>`_,
`Flask-Principal <http://packages.python.org/Flask-Principal/>`_,
`Flask-WTF <http://packages.python.org/Flask-WTF/>`_,
`passlib <http://packages.python.org/passlib/>`_, and your choice of datastore.
Currently `SQLAlchemy <http://www.sqlalchemy.org>`_ via
`Flask-SQLAlchemy <http://packages.python.org/Flask-SQLAlchemy/>`_ and
`MongoEngine <http://www.mongoengine.org/>`_ via
`Flask-MongoEngine <https://github.com/sbook/flask-mongoengine/>`_ are supported
out of the box. You will need to install the necessary Flask extensions that
you'll be using on your own. Additionally, you may need to install an encryption
library such as `py-bcrypt <http://www.mindrot.org/projects/py-bcrypt/>`_ (if
you plan to use bcrypt) for your desired encryption method.
Quick and simple security for Flask applications.
Contents
=========
* :ref:`overview`
* :ref:`installation`
* :ref:`getting-started`
* :ref:`additional-user-fields`
* :ref:`quick-start`
* :ref:`models`
* :ref:`flask-script-commands`
* :ref:`api`
* :doc:`Changelog </changelog>`
@@ -39,17 +27,34 @@ Contents
Overview
========
Flask-Security does a few things that Flask-Login and Flask-Principal don't
provide out of the box. They are:
Flask-Security allows you to quickly add common user and security mechanisms to
your Flask application. They include:
1. Setting up login and logout endpoints
2. Authenticating users based on username or email
3. Limiting access based on user 'roles'
4. User and role creation
5. Password encryption
1. Session based authentication
2. Role management
3. Password encryption
4. Basic HTTP authentication
5. Token based authentication
6. Token based account activation (optional)
7. Token based password recovery/resetting (optional)
8. User registration (optional)
9. Login tracking (optional)
10. Basic user management commands
That being said, you can still hook into things such as the Flask-Login and
Flask-Principal signals if need be.
Many of these features are made possible by integrating various Flask extensions
and libraries. They include:
1. Flask-Login
2. Flask-Mail
3. Flask-Principal
4. Flask-Script
5. Flask-WTF
6. itsdangerous
7. passlib
Additionally, it assumes you'll be using a common library for your database
connections and model definitions. Flask-Security thus supports SQLAlchemy and
MongoEngine out of the box and additional libraries can easily be supported.
.. _installation:
@@ -66,109 +71,93 @@ Then install your datastore requirement.
**SQLAlchemy**::
$ pip install Flask-SQLAlchemy
$ pip install flask-sqlalchemy
**MongoEngine**::
$ pip install https://github.com/sbook/flask-mongoengine/tarball/master
$ pip install flask-mongoengine
And lastly install any password encryption library that you may need. For
example::
$ pip install py-bcrypt
.. _getting-started:
.. _quick-start:
Getting Started
===============
Quick Start Example
===================
The following code samples will illustrate how to get started using SQLAlchemy.
First thing you'll want to do is setup your application and datastore::
The following code sample illustrates how to get started as quickly as possible
using SQLAlchemy.::
from flask import Flask, render_template
from flask import Flask, render_template, url_for
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.security import (User, Security, LoginForm, login_required,
roles_accepted, user_datastore)
from flask.ext.security.datastore.sqlalchemy import SQLAlchemyUserDatastore
from flask.ext.security import Security, UserMixin, RoleMixin, \
login_required
from flask.ext.security.datastore import SQLAlchemyUserDatastore
from flask.ext.security.forms import LoginForm
app = Flask(__name__)
app.debug = True
app.config['SECRET_KEY'] = 'secret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
db = SQLAlchemy(app)
Security(app, SQLAlchemyUserDatastore(db))
app.config['SECURITY_POST_LOGIN_VIEW'] = '/protected'
You'll probably want to at least one user to the database to test this out.
There are many ways to do this, but this is a quick and dirty way to do it::
db = SQLAlchemy(app)
roles_users = db.Table('roles_users',
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))
class Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(80), unique=True)
description = db.Column(db.String(255))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), unique=True)
password = db.Column(db.String(120))
remember_token = db.Column(db.String(255))
active = db.Column(db.Boolean())
authentication_token = db.Column(db.String(255))
roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'))
datastore = SQLAlchemyUserDatastore(db, User, Role)
Security(app, datastore)
@app.before_first_request
def before_first_request():
user_datastore.create_role(name='admin')
user_datastore.create_user(username='matt', email='matt@something.com',
password='password', roles=['admin'])
Next you'll want to setup your login screen. Setup your view::
def add_user():
db.create_all()
datastore.create_user(email='matt@matt.com',
password='password')
@app.route("/login")
@app.route('/')
@app.route('/login')
def login():
return render_template('login.html', form=LoginForm())
And corresponding template::
return render_template('security/logins/new.html',
login_form=LoginForm())
<form action="{{ url_for('auth.authenticate') }}" method="POST">
{{ form.hidden_tag() }}
{{ form.username.label }} {{ form.username }}<br/>
{{ form.password.label }} {{ form.password }}<br/>
{{ form.remember.label }} {{ form.remember }}<br/>
{{ form.submit }}
</form>
By default, Flask-Security will redirect a user to `/profile` after logging in.
You can set this page up yourself or set the `SECURITY_POST_LOGIN` config
value to change this behavior. Regardless, setup a protected view as such::
@app.route('/profile')
@app.route('/protected')
@login_required
def profile():
return render_template('profile.html')
Now you have an application with basic authentication. If you run the local
development server you can visit `http://localhost:5000/login <http://localhost:5000/login>`_
to login.
def protected():
return """<h1>You are logged in</h1>
<p><a href="%s">Log out</a>""" % (
url_for('flask_security.logout'))
The last thing you'll want to do is add a logout link to your templates. This
can be achieved with::
<a href="{{ url_for('auth.logout') }}">Logout</a>
Now, for instance, say you want to protect an admin area to users that are
administrators. You can use the `roles_accepted` decorator to prevent access.
The corresponding view would look like such::
@app.route('/admin')
@roles_accepted('admin')
def admin():
return render_template('admin/index.html')
And lastly, maybe you only want to show something in a template if a user has a
specific role::
{% if current_user.has_role('admin') %}
<a href="{{ url_for('admin.index') }}">Admin Panel</a>
{$ endif %}
if __name__ == '__main__':
app.run()
.. _additional-user-fields:
.. _models:
Additional User Fields
----------------------
If you'd like to add additional fields to the user model you can use a mixin
class that specifies your additional fields. The following is an example of
how you might do this::
Data Models
-----------
db = SQLAlchemy(app)
class UserAccountMixin():
first_name = db.Column(db.String(120))
last_name = db.Column(db.String(120))
Security(app, SQLAlchemyUserDatastore(db, UserAccountMixin))
TODO: Describe models and required fields for various features
.. _flask-script-commands:
@@ -176,12 +165,14 @@ Flask-Script Commands
---------------------
Flask-Security comes packed with a few Flask-Script commands. They are:
* :class:`flask.ext.security.script.CreateUserCommand`
* :class:`flask.ext.security.script.CreateRoleCommand`
* :class:`flask.ext.security.script.AddRoleCommand`
* :class:`flask.ext.security.script.RemoveRoleCommand`
* :class:`flask.ext.security.script.DeactivateUserCommand`
* :class:`flask.ext.security.script.ActivateUserCommand`
* :class:`flask_security.script.CreateUserCommand`
* :class:`flask_security.script.CreateRoleCommand`
* :class:`flask_security.script.AddRoleCommand`
* :class:`flask_security.script.RemoveRoleCommand`
* :class:`flask_security.script.DeactivateUserCommand`
* :class:`flask_security.script.ActivateUserCommand`
* :class:`flask_security.script.ActivateUserCommand`
* :class:`flask_security.script.GenerateBlueprintCommand`
Register these on your script manager for pure convenience.
@@ -192,25 +183,63 @@ Configuration Values
====================
* :attr:`SECURITY_URL_PREFIX`: Specifies the URL prefix for the Security
blueprint
* :attr:`SECURITY_AUTH_PROVIDER`: Specifies the class to use as the
authentication provider. Such as `flask.ext.security.AuthenticationProvider`
* :attr:`SECURITY_PASSWORD_HASH`: Specifies the encryption method to use. e.g.:
plaintext, bcrypt, etc
* :attr:`SECURITY_USER_DATASTORE`: Specifies the property name to use for the
user datastore on the application instance
* :attr:`SECURITY_LOGIN_FORM`: Specifies the form class to use when processing
an authentication request
* :attr:`SECURITY_AUTH_URL`: Specifies the URL to to handle authentication
* :attr:`SECURITY_LOGOUT_URL`: Specifies the URL to process a logout request
* :attr:`SECURITY_LOGIN_VIEW`: Specifies the URL to redirect to when
authentication is required
* :attr:`SECURITY_POST_LOGIN`: Specifies the URL to redirect to after a user is
authenticated
* :attr:`SECURITY_POST_LOGOUT`: Specifies the URL to redirect to after a user
logs out
blueprint.
* :attr:`SECURITY_FLASH_MESSAGES`: Specifies wether or not to flash messages
during authentication request
during security mechanisms.
* :attr:`SECURITY_PASSWORD_HASH`: Specifies the encryption method to use. e.g.:
plaintext, bcrypt, etc.
* :attr:`SECURITY_AUTH_URL`: Specifies the URL to to handle authentication.
* :attr:`SECURITY_LOGOUT_URL`: Specifies the URL to process a logout request.
* :attr:`SECURITY_REGISTER_URL`: Specifies the URL for user registrations.
* :attr:`SECURITY_RESET_URL`: Specifies the URL for password resets.
* :attr:`SECURITY_CONFIRM_URL`: Specifies the URL for account confirmations.
* :attr:`SECURITY_LOGIN_VIEW`: Specifies the URL to redirect to when
authentication is required.
* :attr:`SECURITY_CONFIRM_ERROR_VIEW`: Specifies the URL to redirect to when
an confirmation error occurs.
* :attr:`SECURITY_POST_LOGIN_VIEW`: Specifies the URL to redirect to after a
user logins in.
* :attr:`SECURITY_POST_LOGOUT_VIEW`: Specifies the URL to redirect to after a
user logs out.
* :attr:`SECURITY_POST_FORGOT_VIEW`: Specifies the URL to redirect to after a
user requests password reset instructions.
* :attr:`SECURITY_RESET_PASSWORD_ERROR_VIEW`: Specifies the URL to redirect to
after an error occurs during the password reset process.
* :attr:`SECURITY_POST_REGISTER_VIEW`: Specifies the URL to redirect to after a
user successfully registers.
* :attr:`SECURITY_POST_CONFIRM_VIEW`: Specifies the URL to redirect to after a
user successfully confirms their account.
* :attr:`SECURITY_UNAUTHORIZED_VIEW`: Specifies the URL to redirect to when a
user attempts to access a view they don't have permission to view.
* :attr:`SECURITY_DEFAULT_ROLES`: The default roles any new users should have.
* :attr:`SECURITY_CONFIRMABLE`: Enables confirmation features. Defaults to
`False`.
* :attr:`SECURITY_REGISTERABLE`: Enables user registration features. Defaults to
`False`.
* :attr:`SECURITY_RECOVERABLE`: Enables password reset/recovery features.
Defaults to `False`.
* :attr:`SECURITY_TRACKABLE`: Enables login tracking features. Defaults to
`False`.
* :attr:`SECURITY_CONFIRM_EMAIL_WITHIN`: Specifies the amount of time a user
has to confirm their account/email. Default is `5 days`.
* :attr:`SECURITY_RESET_PASSWORD_WITHIN`: Specifies the amount of time a user
has to reset their password. Default is `5 days`.
* :attr:`SECURITY_LOGIN_WITHOUT_CONFIRMATION`: Specifies if users can login
without first confirming their accounts. Defaults to `False`
* :attr:`SECURITY_EMAIL_SENDER`: Specifies the email address to send emails on
behalf of. Defaults to `no-reply@localhost`.
* :attr:`SECURITY_TOKEN_AUTHENTICATION_KEY`: Specifies the query string argument
to use during token authentication. Defaults to `auth_token`.
* :attr:`SECURITY_TOKEN_AUTHENTICATION_HEADER`: Specifies the header name to use
during token authentication. Defaults to `X-Auth-Token`.
* :attr:`SECURITY_CONFIRM_SALT`: Specifies the salt value to use for account
confirmation tokens. Defaults to `confirm-salt`.
* :attr:`SECURITY_RESET_SALT`: Specifies the salt value to use for password
reset tokens. Defaults to `reset-salt`.
* :attr:`SECURITY_AUTH_SALT`: Specifies the salt value to use for token based
authentication tokens. Defaults to `auth-salt`.
* :attr:`SECURITY_DEFAULT_HTTP_AUTH_REALM`: Specifies the default basic HTTP
authentication realm. Defaults to `Login Required`.
.. _api:
@@ -218,32 +247,36 @@ Configuration Values
API
===
.. autoclass:: flask_security.Security
.. autoclass:: flask_security.core.Security
:members:
.. data:: flask_security.current_user
.. data:: flask_security.core.current_user
A proxy for the current user.
Protecting Views
----------------
.. autofunction:: flask_security.login_required
.. autofunction:: flask_security.decorators.login_required
.. autofunction:: flask_security.roles_required
.. autofunction:: flask_security.decorators.roles_required
.. autofunction:: flask_security.roles_accepted
.. autofunction:: flask_security.decorators.roles_accepted
.. autofunction:: flask_security.decorators.http_auth_required
.. autofunction:: flask_security.decorators.auth_token_required
User Object Helpers
-------------------
.. autoclass:: flask_security.UserMixin
.. autoclass:: flask_security.core.UserMixin
:members:
.. autoclass:: flask_security.RoleMixin
.. autoclass:: flask_security.core.RoleMixin
:members:
.. autoclass:: flask_security.AnonymousUser
.. autoclass:: flask_security.core.AnonymousUser
:members:
@@ -252,65 +285,13 @@ Datastores
.. autoclass:: flask_security.datastore.UserDatastore
:members:
.. autoclass:: flask_security.datastore.sqlalchemy.SQLAlchemyUserDatastore
.. autoclass:: flask_security.datastore.SQLAlchemyUserDatastore
:members:
:inherited-members:
.. autoclass:: flask_security.datastore.mongoengine.MongoEngineUserDatastore
.. autoclass:: flask_security.datastore.MongoEngineUserDatastore
:members:
:inherited-members:
Models
------
.. autoclass:: flask_security.User
.. attribute:: id
User ID
.. attribute:: username
Username
.. attribute:: email
Email address
.. attribute:: password
Password
.. attribute:: active
Active state
.. attribute:: roles
User roles
.. attribute:: created_at
Created date
.. attribute:: modified_at
Modified date
.. autoclass:: flask_security.Role
.. attribute:: id
Role ID
.. attribute:: name
Role name
.. attribute:: description
Role description
Exceptions
@@ -331,6 +312,10 @@ Exceptions
.. autoexception:: flask_security.RoleCreationError
.. autoexception:: flask_security.ConfirmationError
.. autoexception:: flask_security.ResetPasswordError
Signals
-------
+10 -2
View File
@@ -87,7 +87,10 @@ def _check_http_auth():
def http_auth_required(realm):
"""Decorator that protects endpoints using Basic HTTP authentication."""
"""Decorator that protects endpoints using Basic HTTP authentication.
The username should be set to the user's email address.
:param realm: optional realm name"""
def decorator(fn):
@wraps(fn)
@@ -109,7 +112,12 @@ def http_auth_required(realm):
def auth_token_required(fn):
"""Decorator that protects endpoints using token authentication."""
"""Decorator that protects endpoints using token authentication. The token
should be added to the request by the client by using a query string
variable with a name equal to the configuration value of
`SECURITY_TOKEN_AUTHENTICATION_KEY` or in a request header named that of
the configuration value of `SECURITY_TOKEN_AUTHENTICATION_HEADER`
"""
@wraps(fn)
def decorated(*args, **kwargs):