summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorDariusz Górecki <darek.krk@gmail.com>2016-08-10 11:10:49 +0100
committerDariusz Górecki <darek.krk@gmail.com>2016-08-10 11:10:49 +0100
commitf2f196db97462d5d19253d261cb2167fd19c1108 (patch)
tree8f14e42096c343b57d4ccae486dea0309bad4b49 /docs
parentc0ddbc37530042119539b60245e2e2a4fccc83c0 (diff)
parenta69db3dc7c57f318308434905ee96e23d0c0d3df (diff)
downloadpyramid-f2f196db97462d5d19253d261cb2167fd19c1108.tar.gz
pyramid-f2f196db97462d5d19253d261cb2167fd19c1108.tar.bz2
pyramid-f2f196db97462d5d19253d261cb2167fd19c1108.zip
Merge branch 'master' into extract_http_basic
Diffstat (limited to 'docs')
-rw-r--r--docs/narr/hooks.rst8
-rw-r--r--docs/narr/urldispatch.rst6
-rw-r--r--docs/quick_tutorial/authentication.rst35
-rw-r--r--docs/quick_tutorial/authentication/setup.py3
-rw-r--r--docs/quick_tutorial/authentication/tutorial/security.py16
-rw-r--r--docs/quick_tutorial/authentication/tutorial/views.py7
-rw-r--r--docs/quick_tutorial/authorization/setup.py3
-rw-r--r--docs/quick_tutorial/authorization/tutorial/security.py16
-rw-r--r--docs/quick_tutorial/authorization/tutorial/views.py7
-rw-r--r--docs/quick_tutorial/forms.rst1
-rw-r--r--docs/tutorials/wiki2/basiclayout.rst2
-rw-r--r--docs/tutorials/wiki2/installation.rst7
12 files changed, 82 insertions, 29 deletions
diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst
index 49ef29d3f..c54b213f1 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -26,7 +26,7 @@ Not Found View by using the
:linenos:
def notfound(request):
- return Response('Not Found, dude', status='404 Not Found')
+ return Response('Not Found', status='404 Not Found')
def main(globals, **settings):
config = Configurator()
@@ -45,7 +45,7 @@ and a :term:`scan`, you can replace the Not Found View by using the
@notfound_view_config()
def notfound(request):
- return Response('Not Found, dude', status='404 Not Found')
+ return Response('Not Found', status='404 Not Found')
def main(globals, **settings):
config = Configurator()
@@ -67,11 +67,11 @@ Views can carry predicates limiting their applicability. For example:
@notfound_view_config(request_method='GET')
def notfound_get(request):
- return Response('Not Found during GET, dude', status='404 Not Found')
+ return Response('Not Found during GET', status='404 Not Found')
@notfound_view_config(request_method='POST')
def notfound_post(request):
- return Response('Not Found during POST, dude', status='404 Not Found')
+ return Response('Not Found during POST', status='404 Not Found')
def main(globals, **settings):
config = Configurator()
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index 7d37c04df..9ac01e24a 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -850,7 +850,7 @@ application:
from pyramid.httpexceptions import HTTPNotFound
def notfound(request):
- return HTTPNotFound('Not found, bro.')
+ return HTTPNotFound()
def no_slash(request):
return Response('No slash')
@@ -871,7 +871,7 @@ If a request enters the application with the ``PATH_INFO`` value of
However, if a request enters the application with the ``PATH_INFO`` value of
``/no_slash/``, *no* route will match, and the slash-appending not found view
will not find a matching route with an appended slash. As a result, the
-``notfound`` view will be called and it will return a "Not found, bro." body.
+``notfound`` view will be called and it will return a "Not found" body.
If a request enters the application with the ``PATH_INFO`` value of
``/has_slash/``, the second route will match. If a request enters the
@@ -892,7 +892,7 @@ exactly the same job:
@notfound_view_config(append_slash=True)
def notfound(request):
- return HTTPNotFound('Not found, bro.')
+ return HTTPNotFound()
@view_config(route_name='noslash')
def no_slash(request):
diff --git a/docs/quick_tutorial/authentication.rst b/docs/quick_tutorial/authentication.rst
index acff97f3b..892beb3ec 100644
--- a/docs/quick_tutorial/authentication.rst
+++ b/docs/quick_tutorial/authentication.rst
@@ -1,7 +1,7 @@
.. _qtut_authentication:
==============================
-20: Logins With Authentication
+20: Logins with authentication
==============================
Login views that authenticate a username and password against a list of users.
@@ -34,6 +34,18 @@ Steps
.. code-block:: bash
$ cd ..; cp -r view_classes authentication; cd authentication
+
+#. Add ``bcrypt`` as a dependency in ``authentication/setup.py``:
+
+ .. literalinclude:: authentication/setup.py
+ :language: python
+ :emphasize-lines: 5-6
+ :linenos:
+
+#. We can now install our project in development mode:
+
+ .. code-block:: bash
+
$ $VENV/bin/pip install -e .
#. Put the security hash in the ``authentication/development.ini``
@@ -96,8 +108,8 @@ Unlike many web frameworks, Pyramid includes a built-in but optional security
model for authentication and authorization. This security system is intended to
be flexible and support many needs. In this security model, authentication (who
are you) and authorization (what are you allowed to do) are not just pluggable,
-but de-coupled. To learn one step at a time, we provide a system that
-identifies users and lets them log out.
+but decoupled. To learn one step at a time, we provide a system that identifies
+users and lets them log out.
In this example we chose to use the bundled :ref:`AuthTktAuthenticationPolicy
<authentication_module>` policy. We enabled it in our configuration and
@@ -108,6 +120,20 @@ returned a login form. When reached via ``POST``, it processed the submitted
username and password against the "groupfinder" callable that we registered in
the configuration.
+The function ``hash_password`` uses a one-way hashing algorithm with a salt on
+the user's password via ``bcrypt``, instead of storing the password in plain
+text. This is considered to be a "best practice" for security.
+
+.. note::
+ There are alternative libraries to ``bcrypt`` if it is an issue on your
+ system. Just make sure that the library uses an algorithm approved for
+ storing passwords securely.
+
+The function ``check_password`` will compare the two hashed values of the
+submitted password and the user's password stored in the database. If the
+hashed values are equivalent, then the user is authenticated, else
+authentication fails.
+
In our template, we fetched the ``logged_in`` value from the view class. We use
this to calculate the logged-in user, if any. In the template we can then
choose to show a login link to anonymous visitors or a logout link to logged-in
@@ -125,4 +151,5 @@ Extra credit
request? Use ``import pdb; pdb.set_trace()`` to answer this.
.. seealso:: See also :ref:`security_chapter`,
- :ref:`AuthTktAuthenticationPolicy <authentication_module>`.
+ :ref:`AuthTktAuthenticationPolicy <authentication_module>`, `bcrypt
+ <https://pypi.python.org/pypi/bcrypt>`_
diff --git a/docs/quick_tutorial/authentication/setup.py b/docs/quick_tutorial/authentication/setup.py
index 2221b72e9..7a6ff4226 100644
--- a/docs/quick_tutorial/authentication/setup.py
+++ b/docs/quick_tutorial/authentication/setup.py
@@ -2,7 +2,8 @@ from setuptools import setup
requires = [
'pyramid',
- 'pyramid_chameleon'
+ 'pyramid_chameleon',
+ 'bcrypt'
]
setup(name='tutorial',
diff --git a/docs/quick_tutorial/authentication/tutorial/security.py b/docs/quick_tutorial/authentication/tutorial/security.py
index ab90bab2c..e585e2642 100644
--- a/docs/quick_tutorial/authentication/tutorial/security.py
+++ b/docs/quick_tutorial/authentication/tutorial/security.py
@@ -1,5 +1,17 @@
-USERS = {'editor': 'editor',
- 'viewer': 'viewer'}
+import bcrypt
+
+
+def hash_password(pw):
+ pwhash = bcrypt.hashpw(pw.encode('utf8'), bcrypt.gensalt())
+ return pwhash.decode('utf8')
+
+def check_password(pw, hashed_pw):
+ expected_hash = hashed_pw.encode('utf8')
+ return bcrypt.checkpw(pw.encode('utf8'), expected_hash)
+
+
+USERS = {'editor': hash_password('editor'),
+ 'viewer': hash_password('viewer')}
GROUPS = {'editor': ['group:editors']}
diff --git a/docs/quick_tutorial/authentication/tutorial/views.py b/docs/quick_tutorial/authentication/tutorial/views.py
index ab46eb2dd..b07538d5e 100644
--- a/docs/quick_tutorial/authentication/tutorial/views.py
+++ b/docs/quick_tutorial/authentication/tutorial/views.py
@@ -9,7 +9,10 @@ from pyramid.view import (
view_defaults
)
-from .security import USERS
+from .security import (
+ USERS,
+ check_password
+)
@view_defaults(renderer='home.pt')
@@ -40,7 +43,7 @@ class TutorialViews:
if 'form.submitted' in request.params:
login = request.params['login']
password = request.params['password']
- if USERS.get(login) == password:
+ if check_password(password, USERS.get(login)):
headers = remember(request, login)
return HTTPFound(location=came_from,
headers=headers)
diff --git a/docs/quick_tutorial/authorization/setup.py b/docs/quick_tutorial/authorization/setup.py
index 2221b72e9..7a6ff4226 100644
--- a/docs/quick_tutorial/authorization/setup.py
+++ b/docs/quick_tutorial/authorization/setup.py
@@ -2,7 +2,8 @@ from setuptools import setup
requires = [
'pyramid',
- 'pyramid_chameleon'
+ 'pyramid_chameleon',
+ 'bcrypt'
]
setup(name='tutorial',
diff --git a/docs/quick_tutorial/authorization/tutorial/security.py b/docs/quick_tutorial/authorization/tutorial/security.py
index ab90bab2c..e585e2642 100644
--- a/docs/quick_tutorial/authorization/tutorial/security.py
+++ b/docs/quick_tutorial/authorization/tutorial/security.py
@@ -1,5 +1,17 @@
-USERS = {'editor': 'editor',
- 'viewer': 'viewer'}
+import bcrypt
+
+
+def hash_password(pw):
+ pwhash = bcrypt.hashpw(pw.encode('utf8'), bcrypt.gensalt())
+ return pwhash.decode('utf8')
+
+def check_password(pw, hashed_pw):
+ expected_hash = hashed_pw.encode('utf8')
+ return bcrypt.checkpw(pw.encode('utf8'), expected_hash)
+
+
+USERS = {'editor': hash_password('editor'),
+ 'viewer': hash_password('viewer')}
GROUPS = {'editor': ['group:editors']}
diff --git a/docs/quick_tutorial/authorization/tutorial/views.py b/docs/quick_tutorial/authorization/tutorial/views.py
index 43d14455a..b2dc905c0 100644
--- a/docs/quick_tutorial/authorization/tutorial/views.py
+++ b/docs/quick_tutorial/authorization/tutorial/views.py
@@ -10,7 +10,10 @@ from pyramid.view import (
forbidden_view_config
)
-from .security import USERS
+from .security import (
+ USERS,
+ check_password
+)
@view_defaults(renderer='home.pt')
@@ -42,7 +45,7 @@ class TutorialViews:
if 'form.submitted' in request.params:
login = request.params['login']
password = request.params['password']
- if USERS.get(login) == password:
+ if check_password(password, USERS.get(login)):
headers = remember(request, login)
return HTTPFound(location=came_from,
headers=headers)
diff --git a/docs/quick_tutorial/forms.rst b/docs/quick_tutorial/forms.rst
index 1f421ee67..84ceb13d6 100644
--- a/docs/quick_tutorial/forms.rst
+++ b/docs/quick_tutorial/forms.rst
@@ -41,6 +41,7 @@ Steps
pulls in Colander as a dependency:
.. literalinclude:: forms/setup.py
+ :emphasize-lines: 5-6
:linenos:
#. We can now install our project in development mode:
diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst
index ce67bb9e3..98a14c644 100644
--- a/docs/tutorials/wiki2/basiclayout.rst
+++ b/docs/tutorials/wiki2/basiclayout.rst
@@ -114,7 +114,7 @@ Finally ``main`` is finished configuring things, so it uses the
Route declarations
------------------
-Open the ``tutorials/routes.py`` file. It should already contain the following:
+Open the ``tutorial/routes.py`` file. It should already contain the following:
.. literalinclude:: src/basiclayout/tutorial/routes.py
:linenos:
diff --git a/docs/tutorials/wiki2/installation.rst b/docs/tutorials/wiki2/installation.rst
index a214b1306..0440c2d1d 100644
--- a/docs/tutorials/wiki2/installation.rst
+++ b/docs/tutorials/wiki2/installation.rst
@@ -402,13 +402,6 @@ initialize our database.
already have a database, you should delete it before running
``initialize_tutorial_db`` again.
-.. note::
-
- The ``initialize_tutorial_db`` command is not performing a migration but
- rather simply creating missing tables and adding some dummy data. If you
- already have a database, you should delete it before running
- ``initialize_tutorial_db`` again.
-
Type the following command, making sure you are still in the ``tutorial``
directory (the directory with a ``development.ini`` in it):