summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pyramid/config/actions.py2
-rw-r--r--src/pyramid/config/security.py25
-rw-r--r--src/pyramid/config/tweens.py2
-rw-r--r--src/pyramid/config/views.py4
-rw-r--r--src/pyramid/csrf.py18
-rw-r--r--src/pyramid/httpexceptions.py8
-rw-r--r--src/pyramid/interfaces.py10
-rw-r--r--src/pyramid/router.py5
-rw-r--r--src/pyramid/scripts/prequest.py2
-rw-r--r--src/pyramid/scripts/proutes.py10
-rw-r--r--src/pyramid/testing.py2
-rw-r--r--src/pyramid/view.py18
-rw-r--r--src/pyramid/viewderivers.py6
13 files changed, 77 insertions, 35 deletions
diff --git a/src/pyramid/config/actions.py b/src/pyramid/config/actions.py
index 4a526e242..29d06d716 100644
--- a/src/pyramid/config/actions.py
+++ b/src/pyramid/config/actions.py
@@ -168,7 +168,7 @@ class ActionState(object):
Return True if processing is needed and False otherwise. If
the callable needs to be processed, it will be marked as
- processed, assuming that the caller will procces the callable if
+ processed, assuming that the caller will process the callable if
it needs to be processed.
"""
if spec in self._seen_files:
diff --git a/src/pyramid/config/security.py b/src/pyramid/config/security.py
index 8f0a108c5..32b4db03c 100644
--- a/src/pyramid/config/security.py
+++ b/src/pyramid/config/security.py
@@ -254,6 +254,7 @@ class SecurityConfiguratorMixin(object):
token='csrf_token',
header='X-CSRF-Token',
safe_methods=('GET', 'HEAD', 'OPTIONS', 'TRACE'),
+ allow_no_origin=False,
callback=None,
):
"""
@@ -278,6 +279,9 @@ class SecurityConfiguratorMixin(object):
never be automatically checked for CSRF tokens.
Default: ``('GET', 'HEAD', 'OPTIONS', TRACE')``.
+ ``allow_no_origin`` is a boolean. If false, a request lacking both an
+ ``Origin`` and ``Referer`` header will fail the CSRF check.
+
If ``callback`` is set, it must be a callable accepting ``(request)``
and returning ``True`` if the request should be checked for a valid
CSRF token. This callback allows an application to support
@@ -293,9 +297,17 @@ class SecurityConfiguratorMixin(object):
.. versionchanged:: 1.8
Added the ``callback`` option.
+ .. versionchanged:: 2.0
+ Added the ``allow_no_origin`` option.
+
"""
options = DefaultCSRFOptions(
- require_csrf, token, header, safe_methods, callback
+ require_csrf=require_csrf,
+ token=token,
+ header=header,
+ safe_methods=safe_methods,
+ allow_no_origin=allow_no_origin,
+ callback=callback,
)
def register():
@@ -344,9 +356,18 @@ class SecurityConfiguratorMixin(object):
@implementer(IDefaultCSRFOptions)
class DefaultCSRFOptions(object):
- def __init__(self, require_csrf, token, header, safe_methods, callback):
+ def __init__(
+ self,
+ require_csrf,
+ token,
+ header,
+ safe_methods,
+ allow_no_origin,
+ callback,
+ ):
self.require_csrf = require_csrf
self.token = token
self.header = header
self.safe_methods = frozenset(safe_methods)
+ self.allow_no_origin = allow_no_origin
self.callback = callback
diff --git a/src/pyramid/config/tweens.py b/src/pyramid/config/tweens.py
index c85639d14..feb4a3230 100644
--- a/src/pyramid/config/tweens.py
+++ b/src/pyramid/config/tweens.py
@@ -73,7 +73,7 @@ class TweensConfiguratorMixin(object):
If all options for ``under`` (or ``over``) cannot be found in the
current configuration, it is an error. If some options are specified
- purely for compatibilty with other tweens, just add a fallback of
+ purely for compatibility with other tweens, just add a fallback of
MAIN or INGRESS. For example, ``under=('mypkg.someothertween',
'mypkg.someothertween2', INGRESS)``. This constraint will require
the tween to be located under both the 'mypkg.someothertween' tween,
diff --git a/src/pyramid/config/views.py b/src/pyramid/config/views.py
index ac531ecb2..1abff0579 100644
--- a/src/pyramid/config/views.py
+++ b/src/pyramid/config/views.py
@@ -751,7 +751,7 @@ class ViewsConfiguratorMixin(object):
It's useful when you want to always potentially show a view when some
object is traversed to, but you can't be sure about what kind of
object it will be, so you can't use the ``context`` predicate. The
- individual path elements inbetween slash characters or in tuple
+ individual path elements in between slash characters or in tuple
elements should be the Unicode representation of the name of the
resource and should not be encoded in any way.
@@ -859,7 +859,7 @@ class ViewsConfiguratorMixin(object):
else:
raise ConfigurationError(
- '"view" was not specified and ' 'no "renderer" specified'
+ '"view" was not specified and no "renderer" specified'
)
if request_type is not None:
diff --git a/src/pyramid/csrf.py b/src/pyramid/csrf.py
index 26c628acc..b352ada71 100644
--- a/src/pyramid/csrf.py
+++ b/src/pyramid/csrf.py
@@ -97,9 +97,9 @@ class SessionCSRFStoragePolicy(object):
class CookieCSRFStoragePolicy(object):
""" An alternative CSRF implementation that stores its information in
unauthenticated cookies, known as the 'Double Submit Cookie' method in the
- `OWASP CSRF guidelines <https://www.owasp.org/index.php/
- Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#
- Double_Submit_Cookie>`_. This gives some additional flexibility with
+ `OWASP CSRF guidelines
+ <https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#double-submit-cookie>`_.
+ This gives some additional flexibility with
regards to scaling as the tokens can be generated and verified by a
front-end server.
@@ -247,7 +247,9 @@ def check_csrf_token(
return True
-def check_csrf_origin(request, trusted_origins=None, raises=True):
+def check_csrf_origin(
+ request, trusted_origins=None, allow_no_origin=False, raises=True
+):
"""
Check the ``Origin`` of the request to see if it is a cross site request or
not.
@@ -302,9 +304,13 @@ def check_csrf_origin(request, trusted_origins=None, raises=True):
if origin is None:
origin = request.referrer
- # Fail if we were not able to locate an origin at all
+ # If we can't find an origin, fail or pass immediately depending on
+ # ``allow_no_origin``
if not origin:
- return _fail("Origin checking failed - no Origin or Referer.")
+ if allow_no_origin:
+ return True
+ else:
+ return _fail("Origin checking failed - no Origin or Referer.")
# Parse our origin so we we can extract the required information from
# it.
diff --git a/src/pyramid/httpexceptions.py b/src/pyramid/httpexceptions.py
index 56797dc88..c9fdfe04b 100644
--- a/src/pyramid/httpexceptions.py
+++ b/src/pyramid/httpexceptions.py
@@ -367,7 +367,7 @@ class HTTPRedirection(HTTPException):
This is an abstract base class for 3xx redirection. It indicates
that further action needs to be taken by the user agent in order
- to fulfill the request. It does not necessarly signal an error
+ to fulfill the request. It does not necessarily signal an error
condition.
"""
@@ -914,9 +914,7 @@ class HTTPConflict(HTTPClientError):
code = 409
title = 'Conflict'
- explanation = (
- 'There was a conflict when trying to complete ' 'your request.'
- )
+ explanation = 'There was a conflict when trying to complete your request.'
class HTTPGone(HTTPClientError):
@@ -1040,7 +1038,7 @@ class HTTPExpectationFailed(HTTPClientError):
"""
subclass of :class:`~HTTPClientError`
- This indidcates that the expectation given in an Expect
+ This indicates that the expectation given in an Expect
request-header field could not be met by this server.
code: 417, title: Expectation Failed
diff --git a/src/pyramid/interfaces.py b/src/pyramid/interfaces.py
index d97c3811b..2d8b1ac40 100644
--- a/src/pyramid/interfaces.py
+++ b/src/pyramid/interfaces.py
@@ -426,7 +426,7 @@ class IRendererInfo(Interface):
)
type = Attribute('The renderer type name')
registry = Attribute(
- 'The "current" application registry when the ' 'renderer was created'
+ 'The "current" application registry when the renderer was created'
)
settings = Attribute(
'The deployment settings dictionary related '
@@ -1100,6 +1100,10 @@ class IDefaultCSRFOptions(Interface):
header = Attribute('The header to be matched with the CSRF token.')
safe_methods = Attribute('A set of safe methods that skip CSRF checks.')
callback = Attribute('A callback to disable CSRF checks per-request.')
+ allow_no_origin = Attribute(
+ 'Boolean. If false, a request lacking both an ``Origin`` and '
+ '``Referer`` header will fail the CSRF check.'
+ )
class ISessionFactory(Interface):
@@ -1319,7 +1323,7 @@ class IIntrospectable(Interface):
)
category_name = Attribute('introspection category name')
discriminator = Attribute(
- 'introspectable discriminator (within category) ' '(must be hashable)'
+ 'introspectable discriminator (within category) (must be hashable)'
)
discriminator_hash = Attribute('an integer hash of the discriminator')
action_info = Attribute(
@@ -1460,7 +1464,7 @@ class IViewDeriverInfo(Interface):
:term:`view deriver` during configuration."""
registry = Attribute(
- 'The "current" application registry where the ' 'view was created'
+ 'The "current" application registry where the view was created'
)
package = Attribute(
'The "current package" where the view '
diff --git a/src/pyramid/router.py b/src/pyramid/router.py
index 19641aecd..fa1a9ebf7 100644
--- a/src/pyramid/router.py
+++ b/src/pyramid/router.py
@@ -273,7 +273,4 @@ class Router(object):
def default_execution_policy(environ, router):
with router.request_context(environ) as request:
- try:
- return router.invoke_request(request)
- except Exception:
- return request.invoke_exception_view(reraise=True)
+ return router.invoke_request(request)
diff --git a/src/pyramid/scripts/prequest.py b/src/pyramid/scripts/prequest.py
index eb2032419..759978936 100644
--- a/src/pyramid/scripts/prequest.py
+++ b/src/pyramid/scripts/prequest.py
@@ -18,7 +18,7 @@ class PRequestCommand(object):
description = """\
Submit a HTTP request to a web application.
- This command makes an artifical request to a web application that uses a
+ This command makes an artificial request to a web application that uses a
PasteDeploy (.ini) configuration file for the server and application.
Use "prequest config.ini /path" to request "/path".
diff --git a/src/pyramid/scripts/proutes.py b/src/pyramid/scripts/proutes.py
index 78c2295d5..09b550cef 100644
--- a/src/pyramid/scripts/proutes.py
+++ b/src/pyramid/scripts/proutes.py
@@ -268,9 +268,11 @@ class PRoutesCommand(object):
'config_vars',
nargs='*',
default=(),
- help="Variables required by the config file. For example, "
- "`http_port=%%(http_port)s` would expect `http_port=8080` to be "
- "passed here.",
+ help=(
+ "Variables required by the config file. For example, "
+ "`http_port=%%(http_port)s` would expect `http_port=8080` to be "
+ "passed here."
+ ),
)
def __init__(self, argv, quiet=False):
@@ -285,7 +287,7 @@ class PRoutesCommand(object):
if fmt not in self.available_formats:
invalid_formats.append(fmt)
- msg = 'You provided invalid formats %s, ' 'Available formats are %s'
+ msg = 'You provided invalid formats %s. Available formats are %s'
if invalid_formats:
msg = msg % (invalid_formats, self.available_formats)
diff --git a/src/pyramid/testing.py b/src/pyramid/testing.py
index 4bf6d281f..3bf3f1898 100644
--- a/src/pyramid/testing.py
+++ b/src/pyramid/testing.py
@@ -154,7 +154,7 @@ class DummyResource:
should be an interface object or tuple of interface objects
that will be attached to the resulting resource via
:func:`zope.interface.alsoProvides`. Any extra keywords passed
- in the ``kw`` argumnent will be set as direct attributes of
+ in the ``kw`` argument will be set as direct attributes of
the resource object.
.. note:: For backwards compatibility purposes, this class can also
diff --git a/src/pyramid/view.py b/src/pyramid/view.py
index 944ad93ea..7e54a40f6 100644
--- a/src/pyramid/view.py
+++ b/src/pyramid/view.py
@@ -1,5 +1,6 @@
import itertools
import sys
+import inspect
import venusian
@@ -216,6 +217,14 @@ class view_config(object):
if settings.get('context') is None:
settings['context'] = settings['for_']
self.__dict__.update(settings)
+ self._get_info()
+
+ def _get_info(self):
+ depth = self.__dict__.get('_depth', 0)
+ frame = sys._getframe(depth + 2)
+ frameinfo = inspect.getframeinfo(frame)
+ sourceline = frameinfo[3][0].strip()
+ self._info = frameinfo[0], frameinfo[1], frameinfo[2], sourceline
def __call__(self, wrapped):
settings = self.__dict__.copy()
@@ -237,14 +246,13 @@ class view_config(object):
if settings.get('attr') is None:
settings['attr'] = wrapped.__name__
- settings['_info'] = info.codeinfo # fbo "action_method"
return wrapped
bfg_view = view_config # bw compat (forever)
-class view_defaults(view_config):
+def view_defaults(**settings):
""" A class :term:`decorator` which, when applied to a class, will
provide defaults for all view configurations that use the class. This
decorator accepts all the arguments accepted by
@@ -253,10 +261,12 @@ class view_defaults(view_config):
See :ref:`view_defaults` for more information.
"""
- def __call__(self, wrapped):
- wrapped.__view_defaults__ = self.__dict__.copy()
+ def wrap(wrapped):
+ wrapped.__view_defaults__ = settings
return wrapped
+ return wrap
+
class AppendSlashNotFoundViewFactory(object):
""" There can only be one :term:`Not Found view` in any
diff --git a/src/pyramid/viewderivers.py b/src/pyramid/viewderivers.py
index 22659d2a3..95c223e61 100644
--- a/src/pyramid/viewderivers.py
+++ b/src/pyramid/viewderivers.py
@@ -484,12 +484,14 @@ def csrf_view(view, info):
token = 'csrf_token'
header = 'X-CSRF-Token'
safe_methods = frozenset(["GET", "HEAD", "OPTIONS", "TRACE"])
+ allow_no_origin = False
callback = None
else:
default_val = defaults.require_csrf
token = defaults.token
header = defaults.header
safe_methods = defaults.safe_methods
+ allow_no_origin = defaults.allow_no_origin
callback = defaults.callback
enabled = (
@@ -508,7 +510,9 @@ def csrf_view(view, info):
if request.method not in safe_methods and (
callback is None or callback(request)
):
- check_csrf_origin(request, raises=True)
+ check_csrf_origin(
+ request, raises=True, allow_no_origin=allow_no_origin
+ )
check_csrf_token(request, token, header, raises=True)
return view(context, request)