From 3c2f95e8049bbd45b144d454daa68005361828b2 Mon Sep 17 00:00:00 2001 From: Matt Russell Date: Thu, 24 Oct 2013 23:52:42 +0100 Subject: Security APIs on pyramid.request.Request The pyramid.security Authorization API function has_permission is made available on the request. The pyramid.security Authentication API functions are now available as properties (unauthenticated_userid, authenticated_userid, effective_principals) and methods (remember_userid, forget_userid) on pyramid.request.Request. Backwards compatibility: For each of the APIs moved to request method or property, the original API in the pyramid.security module proxies to the request. Reworked tests to check module level b/c wrappers call through to mixins for each API. Tests that check no reg on request now do the right thing. Use a response callback to set the request headers for forget_userid and remember_userid. Update docs. Attempt to improve a documentation section referencing the pyramid.security.has_permission function in docs/narr/resources.rst Ensures backwards compatiblity for `pyramid.security.forget` and `pyramid.security.remember`. --- docs/narr/resources.rst | 12 ++++++------ docs/narr/security.rst | 4 ++-- docs/narr/testing.rst | 2 +- docs/narr/viewconfig.rst | 2 +- docs/tutorials/wiki/authorization.rst | 4 ++-- docs/tutorials/wiki2/authorization.rst | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) (limited to 'docs') diff --git a/docs/narr/resources.rst b/docs/narr/resources.rst index b1bb611e5..34d75f2cc 100644 --- a/docs/narr/resources.rst +++ b/docs/narr/resources.rst @@ -201,7 +201,7 @@ location-aware resources. These APIs include (but are not limited to) :func:`~pyramid.traversal.resource_path`, :func:`~pyramid.traversal.resource_path_tuple`, or :func:`~pyramid.traversal.traverse`, :func:`~pyramid.traversal.virtual_root`, -and (usually) :func:`~pyramid.security.has_permission` and +and (usually) :meth:`~pyramid.request.Request.has_permission` and :func:`~pyramid.security.principals_allowed_by_permission`. In general, since so much :app:`Pyramid` infrastructure depends on @@ -695,10 +695,10 @@ The APIs provided by :ref:`location_module` are used against resources. These can be used to walk down a resource tree, or conveniently locate one resource "inside" another. -Some APIs in :ref:`security_module` accept a resource object as a parameter. -For example, the :func:`~pyramid.security.has_permission` API accepts a +Some APIs on the :class:`pyramid.request.Request` accept a resource object as a parameter. +For example, the :meth:`~pyramid.request.Request.has_permission` API accepts a resource object as one of its arguments; the ACL is obtained from this -resource or one of its ancestors. Other APIs in the :mod:`pyramid.security` -module also accept :term:`context` as an argument, and a context is always a -resource. +resource or one of its ancestors. Other security related APIs on the +:class:`pyramid.request.Request` class also accept :term:`context` as an argument, +and a context is always a resource. diff --git a/docs/narr/security.rst b/docs/narr/security.rst index e85ed823a..9e6fb6c82 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -550,7 +550,7 @@ also contain security debugging information in its body. Debugging Imperative Authorization Failures ------------------------------------------- -The :func:`pyramid.security.has_permission` API is used to check +The :meth:`pyramid.request.Request.has_permission` API is used to check security within view functions imperatively. It returns instances of objects that are effectively booleans. But these objects are not raw ``True`` or ``False`` objects, and have information attached to them @@ -563,7 +563,7 @@ one of :data:`pyramid.security.ACLAllowed`, ``msg`` attribute, which is a string indicating why the permission was denied or allowed. Introspecting this information in the debugger or via print statements when a call to -:func:`~pyramid.security.has_permission` fails is often useful. +:meth:`~pyramid.request.Request.has_permission` fails is often useful. .. index:: single: authentication policy (creating) diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst index 88d6904c7..3f5d5ae6c 100644 --- a/docs/narr/testing.rst +++ b/docs/narr/testing.rst @@ -229,7 +229,7 @@ function. otherwise it would fail when run normally. Without doing anything special during a unit test, the call to -:func:`~pyramid.security.has_permission` in this view function will always +:meth:`~pyramid.request.Request.has_permission` in this view function will always return a ``True`` value. When a :app:`Pyramid` application starts normally, it will populate a :term:`application registry` using :term:`configuration declaration` calls made against a :term:`Configurator`. But if this diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index 7c76116f7..e5a2c1ade 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -435,7 +435,7 @@ configured view. If specified, this value should be a :term:`principal` identifier or a sequence of principal identifiers. If the - :func:`pyramid.security.effective_principals` method indicates that every + :meth:`pyramid.request.Request.effective_principals` method indicates that every principal named in the argument list is present in the current request, this predicate will return True; otherwise it will return False. For example: ``effective_principals=pyramid.security.Authenticated`` or diff --git a/docs/tutorials/wiki/authorization.rst b/docs/tutorials/wiki/authorization.rst index 460a852e0..2bd8c1f1c 100644 --- a/docs/tutorials/wiki/authorization.rst +++ b/docs/tutorials/wiki/authorization.rst @@ -207,8 +207,8 @@ need to be added.) :meth:`~pyramid.view.forbidden_view_config` will be used to customize the default 403 Forbidden page. -:meth:`~pyramid.security.remember` and -:meth:`~pyramid.security.forget` help to create and +:meth:`~pyramid.request.Request.remember_userid` and +:meth:`~pyramid.request.Request.forget_userid` help to create and expire an auth ticket cookie. Now add the ``login`` and ``logout`` views: diff --git a/docs/tutorials/wiki2/authorization.rst b/docs/tutorials/wiki2/authorization.rst index cf20db6d7..2b4263610 100644 --- a/docs/tutorials/wiki2/authorization.rst +++ b/docs/tutorials/wiki2/authorization.rst @@ -230,8 +230,8 @@ head of ``tutorial/tutorial/views.py``: :meth:`~pyramid.view.forbidden_view_config` will be used to customize the default 403 Forbidden page. -:meth:`~pyramid.security.remember` and -:meth:`~pyramid.security.forget` help to create and +:meth:`~pyramid.request.Request.remember_userid` and +:meth:`~pyramid.request.Request.forget_userid` help to create and expire an auth ticket cookie. Now add the ``login`` and ``logout`` views: -- cgit v1.2.3 From 0184b527725cfb634e4d57a1b033450fa8b24502 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Mon, 28 Oct 2013 15:26:31 -0400 Subject: Bring change log, API docs, and deprecations in line with normal policies/processes --- docs/api/request.rst | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api/request.rst b/docs/api/request.rst index 72abddb68..3d1fe020c 100644 --- a/docs/api/request.rst +++ b/docs/api/request.rst @@ -11,7 +11,10 @@ :exclude-members: add_response_callback, add_finished_callback, route_url, route_path, current_route_url, current_route_path, static_url, static_path, - model_url, resource_url, set_property + model_url, resource_url, set_property, + effective_principals, authenticated_userid, + unauthenticated_userid, has_permission, forget_userid, + remember_userid .. attribute:: context @@ -161,6 +164,42 @@ request, the value of this attribute will be ``None``. See :ref:`matched_route`. + .. attribute:: authenticated_userid + + .. versionadded:: 1.5 + + A property which returns the userid of the currently authenticated user + or ``None`` if there is no :term:`authentication policy` in effect or + there is no currently authenticated user. This differs from + :meth:`~pyramid.request.Request.unauthenticated_userid`, because the + effective authentication policy will have ensured that a record + associated with the userid exists in persistent storage; if it has + not, this value will be ``None``. + + .. attribute:: unauthenticated_userid + + .. versionadded:: 1.5 + + A property which returns a value which represents the *claimed* (not + verified) user id of the credentials present in the request. ``None`` if + there is no :term:`authentication policy` in effect or there is no user + data associated with the current request. This differs from + :meth:`~pyramid.request.Request.authenticated_userid`, because the + effective authentication policy will not ensure that a record associated + with the userid exists in persistent storage. Even if the userid + does not exist in persistent storage, this value will be the value + of the userid *claimed* by the request data. + + .. attribute:: effective_principals + + .. versionadded:: 1.5 + + A property which returns the list of 'effective' :term:`principal` + identifiers for this request. This will include the userid of the + currently authenticated user if a user is currently authenticated. If no + :term:`authentication policy` is in effect, this will return a sequence + containing only the :attr:`pyramid.security.Everyone` principal. + .. method:: invoke_subrequest(request, use_tweens=False) .. versionadded:: 1.4a1 @@ -215,6 +254,12 @@ request provided by e.g. the ``pshell`` environment. For more information, see :ref:`subrequest_chapter`. + .. automethod:: remember_userid + + .. automethod:: forget_userid + + .. automethod:: has_permission + .. automethod:: add_response_callback .. automethod:: add_finished_callback -- cgit v1.2.3 From 696e0e3bd257fdace57adbb4c3d331af377d9e5b Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 30 Oct 2013 19:47:52 -0400 Subject: fix zodb tutorial wrt request-based authentication and authorization apis --- docs/tutorials/wiki/authorization.rst | 34 +++++++--------------- .../wiki/src/authorization/tutorial/views.py | 22 +++++--------- 2 files changed, 18 insertions(+), 38 deletions(-) (limited to 'docs') diff --git a/docs/tutorials/wiki/authorization.rst b/docs/tutorials/wiki/authorization.rst index 2bd8c1f1c..bba303d7f 100644 --- a/docs/tutorials/wiki/authorization.rst +++ b/docs/tutorials/wiki/authorization.rst @@ -56,10 +56,10 @@ returns one of these values: return ``None``. For example, ``groupfinder('editor', request )`` returns ``['group:editor']``, -``groupfinder('viewer', request)`` returns ``[]``, and ``groupfinder('admin', request)`` -returns ``None``. We will use ``groupfinder()`` as an :term:`authentication policy` -"callback" that will provide the :term:`principal` or principals -for a user. +``groupfinder('viewer', request)`` returns ``[]``, and ``groupfinder('admin', +request)`` returns ``None``. We will use ``groupfinder()`` as an +:term:`authentication policy` "callback" that will provide the +:term:`principal` or principals for a user. In a production system, user and group data will most often come from a database, but here we use "dummy" @@ -197,15 +197,15 @@ Add the following import statements to the head of ``tutorial/tutorial/views.py``: .. literalinclude:: src/authorization/tutorial/views.py - :lines: 6-13,15-17 + :lines: 6-11 :linenos: - :emphasize-lines: 3,6-9,11 + :emphasize-lines: 3,6 :language: python (Only the highlighted lines, with other necessary modifications, need to be added.) -:meth:`~pyramid.view.forbidden_view_config` will be used +:func:`~pyramid.view.forbidden_view_config` will be used to customize the default 403 Forbidden page. :meth:`~pyramid.request.Request.remember_userid` and :meth:`~pyramid.request.Request.forget_userid` help to create and @@ -214,7 +214,7 @@ expire an auth ticket cookie. Now add the ``login`` and ``logout`` views: .. literalinclude:: src/authorization/tutorial/views.py - :lines: 82-120 + :lines: 76-102 :linenos: :language: python @@ -251,18 +251,6 @@ in ``views.py``. Return a logged_in flag to the renderer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Add the following line to the import at the head of -``tutorial/tutorial/views.py``: - -.. literalinclude:: src/authorization/tutorial/views.py - :lines: 11-15 - :linenos: - :emphasize-lines: 4 - :language: python - -(Only the highlighted line and a trailing comma on the preceding -line need to be added.) - Add a ``logged_in`` parameter to the return value of ``view_page()``, ``edit_page()`` and ``add_page()``, like this: @@ -274,12 +262,12 @@ like this: return dict(page = page, content = content, edit_url = edit_url, - logged_in = authenticated_userid(request)) + logged_in = request.authenticated_userid) (Only the highlighted line and a trailing comma on the preceding line need to be added.) -:meth:`~pyramid.security.authenticated_userid()` will return ``None`` +:attr:`~pyramid.request.Request.authenticated_userid` will return ``None`` if the user is not authenticated, or a user id if the user is authenticated. @@ -329,7 +317,7 @@ when we're done: .. literalinclude:: src/authorization/tutorial/views.py :linenos: - :emphasize-lines: 8,11-15,17,24,29,48,52,68,72,80,82-120 + :emphasize-lines: 8,11,18,23,42,46,62,66,74,80,76-107 :language: python (Only the highlighted lines need to be added.) diff --git a/docs/tutorials/wiki/src/authorization/tutorial/views.py b/docs/tutorials/wiki/src/authorization/tutorial/views.py index 77956b1e3..57529ac8d 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/views.py +++ b/docs/tutorials/wiki/src/authorization/tutorial/views.py @@ -8,12 +8,6 @@ from pyramid.view import ( forbidden_view_config, ) -from pyramid.security import ( - remember, - forget, - authenticated_userid, - ) - from .security import USERS from .models import Page @@ -45,7 +39,7 @@ def view_page(context, request): edit_url = request.resource_url(context, 'edit_page') return dict(page = context, content = content, edit_url = edit_url, - logged_in = authenticated_userid(request)) + logged_in = request.authenticated_userid) @view_config(name='add_page', context='.models.Wiki', renderer='templates/edit.pt', @@ -65,7 +59,7 @@ def add_page(context, request): page.__parent__ = context return dict(page=page, save_url=save_url, - logged_in=authenticated_userid(request)) + logged_in=request.authenticated_userid) @view_config(name='edit_page', context='.models.Page', renderer='templates/edit.pt', @@ -77,7 +71,7 @@ def edit_page(context, request): return dict(page=context, save_url=request.resource_url(context, 'edit_page'), - logged_in=authenticated_userid(request)) + logged_in=request.authenticated_userid) @view_config(context='.models.Wiki', name='login', renderer='templates/login.pt') @@ -95,9 +89,8 @@ def login(request): login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - headers = remember(request, login) - return HTTPFound(location = came_from, - headers = headers) + request.remember_userid(login) + return HTTPFound(location=came_from) message = 'Failed login' return dict( @@ -110,6 +103,5 @@ def login(request): @view_config(context='.models.Wiki', name='logout') def logout(request): - headers = forget(request) - return HTTPFound(location = request.resource_url(request.context), - headers = headers) + request.forget_userid() + return HTTPFound(location=request.resource_url(request.context)) -- cgit v1.2.3 From f436d7f5cd19e94378737096d9d21635b157fc46 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 30 Oct 2013 20:03:49 -0400 Subject: copy forward views.py changes to tests step --- docs/tutorials/wiki/src/tests/tutorial/views.py | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) (limited to 'docs') diff --git a/docs/tutorials/wiki/src/tests/tutorial/views.py b/docs/tutorials/wiki/src/tests/tutorial/views.py index 77956b1e3..57529ac8d 100644 --- a/docs/tutorials/wiki/src/tests/tutorial/views.py +++ b/docs/tutorials/wiki/src/tests/tutorial/views.py @@ -8,12 +8,6 @@ from pyramid.view import ( forbidden_view_config, ) -from pyramid.security import ( - remember, - forget, - authenticated_userid, - ) - from .security import USERS from .models import Page @@ -45,7 +39,7 @@ def view_page(context, request): edit_url = request.resource_url(context, 'edit_page') return dict(page = context, content = content, edit_url = edit_url, - logged_in = authenticated_userid(request)) + logged_in = request.authenticated_userid) @view_config(name='add_page', context='.models.Wiki', renderer='templates/edit.pt', @@ -65,7 +59,7 @@ def add_page(context, request): page.__parent__ = context return dict(page=page, save_url=save_url, - logged_in=authenticated_userid(request)) + logged_in=request.authenticated_userid) @view_config(name='edit_page', context='.models.Page', renderer='templates/edit.pt', @@ -77,7 +71,7 @@ def edit_page(context, request): return dict(page=context, save_url=request.resource_url(context, 'edit_page'), - logged_in=authenticated_userid(request)) + logged_in=request.authenticated_userid) @view_config(context='.models.Wiki', name='login', renderer='templates/login.pt') @@ -95,9 +89,8 @@ def login(request): login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - headers = remember(request, login) - return HTTPFound(location = came_from, - headers = headers) + request.remember_userid(login) + return HTTPFound(location=came_from) message = 'Failed login' return dict( @@ -110,6 +103,5 @@ def login(request): @view_config(context='.models.Wiki', name='logout') def logout(request): - headers = forget(request) - return HTTPFound(location = request.resource_url(request.context), - headers = headers) + request.forget_userid() + return HTTPFound(location=request.resource_url(request.context)) -- cgit v1.2.3 From 3657ba974660677050fe4a62441c2073bd71203c Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 30 Oct 2013 20:08:58 -0400 Subject: fix wiki2 tutorial wrt request-method security APIs --- docs/tutorials/wiki2/authorization.rst | 27 +++++++--------------- .../wiki2/src/authorization/tutorial/views.py | 22 ++++++------------ docs/tutorials/wiki2/src/tests/tutorial/views.py | 22 ++++++------------ 3 files changed, 22 insertions(+), 49 deletions(-) (limited to 'docs') diff --git a/docs/tutorials/wiki2/authorization.rst b/docs/tutorials/wiki2/authorization.rst index 2b4263610..830cb0277 100644 --- a/docs/tutorials/wiki2/authorization.rst +++ b/docs/tutorials/wiki2/authorization.rst @@ -221,14 +221,14 @@ Add the following import statements to the head of ``tutorial/tutorial/views.py``: .. literalinclude:: src/authorization/tutorial/views.py - :lines: 9-16,18,24-25 + :lines: 9-12,19 :linenos: - :emphasize-lines: 3,6-9,11 + :emphasize-lines: 3,5 :language: python (Only the highlighted lines need to be added.) -:meth:`~pyramid.view.forbidden_view_config` will be used +:func:`~pyramid.view.forbidden_view_config` will be used to customize the default 403 Forbidden page. :meth:`~pyramid.request.Request.remember_userid` and :meth:`~pyramid.request.Request.forget_userid` help to create and @@ -237,7 +237,7 @@ expire an auth ticket cookie. Now add the ``login`` and ``logout`` views: .. literalinclude:: src/authorization/tutorial/views.py - :lines: 91-123 + :lines: 85-115 :linenos: :language: python @@ -274,17 +274,6 @@ added to ``views.py``. Return a logged_in flag to the renderer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Add the following line to the import at the head of -``tutorial/tutorial/views.py``: - -.. literalinclude:: src/authorization/tutorial/views.py - :lines: 14-18 - :linenos: - :emphasize-lines: 4 - :language: python - -(Only the highlighted line needs to be added.) - Add a ``logged_in`` parameter to the return value of ``view_page()``, ``edit_page()`` and ``add_page()``, like this: @@ -296,12 +285,12 @@ like this: return dict(page = page, content = content, edit_url = edit_url, - logged_in = authenticated_userid(request)) + logged_in = request.authenticated_userid) (Only the highlighted line needs to be added.) -The :meth:`~pyramid.security.authenticated_userid` method will return None -if the user is not authenticated. +The :attr:`~pyramid.request.Request.authenticated_userid` property will return +``None`` if the user is not authenticated. Add a "Logout" link when logged in ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -349,7 +338,7 @@ when we're done: .. literalinclude:: src/authorization/tutorial/views.py :linenos: - :emphasize-lines: 11,14-18,25,31,37,58,61,73,76,88,91-117,119-123 + :emphasize-lines: 11,19,25,31,52,55,67,70,82,85-115 :language: python (Only the highlighted lines need to be added.) diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/views.py b/docs/tutorials/wiki2/src/authorization/tutorial/views.py index b6dbbf5f6..110d738c2 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/views.py +++ b/docs/tutorials/wiki2/src/authorization/tutorial/views.py @@ -11,12 +11,6 @@ from pyramid.view import ( forbidden_view_config, ) -from pyramid.security import ( - remember, - forget, - authenticated_userid, - ) - from .models import ( DBSession, Page, @@ -55,7 +49,7 @@ def view_page(request): content = wikiwords.sub(check, content) edit_url = request.route_url('edit_page', pagename=pagename) return dict(page=page, content=content, edit_url=edit_url, - logged_in=authenticated_userid(request)) + logged_in=request.authenticated_userid) @view_config(route_name='add_page', renderer='templates/edit.pt', permission='edit') @@ -70,7 +64,7 @@ def add_page(request): save_url = request.route_url('add_page', pagename=pagename) page = Page(name='', data='') return dict(page=page, save_url=save_url, - logged_in=authenticated_userid(request)) + logged_in=request.authenticated_userid) @view_config(route_name='edit_page', renderer='templates/edit.pt', permission='edit') @@ -85,7 +79,7 @@ def edit_page(request): return dict( page=page, save_url = request.route_url('edit_page', pagename=pagename), - logged_in=authenticated_userid(request), + logged_in=request.authenticated_userid, ) @view_config(route_name='login', renderer='templates/login.pt') @@ -103,9 +97,8 @@ def login(request): login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - headers = remember(request, login) - return HTTPFound(location = came_from, - headers = headers) + request.remember_userid(login) + return HTTPFound(location = came_from) message = 'Failed login' return dict( @@ -118,7 +111,6 @@ def login(request): @view_config(route_name='logout') def logout(request): - headers = forget(request) - return HTTPFound(location = request.route_url('view_wiki'), - headers = headers) + request.forget_userid() + return HTTPFound(location = request.route_url('view_wiki')) diff --git a/docs/tutorials/wiki2/src/tests/tutorial/views.py b/docs/tutorials/wiki2/src/tests/tutorial/views.py index b6dbbf5f6..110d738c2 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/views.py +++ b/docs/tutorials/wiki2/src/tests/tutorial/views.py @@ -11,12 +11,6 @@ from pyramid.view import ( forbidden_view_config, ) -from pyramid.security import ( - remember, - forget, - authenticated_userid, - ) - from .models import ( DBSession, Page, @@ -55,7 +49,7 @@ def view_page(request): content = wikiwords.sub(check, content) edit_url = request.route_url('edit_page', pagename=pagename) return dict(page=page, content=content, edit_url=edit_url, - logged_in=authenticated_userid(request)) + logged_in=request.authenticated_userid) @view_config(route_name='add_page', renderer='templates/edit.pt', permission='edit') @@ -70,7 +64,7 @@ def add_page(request): save_url = request.route_url('add_page', pagename=pagename) page = Page(name='', data='') return dict(page=page, save_url=save_url, - logged_in=authenticated_userid(request)) + logged_in=request.authenticated_userid) @view_config(route_name='edit_page', renderer='templates/edit.pt', permission='edit') @@ -85,7 +79,7 @@ def edit_page(request): return dict( page=page, save_url = request.route_url('edit_page', pagename=pagename), - logged_in=authenticated_userid(request), + logged_in=request.authenticated_userid, ) @view_config(route_name='login', renderer='templates/login.pt') @@ -103,9 +97,8 @@ def login(request): login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - headers = remember(request, login) - return HTTPFound(location = came_from, - headers = headers) + request.remember_userid(login) + return HTTPFound(location = came_from) message = 'Failed login' return dict( @@ -118,7 +111,6 @@ def login(request): @view_config(route_name='logout') def logout(request): - headers = forget(request) - return HTTPFound(location = request.route_url('view_wiki'), - headers = headers) + request.forget_userid() + return HTTPFound(location = request.route_url('view_wiki')) -- cgit v1.2.3 From e1838557e6721b5b42f1267b134b626099703c2c Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 30 Oct 2013 20:14:52 -0400 Subject: not methods, attrs --- docs/api/request.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api/request.rst b/docs/api/request.rst index 3d1fe020c..661cdfc91 100644 --- a/docs/api/request.rst +++ b/docs/api/request.rst @@ -171,7 +171,7 @@ A property which returns the userid of the currently authenticated user or ``None`` if there is no :term:`authentication policy` in effect or there is no currently authenticated user. This differs from - :meth:`~pyramid.request.Request.unauthenticated_userid`, because the + :attr:`~pyramid.request.Request.unauthenticated_userid`, because the effective authentication policy will have ensured that a record associated with the userid exists in persistent storage; if it has not, this value will be ``None``. @@ -184,7 +184,7 @@ verified) user id of the credentials present in the request. ``None`` if there is no :term:`authentication policy` in effect or there is no user data associated with the current request. This differs from - :meth:`~pyramid.request.Request.authenticated_userid`, because the + :attr:`~pyramid.request.Request.authenticated_userid`, because the effective authentication policy will not ensure that a record associated with the userid exists in persistent storage. Even if the userid does not exist in persistent storage, this value will be the value -- cgit v1.2.3 From a91c19837f5ce579ce2a5bf68ddee30cfaebe034 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 30 Oct 2013 20:19:23 -0400 Subject: note deprecation --- docs/narr/threadlocals.rst | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'docs') diff --git a/docs/narr/threadlocals.rst b/docs/narr/threadlocals.rst index a90ee4905..afe56de3e 100644 --- a/docs/narr/threadlocals.rst +++ b/docs/narr/threadlocals.rst @@ -29,17 +29,16 @@ of a thread local or a global is usually just a way to avoid passing some value around between functions, which is itself usually a very bad idea, at least if code readability counts as an important concern. -For historical reasons, however, thread local variables are indeed -consulted by various :app:`Pyramid` API functions. For example, -the implementation of the :mod:`pyramid.security` function named -:func:`~pyramid.security.authenticated_userid` retrieves the thread -local :term:`application registry` as a matter of course to find an +For historical reasons, however, thread local variables are indeed consulted by +various :app:`Pyramid` API functions. For example, the implementation of the +:mod:`pyramid.security` function named +:func:`~pyramid.security.authenticated_userid` (deprecated as of 1.5) retrieves +the thread local :term:`application registry` as a matter of course to find an :term:`authentication policy`. It uses the -:func:`pyramid.threadlocal.get_current_registry` function to -retrieve the application registry, from which it looks up the -authentication policy; it then uses the authentication policy to -retrieve the authenticated user id. This is how :app:`Pyramid` -allows arbitrary authentication policies to be "plugged in". +:func:`pyramid.threadlocal.get_current_registry` function to retrieve the +application registry, from which it looks up the authentication policy; it then +uses the authentication policy to retrieve the authenticated user id. This is +how :app:`Pyramid` allows arbitrary authentication policies to be "plugged in". When they need to do so, :app:`Pyramid` internals use two API functions to retrieve the :term:`request` and :term:`application -- cgit v1.2.3 From 675e0d4cf01840740490c03a2e3704b0b7d98de3 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 30 Oct 2013 20:24:34 -0400 Subject: convert remember/forget to request-method-based --- docs/quick_tutorial/authentication/tutorial/views.py | 17 +++++------------ docs/quick_tutorial/authorization/tutorial/views.py | 17 +++++------------ 2 files changed, 10 insertions(+), 24 deletions(-) (limited to 'docs') diff --git a/docs/quick_tutorial/authentication/tutorial/views.py b/docs/quick_tutorial/authentication/tutorial/views.py index 3038b6d9b..240a23d3e 100644 --- a/docs/quick_tutorial/authentication/tutorial/views.py +++ b/docs/quick_tutorial/authentication/tutorial/views.py @@ -1,9 +1,4 @@ from pyramid.httpexceptions import HTTPFound -from pyramid.security import ( - remember, - forget, - authenticated_userid - ) from pyramid.view import ( view_config, view_defaults @@ -16,7 +11,7 @@ from .security import USERS class TutorialViews: def __init__(self, request): self.request = request - self.logged_in = authenticated_userid(request) + self.logged_in = request.authenticated_userid @view_config(route_name='home') def home(self): @@ -41,9 +36,8 @@ class TutorialViews: login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - headers = remember(request, login) - return HTTPFound(location=came_from, - headers=headers) + request.remember_userid(login) + return HTTPFound(location=came_from) message = 'Failed login' return dict( @@ -58,7 +52,6 @@ class TutorialViews: @view_config(route_name='logout') def logout(self): request = self.request - headers = forget(request) + request.forget_userid() url = request.route_url('home') - return HTTPFound(location=url, - headers=headers) + return HTTPFound(location=url) diff --git a/docs/quick_tutorial/authorization/tutorial/views.py b/docs/quick_tutorial/authorization/tutorial/views.py index 92c1946ba..2ce2c37b4 100644 --- a/docs/quick_tutorial/authorization/tutorial/views.py +++ b/docs/quick_tutorial/authorization/tutorial/views.py @@ -1,9 +1,4 @@ from pyramid.httpexceptions import HTTPFound -from pyramid.security import ( - remember, - forget, - authenticated_userid - ) from pyramid.view import ( view_config, view_defaults, @@ -17,7 +12,7 @@ from .security import USERS class TutorialViews: def __init__(self, request): self.request = request - self.logged_in = authenticated_userid(request) + self.logged_in = request.authenticated_userid @view_config(route_name='home') def home(self): @@ -43,9 +38,8 @@ class TutorialViews: login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - headers = remember(request, login) - return HTTPFound(location=came_from, - headers=headers) + request.remember_userid(login) + return HTTPFound(location=came_from) message = 'Failed login' return dict( @@ -60,7 +54,6 @@ class TutorialViews: @view_config(route_name='logout') def logout(self): request = self.request - headers = forget(request) + request.forget_userid() url = request.route_url('home') - return HTTPFound(location=url, - headers=headers) + return HTTPFound(location=url) -- cgit v1.2.3 From 3bd1fa5dd792d639615e5125b73caef8c65a0a30 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 30 Oct 2013 20:28:53 -0400 Subject: new api --- docs/narr/testing.rst | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'docs') diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst index 3f5d5ae6c..5a5bf8fad 100644 --- a/docs/narr/testing.rst +++ b/docs/narr/testing.rst @@ -214,11 +214,10 @@ function. .. code-block:: python :linenos: - from pyramid.security import has_permission from pyramid.httpexceptions import HTTPForbidden def view_fn(request): - if not has_permission('edit', request.context, request): + if request.has_permission('edit'): raise HTTPForbidden return {'greeting':'hello'} @@ -229,15 +228,16 @@ function. otherwise it would fail when run normally. Without doing anything special during a unit test, the call to -:meth:`~pyramid.request.Request.has_permission` in this view function will always -return a ``True`` value. When a :app:`Pyramid` application starts normally, -it will populate a :term:`application registry` using :term:`configuration -declaration` calls made against a :term:`Configurator`. But if this -application registry is not created and populated (e.g. by initializing the -configurator with an authorization policy), like when you invoke application -code via a unit test, :app:`Pyramid` API functions will tend to either fail -or return default results. So how do you test the branch of the code in this -view function that raises :exc:`~pyramid.httpexceptions.HTTPForbidden`? +:meth:`~pyramid.request.Request.has_permission` in this view function will +always return a ``True`` value. When a :app:`Pyramid` application starts +normally, it will populate a :term:`application registry` using +:term:`configuration declaration` calls made against a :term:`Configurator`. +But if this application registry is not created and populated (e.g. by +initializing the configurator with an authorization policy), like when you +invoke application code via a unit test, :app:`Pyramid` API functions will tend +to either fail or return default results. So how do you test the branch of the +code in this view function that raises +:exc:`~pyramid.httpexceptions.HTTPForbidden`? The testing API provided by :app:`Pyramid` allows you to simulate various application registry registrations for use under a unit testing framework @@ -287,12 +287,12 @@ Its third line registers a "dummy" "non-permissive" authorization policy using the :meth:`~pyramid.config.Configurator.testing_securitypolicy` method, which is a special helper method for unit testing. -We then create a :class:`pyramid.testing.DummyRequest` object which simulates -a WebOb request object API. A :class:`pyramid.testing.DummyRequest` is a -request object that requires less setup than a "real" :app:`Pyramid` request. -We call the function being tested with the manufactured request. When the -function is called, :func:`pyramid.security.has_permission` will call the -"dummy" authentication policy we've registered through +We then create a :class:`pyramid.testing.DummyRequest` object which simulates a +WebOb request object API. A :class:`pyramid.testing.DummyRequest` is a request +object that requires less setup than a "real" :app:`Pyramid` request. We call +the function being tested with the manufactured request. When the function is +called, :meth:`pyramid.request.Request.has_permission` will call the "dummy" +authentication policy we've registered through :meth:`~pyramid.config.Configurator.testing_securitypolicy`, which denies access. We check that the view function raises a :exc:`~pyramid.httpexceptions.HTTPForbidden` error. -- cgit v1.2.3 From 2885a7b96545c037109d7999319f74869a640050 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 30 Oct 2013 20:40:12 -0400 Subject: fix failing test (unrelated to security stuff) --- docs/tutorials/wiki2/src/tests/tutorial/tests.py | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'docs') diff --git a/docs/tutorials/wiki2/src/tests/tutorial/tests.py b/docs/tutorials/wiki2/src/tests/tutorial/tests.py index 4ee30685e..c50e05b6d 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/tests.py +++ b/docs/tutorials/wiki2/src/tests/tutorial/tests.py @@ -26,27 +26,6 @@ def _registerRoutes(config): config.add_route('add_page', 'add_page/{pagename}') -class PageModelTests(unittest.TestCase): - - def setUp(self): - self.session = _initTestingDB() - - def tearDown(self): - self.session.remove() - - def _getTargetClass(self): - from tutorial.models import Page - return Page - - def _makeOne(self, name='SomeName', data='some data'): - return self._getTargetClass()(name, data) - - def test_constructor(self): - instance = self._makeOne() - self.assertEqual(instance.name, 'SomeName') - self.assertEqual(instance.data, 'some data') - - class ViewWikiTests(unittest.TestCase): def setUp(self): self.config = testing.setUp() -- cgit v1.2.3 From 0dcd56c2c30863c6683c0cf442aa73dfdcd11b13 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 9 Nov 2013 17:11:16 -0500 Subject: undeprecate remember/forget functions and remove remember_userid/forget_userid methods from request --- docs/api/request.rst | 7 +------ .../authentication/tutorial/views.py | 15 ++++++++++---- .../quick_tutorial/authorization/tutorial/views.py | 15 ++++++++++---- docs/tutorials/wiki/authorization.rst | 19 +++++++++--------- .../wiki/src/authorization/tutorial/views.py | 16 +++++++++++---- docs/tutorials/wiki/src/tests/tutorial/views.py | 16 +++++++++++---- docs/tutorials/wiki2/authorization.rst | 16 +++++++-------- .../wiki2/src/authorization/tutorial/views.py | 22 ++++++++++++++------- docs/tutorials/wiki2/src/tests/tutorial/views.py | 23 ++++++++++++++-------- 9 files changed, 94 insertions(+), 55 deletions(-) (limited to 'docs') diff --git a/docs/api/request.rst b/docs/api/request.rst index 661cdfc91..b7604020e 100644 --- a/docs/api/request.rst +++ b/docs/api/request.rst @@ -13,8 +13,7 @@ current_route_path, static_url, static_path, model_url, resource_url, set_property, effective_principals, authenticated_userid, - unauthenticated_userid, has_permission, forget_userid, - remember_userid + unauthenticated_userid, has_permission .. attribute:: context @@ -254,10 +253,6 @@ request provided by e.g. the ``pshell`` environment. For more information, see :ref:`subrequest_chapter`. - .. automethod:: remember_userid - - .. automethod:: forget_userid - .. automethod:: has_permission .. automethod:: add_response_callback diff --git a/docs/quick_tutorial/authentication/tutorial/views.py b/docs/quick_tutorial/authentication/tutorial/views.py index 240a23d3e..ab46eb2dd 100644 --- a/docs/quick_tutorial/authentication/tutorial/views.py +++ b/docs/quick_tutorial/authentication/tutorial/views.py @@ -1,4 +1,9 @@ from pyramid.httpexceptions import HTTPFound +from pyramid.security import ( + remember, + forget, + ) + from pyramid.view import ( view_config, view_defaults @@ -36,8 +41,9 @@ class TutorialViews: login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - request.remember_userid(login) - return HTTPFound(location=came_from) + headers = remember(request, login) + return HTTPFound(location=came_from, + headers=headers) message = 'Failed login' return dict( @@ -52,6 +58,7 @@ class TutorialViews: @view_config(route_name='logout') def logout(self): request = self.request - request.forget_userid() + headers = forget(request) url = request.route_url('home') - return HTTPFound(location=url) + return HTTPFound(location=url, + headers=headers) diff --git a/docs/quick_tutorial/authorization/tutorial/views.py b/docs/quick_tutorial/authorization/tutorial/views.py index 2ce2c37b4..43d14455a 100644 --- a/docs/quick_tutorial/authorization/tutorial/views.py +++ b/docs/quick_tutorial/authorization/tutorial/views.py @@ -1,4 +1,9 @@ from pyramid.httpexceptions import HTTPFound +from pyramid.security import ( + remember, + forget, + ) + from pyramid.view import ( view_config, view_defaults, @@ -38,8 +43,9 @@ class TutorialViews: login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - request.remember_userid(login) - return HTTPFound(location=came_from) + headers = remember(request, login) + return HTTPFound(location=came_from, + headers=headers) message = 'Failed login' return dict( @@ -54,6 +60,7 @@ class TutorialViews: @view_config(route_name='logout') def logout(self): request = self.request - request.forget_userid() + headers = forget(request) url = request.route_url('home') - return HTTPFound(location=url) + return HTTPFound(location=url, + headers=headers) diff --git a/docs/tutorials/wiki/authorization.rst b/docs/tutorials/wiki/authorization.rst index bba303d7f..62b1164e3 100644 --- a/docs/tutorials/wiki/authorization.rst +++ b/docs/tutorials/wiki/authorization.rst @@ -197,24 +197,24 @@ Add the following import statements to the head of ``tutorial/tutorial/views.py``: .. literalinclude:: src/authorization/tutorial/views.py - :lines: 6-11 + :lines: 6-13,15-17 :linenos: - :emphasize-lines: 3,6 + :emphasize-lines: 3,6-9,11 :language: python (Only the highlighted lines, with other necessary modifications, need to be added.) -:func:`~pyramid.view.forbidden_view_config` will be used +:meth:`~pyramid.view.forbidden_view_config` will be used to customize the default 403 Forbidden page. -:meth:`~pyramid.request.Request.remember_userid` and -:meth:`~pyramid.request.Request.forget_userid` help to create and +:meth:`~pyramid.security.remember` and +:meth:`~pyramid.security.forget` help to create and expire an auth ticket cookie. Now add the ``login`` and ``logout`` views: .. literalinclude:: src/authorization/tutorial/views.py - :lines: 76-102 + :lines: 82-120 :linenos: :language: python @@ -267,9 +267,8 @@ like this: (Only the highlighted line and a trailing comma on the preceding line need to be added.) -:attr:`~pyramid.request.Request.authenticated_userid` will return ``None`` -if the user is not authenticated, or a user id if the user is -authenticated. +The :meth:`pyramid.request.Request.authenticated_userid` will be ``None`` if +the user is not authenticated, or a user id if the user is authenticated. Add a "Logout" link when logged in ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -317,7 +316,7 @@ when we're done: .. literalinclude:: src/authorization/tutorial/views.py :linenos: - :emphasize-lines: 8,11,18,23,42,46,62,66,74,80,76-107 + :emphasize-lines: 8,11-15,17,24,29,48,52,68,72,80,82-120 :language: python (Only the highlighted lines need to be added.) diff --git a/docs/tutorials/wiki/src/authorization/tutorial/views.py b/docs/tutorials/wiki/src/authorization/tutorial/views.py index 57529ac8d..62e96e0e7 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/views.py +++ b/docs/tutorials/wiki/src/authorization/tutorial/views.py @@ -8,6 +8,12 @@ from pyramid.view import ( forbidden_view_config, ) +from pyramid.security import ( + remember, + forget, + ) + + from .security import USERS from .models import Page @@ -89,8 +95,9 @@ def login(request): login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - request.remember_userid(login) - return HTTPFound(location=came_from) + headers = remember(request, login) + return HTTPFound(location = came_from, + headers = headers) message = 'Failed login' return dict( @@ -103,5 +110,6 @@ def login(request): @view_config(context='.models.Wiki', name='logout') def logout(request): - request.forget_userid() - return HTTPFound(location=request.resource_url(request.context)) + headers = forget(request) + return HTTPFound(location = request.resource_url(request.context), + headers = headers) diff --git a/docs/tutorials/wiki/src/tests/tutorial/views.py b/docs/tutorials/wiki/src/tests/tutorial/views.py index 57529ac8d..62e96e0e7 100644 --- a/docs/tutorials/wiki/src/tests/tutorial/views.py +++ b/docs/tutorials/wiki/src/tests/tutorial/views.py @@ -8,6 +8,12 @@ from pyramid.view import ( forbidden_view_config, ) +from pyramid.security import ( + remember, + forget, + ) + + from .security import USERS from .models import Page @@ -89,8 +95,9 @@ def login(request): login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - request.remember_userid(login) - return HTTPFound(location=came_from) + headers = remember(request, login) + return HTTPFound(location = came_from, + headers = headers) message = 'Failed login' return dict( @@ -103,5 +110,6 @@ def login(request): @view_config(context='.models.Wiki', name='logout') def logout(request): - request.forget_userid() - return HTTPFound(location=request.resource_url(request.context)) + headers = forget(request) + return HTTPFound(location = request.resource_url(request.context), + headers = headers) diff --git a/docs/tutorials/wiki2/authorization.rst b/docs/tutorials/wiki2/authorization.rst index 830cb0277..1e5d0dcbf 100644 --- a/docs/tutorials/wiki2/authorization.rst +++ b/docs/tutorials/wiki2/authorization.rst @@ -221,23 +221,23 @@ Add the following import statements to the head of ``tutorial/tutorial/views.py``: .. literalinclude:: src/authorization/tutorial/views.py - :lines: 9-12,19 + :lines: 9-19 :linenos: - :emphasize-lines: 3,5 + :emphasize-lines: 3,6-9,11 :language: python (Only the highlighted lines need to be added.) -:func:`~pyramid.view.forbidden_view_config` will be used +:meth:`~pyramid.view.forbidden_view_config` will be used to customize the default 403 Forbidden page. -:meth:`~pyramid.request.Request.remember_userid` and -:meth:`~pyramid.request.Request.forget_userid` help to create and +:meth:`~pyramid.security.remember` and +:meth:`~pyramid.security.forget` help to create and expire an auth ticket cookie. Now add the ``login`` and ``logout`` views: .. literalinclude:: src/authorization/tutorial/views.py - :lines: 85-115 + :lines: 91-123 :linenos: :language: python @@ -289,7 +289,7 @@ like this: (Only the highlighted line needs to be added.) -The :attr:`~pyramid.request.Request.authenticated_userid` property will return +The :meth:`~pyramid.request.Request.authenticated_userid` property will be ``None`` if the user is not authenticated. Add a "Logout" link when logged in @@ -338,7 +338,7 @@ when we're done: .. literalinclude:: src/authorization/tutorial/views.py :linenos: - :emphasize-lines: 11,19,25,31,52,55,67,70,82,85-115 + :emphasize-lines: 11,14-19,25,31,37,58,61,73,76,88,91-117,119-123 :language: python (Only the highlighted lines need to be added.) diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/views.py b/docs/tutorials/wiki2/src/authorization/tutorial/views.py index 110d738c2..e954d5a31 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/views.py +++ b/docs/tutorials/wiki2/src/authorization/tutorial/views.py @@ -11,12 +11,18 @@ from pyramid.view import ( forbidden_view_config, ) +from pyramid.security import ( + remember, + forget, + ) + +from .security import USERS + from .models import ( DBSession, Page, ) -from .security import USERS # regular expression used to find WikiWords wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)") @@ -78,8 +84,8 @@ def edit_page(request): pagename=pagename)) return dict( page=page, - save_url = request.route_url('edit_page', pagename=pagename), - logged_in=request.authenticated_userid, + save_url=request.route_url('edit_page', pagename=pagename), + logged_in=request.authenticated_userid ) @view_config(route_name='login', renderer='templates/login.pt') @@ -97,8 +103,9 @@ def login(request): login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - request.remember_userid(login) - return HTTPFound(location = came_from) + headers = remember(request, login) + return HTTPFound(location = came_from, + headers = headers) message = 'Failed login' return dict( @@ -111,6 +118,7 @@ def login(request): @view_config(route_name='logout') def logout(request): - request.forget_userid() - return HTTPFound(location = request.route_url('view_wiki')) + headers = forget(request) + return HTTPFound(location = request.route_url('view_wiki'), + headers = headers) diff --git a/docs/tutorials/wiki2/src/tests/tutorial/views.py b/docs/tutorials/wiki2/src/tests/tutorial/views.py index 110d738c2..41bea4785 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/views.py +++ b/docs/tutorials/wiki2/src/tests/tutorial/views.py @@ -11,12 +11,18 @@ from pyramid.view import ( forbidden_view_config, ) +from pyramid.security import ( + remember, + forget, + ) + +from .security import USERS + from .models import ( DBSession, Page, ) -from .security import USERS # regular expression used to find WikiWords wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)") @@ -78,8 +84,8 @@ def edit_page(request): pagename=pagename)) return dict( page=page, - save_url = request.route_url('edit_page', pagename=pagename), - logged_in=request.authenticated_userid, + save_url=request.route_url('edit_page', pagename=pagename), + logged_in=request.authenticated_userid ) @view_config(route_name='login', renderer='templates/login.pt') @@ -97,8 +103,9 @@ def login(request): login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - request.remember_userid(login) - return HTTPFound(location = came_from) + headers = remember(request, login) + return HTTPFound(location = came_from, + headers = headers) message = 'Failed login' return dict( @@ -111,6 +118,6 @@ def login(request): @view_config(route_name='logout') def logout(request): - request.forget_userid() - return HTTPFound(location = request.route_url('view_wiki')) - + headers = forget(request) + return HTTPFound(location = request.route_url('view_wiki'), + headers = headers) -- cgit v1.2.3