diff options
Diffstat (limited to 'docs/narr')
| -rw-r--r-- | docs/narr/commandline.rst | 24 | ||||
| -rw-r--r-- | docs/narr/i18n.rst | 4 | ||||
| -rw-r--r-- | docs/narr/introduction.rst | 4 | ||||
| -rw-r--r-- | docs/narr/project.rst | 12 | ||||
| -rw-r--r-- | docs/narr/renderers.rst | 2 | ||||
| -rw-r--r-- | docs/narr/resources.rst | 2 | ||||
| -rw-r--r-- | docs/narr/sessions.rst | 109 | ||||
| -rw-r--r-- | docs/narr/traversal.rst | 2 | ||||
| -rw-r--r-- | docs/narr/urldispatch.rst | 2 | ||||
| -rw-r--r-- | docs/narr/viewconfig.rst | 43 |
10 files changed, 158 insertions, 46 deletions
diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst index e1347f3ca..17e5227fa 100644 --- a/docs/narr/commandline.rst +++ b/docs/narr/commandline.rst @@ -474,6 +474,30 @@ input of the ``prequest`` process is used as the ``POST`` body:: $ $VENV/bin/prequest -mPOST development.ini / < somefile +Showing All Installed Distributions and their Versions +------------------------------------------------------ + +.. versionadded:: 1.5 + +You can use the ``pdistreport`` command to show the Pyramid version in use, the +Python version in use, and all installed versions of Python distributions in +your Python environment:: + + $ $VENV/bin/pdistreport + Pyramid version: 1.5dev + Platform Linux-3.2.0-51-generic-x86_64-with-debian-wheezy-sid + Packages: + authapp 0.0 + /home/chrism/projects/foo/src/authapp + beautifulsoup4 4.1.3 + /home/chrism/projects/foo/lib/python2.7/site-packages/beautifulsoup4-4.1.3-py2.7.egg + ... more output ... + +``pdistreport`` takes no options. Its output is useful to paste into a +pastebin when you are having problems and need someone with more familiarity +with Python packaging and distribution than you have to look at your +environment. + .. _writing_a_script: Writing a Script diff --git a/docs/narr/i18n.rst b/docs/narr/i18n.rst index 74765f8e2..2964686d3 100644 --- a/docs/narr/i18n.rst +++ b/docs/narr/i18n.rst @@ -808,7 +808,7 @@ If this setting is supplied within the :app:`Pyramid` application default_locale_name = settings['pyramid.default_locale_name'] .. index:: - single: detecting langauges + single: detecting languages "Detecting" Available Languages ------------------------------- @@ -984,7 +984,7 @@ requires no additional coding or configuration. The default locale negotiator implementation named :class:`~pyramid.i18n.default_locale_negotiator` uses the following -set of steps to dermine the locale name. +set of steps to determine the locale name. - First, the negotiator looks for the ``_LOCALE_`` attribute of the request object (possibly set directly by view code or by a listener diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst index 48164d323..032f4be6b 100644 --- a/docs/narr/introduction.rst +++ b/docs/narr/introduction.rst @@ -217,6 +217,8 @@ that the Pyramid core doesn't. Add-on packages already exist which let you easily send email, let you use the Jinja2 templating system, let you use XML-RPC or JSON-RPC, let you integrate with jQuery Mobile, etc. +Examples: http://docs.pylonsproject.org/en/latest/docs/pyramid.html#pyramid-add-on-documentation + Class-based and function-based views ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -857,7 +859,7 @@ It's our goal that no Pyramid question go unanswered. Whether you ask a question on IRC, on the Pylons-discuss maillist, or on StackOverflow, you're likely to get a reasonably prompt response. We don't tolerate "support trolls" or other people who seem to get their rocks off by berating fellow -users in our various offical support channels. We try to keep it well-lit +users in our various official support channels. We try to keep it well-lit and new-user-friendly. Example: Visit irc\://freenode.net#pyramid (the ``#pyramid`` channel on diff --git a/docs/narr/project.rst b/docs/narr/project.rst index 9d69a65a5..e25f3012a 100644 --- a/docs/narr/project.rst +++ b/docs/narr/project.rst @@ -1005,12 +1005,12 @@ Pyramid application based on the data in the file. application. As we saw in :ref:`firstapp_chapter`, ``pserve`` needn't be invoked at all to run a :app:`Pyramid` application. The use of ``pserve`` to run a :app:`Pyramid` application is purely conventional based on the output -of its scaffolding. But we strongly recommend using while developing your -application, because many other convenience introspection commands (such as -``pviews``, ``prequest``, ``proutes`` and others) are also implemented in -terms of configuration availability of this ``.ini`` file format. It also -configures Pyramid logging and provides the ``--reload`` switch for -convenient restarting of the server when code changes. +of its scaffolding. But we strongly recommend using ``pserve`` while +developing your application, because many other convenience introspection +commands (such as ``pviews``, ``prequest``, ``proutes`` and others) are also +implemented in terms of configuration availability of this ``.ini`` file +format. It also configures Pyramid logging and provides the ``--reload`` +switch for convenient restarting of the server when code changes. .. _alternate_wsgi_server: diff --git a/docs/narr/renderers.rst b/docs/narr/renderers.rst index 20a9eda31..a2811dbae 100644 --- a/docs/narr/renderers.rst +++ b/docs/narr/renderers.rst @@ -198,7 +198,7 @@ representing the JSON serialization of the return value: .. code-block:: python - '{"content": "Hello!"}' + {"content": "Hello!"} The return value needn't be a dictionary, but the return value must contain values serializable by the configured serializer (by default ``json.dumps``). diff --git a/docs/narr/resources.rst b/docs/narr/resources.rst index 699a3d4ac..b1bb611e5 100644 --- a/docs/narr/resources.rst +++ b/docs/narr/resources.rst @@ -300,7 +300,7 @@ the resource by :meth:`~pyramid.request.Request.resource_url`. The ``__resource_url__`` hook is passed two arguments: ``request`` and ``info``. ``request`` is the :term:`request` object passed to :meth:`~pyramid.request.Request.resource_url`. ``info`` is a dictionary with -two keys: +the following keys: ``physical_path`` A string representing the "physical path" computed for the resource, as diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index c4f4b5f07..82440060c 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -148,6 +148,7 @@ Some gotchas: .. index:: single: pyramid_beaker single: Beaker + single: pyramid_redis_sessions single: session factory (alternates) .. _using_alternate_session_factories: @@ -155,11 +156,17 @@ Some gotchas: Using Alternate Session Factories --------------------------------- -At the time of this writing, exactly one alternate session factory -implementation exists, named ``pyramid_beaker``. This is a session factory -that uses the `Beaker <http://beaker.groovie.org/>`_ library as a backend. -Beaker has support for file-based sessions, database based sessions, and -encrypted cookie-based sessions. See `the pyramid_beaker documentation +At the time of this writing, exactly two alternate session factories +exist. + +The first is named ``pyramid_redis_sessions``. It can be downloaded from PyPI. +It uses Redis as a backend. It is the recommended persistent session solution +at the time of this writing. + +The second is named ``pyramid_beaker``. This is a session factory that uses the +`Beaker <http://beaker.groovie.org/>`_ library as a backend. Beaker has +support for file-based sessions, database based sessions, and encrypted +cookie-based sessions. See `the pyramid_beaker documentation <http://docs.pylonsproject.org/projects/pyramid_beaker/en/latest/>`_ for more information about ``pyramid_beaker``. @@ -298,14 +305,15 @@ Preventing Cross-Site Request Forgery Attacks `Cross-site request forgery <http://en.wikipedia.org/wiki/Cross-site_request_forgery>`_ attacks are a -phenomenon whereby a user with an identity on your website might click on a -URL or button on another website which secretly redirects the user to your -application to perform some command that requires elevated privileges. - -You can avoid most of these attacks by making sure that the correct *CSRF -token* has been set in an :app:`Pyramid` session object before performing any -actions in code which requires elevated privileges that is invoked via a form -post. To use CSRF token support, you must enable a :term:`session factory` +phenomenon whereby a user who is logged in to your website might inadvertantly +load a URL because it is linked from, or embedded in, an attacker's website. +If the URL is one that may modify or delete data, the consequences can be dire. + +You can avoid most of these attacks by issuing a unique token to the browser +and then requiring that it be present in all potentially unsafe requests. +:app:`Pyramid` sessions provide facilities to create and check CSRF tokens. + +To use CSRF tokens, you must first enable a :term:`session factory` as described in :ref:`using_the_default_session_factory` or :ref:`using_alternate_session_factories`. @@ -324,33 +332,82 @@ To get the current CSRF token from the session, use the The ``session.get_csrf_token()`` method accepts no arguments. It returns a CSRF *token* string. If ``session.get_csrf_token()`` or -``session.new_csrf_token()`` was invoked previously for this session, the +``session.new_csrf_token()`` was invoked previously for this session, then the existing token will be returned. If no CSRF token previously existed for -this session, a new token will be will be set into the session and returned. +this session, then a new token will be will be set into the session and returned. The newly created token will be opaque and randomized. You can use the returned token as the value of a hidden field in a form that -posts to a method that requires elevated privileges. The handler for the -form post should use ``session.get_csrf_token()`` *again* to obtain the -current CSRF token related to the user from the session, and compare it to -the value of the hidden form field. For example, if your form rendering -included the CSRF token obtained via ``session.get_csrf_token()`` as a hidden -input field named ``csrf_token``: +posts to a method that requires elevated privileges, or supply it as a request +header in AJAX requests. + +For example, include the CSRF token as a hidden field: + +.. code-block:: html + + <form method="post" action="/myview"> + <input type="hidden" name="csrf_token" value="${request.session.get_csrf_token()}"> + <input type="submit" value="Delete Everything"> + </form> + +Or, include it as a header in a jQuery AJAX request: + +.. code-block:: javascript + + var csrfToken = ${request.session.get_csrf_token()}; + $.ajax({ + type: "POST", + url: "/myview", + headers: { 'X-CSRF-Token': csrfToken } + }).done(function() { + alert("Deleted"); + }); + + +The handler for the URL that receives the request +should then require that the correct CSRF token is supplied. + +Using the ``session.check_csrf_token`` Method +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In request handling code, you can check the presence and validity of a CSRF +token with ``session.check_csrf_token(request)``. If the token is valid, +it will return True, otherwise it will raise ``HTTPBadRequest``. + +By default, it checks for a GET or POST parameter named ``csrf_token`` or a +header named ``X-CSRF-Token``. .. code-block:: python - :linenos: - token = request.session.get_csrf_token() - if token != request.POST['csrf_token']: - raise ValueError('CSRF token did not match') + def myview(request): + session = request.session + + # Require CSRF Token + session.check_csrf_token(request): + + ... .. index:: single: session.new_csrf_token +Checking CSRF Tokens With A View Predicate +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A convenient way to require a valid CSRF Token for a particular view is to +include ``check_csrf=True`` as a view predicate. +See :meth:`pyramid.config.Configurator.add_route`. + +.. code-block:: python + + @view_config(request_method='POST', check_csrf=True, ...) + def myview(request): + ... + + Using the ``session.new_csrf_token`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To explicitly add a new CSRF token to the session, use the +To explicitly create a new CSRF token, use the ``session.new_csrf_token()`` method. This differs only from ``session.get_csrf_token()`` inasmuch as it clears any existing CSRF token, creates a new CSRF token, sets the token into the session, and returns the diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst index 2eb6ece13..a60c5ba56 100644 --- a/docs/narr/traversal.rst +++ b/docs/narr/traversal.rst @@ -289,7 +289,7 @@ system uses this algorithm to find a :term:`context` resource and a return resource "C". #. Traversal ends when a) the entire path is exhausted or b) when any - resouce raises a :exc:`KeyError` from its ``__getitem__`` or c) when any + resource raises a :exc:`KeyError` from its ``__getitem__`` or c) when any non-final path element traversal does not have a ``__getitem__`` method (resulting in a :exc:`AttributeError`) or d) when any path element is prefixed with the set of characters ``@@`` (indicating that the characters diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst index 18cb3e4db..310c160c0 100644 --- a/docs/narr/urldispatch.rst +++ b/docs/narr/urldispatch.rst @@ -865,7 +865,7 @@ Debugging Route Matching ------------------------ It's useful to be able to take a peek under the hood when requests that enter -your application arent matching your routes as you expect them to. To debug +your application aren't matching your routes as you expect them to. To debug route matching, use the ``PYRAMID_DEBUG_ROUTEMATCH`` environment variable or the ``pyramid.debug_routematch`` configuration file setting (set either to ``true``). Details of the route matching decision for a particular request to the diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index 241ce62b5..6a064c209 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -290,9 +290,9 @@ configured view. of the ``REQUEST_METHOD`` of the :term:`WSGI` environment. ``request_param`` - This value can be any string or a sequence of strings. A view declaration - with this argument ensures that the view will only be called when the - :term:`request` has a key in the ``request.params`` dictionary (an HTTP + This value can be any string or a sequence of strings. A view declaration + with this argument ensures that the view will only be called when the + :term:`request` has a key in the ``request.params`` dictionary (an HTTP ``GET`` or ``POST`` variable) that has a name which matches the supplied value. @@ -306,8 +306,6 @@ configured view. consideration of keys and values in the ``request.params`` dictionary. ``match_param`` - .. versionadded:: 1.2 - This param may be either a single string of the format "key=value" or a dict of key/value pairs. @@ -324,6 +322,8 @@ configured view. If ``match_param`` is not supplied, the view will be invoked without consideration of the keys and values in ``request.matchdict``. + .. versionadded:: 1.2 + ``containment`` This value should be a reference to a Python class or :term:`interface` that a parent object in the context resource's :term:`lineage` must provide @@ -505,7 +505,7 @@ configuration stanza: .. code-block:: python :linenos: - config.add_view('mypackage.views.my_view', route_name='ok', + config.add_view('mypackage.views.my_view', route_name='ok', request_method='POST', permission='read') All arguments to ``view_config`` may be omitted. For example: @@ -557,6 +557,35 @@ form of :term:`declarative configuration`, while :meth:`pyramid.config.Configurator.add_view` is a form of :term:`imperative configuration`. However, they both do the same thing. +Inverting Predicate Values +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can invert the meaning of any predicate value by wrapping it in a call to +:class:`pyramid.config.not_`. + +.. code-block:: python + :linenos: + + from pyramid.config import not_ + + config.add_view( + 'mypackage.views.my_view', + route_name='ok', + request_method=not_('POST') + ) + +The above example will ensure that the view is called if the request method +is *not* ``POST``, at least if no other view is more specific. + +This technique of wrapping a predicate value in ``not_`` can be used anywhere +predicate values are accepted: + +- :meth:`pyramid.config.Configurator.add_view` + +- :meth:`pyramid.view.view_config` + +.. versionadded:: 1.5 + .. index:: single: view_config placement @@ -802,7 +831,7 @@ of this: config.add_view( RESTView, route_name='rest', attr='delete', request_method='DELETE') -To reduce the amount of repetion in the ``config.add_view`` statements, we +To reduce the amount of repetition in the ``config.add_view`` statements, we can move the ``route_name='rest'`` argument to a ``@view_default`` class decorator on the RESTView class: |
