Skip to content

Commit

Permalink
fix secured views to avoid being applied to exception views
Browse files Browse the repository at this point in the history
  • Loading branch information
mmerickel committed Jan 29, 2024
1 parent 55f9eb0 commit 6c00625
Showing 1 changed file with 70 additions and 60 deletions.
130 changes: 70 additions & 60 deletions src/pyramid/viewderivers.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,90 +293,100 @@ def secured_view(view, info):


def _secured_view(view, info):
permission = explicit_val = info.options.get('permission')
if permission is None:
permission = info.options.get('permission')

if not info.exception_only and permission is None:
# no permission is specified on the view so we pull in the default
# permission - however if this is an exception view then we do not want
# to inherit the default permission by definition
permission = info.registry.queryUtility(IDefaultPermission)

if permission == NO_PERMISSION_REQUIRED:
# allow views registered within configurations that have a
# default permission to explicitly override the default
# permission, replacing it with no permission at all
permission = None

policy = info.registry.queryUtility(ISecurityPolicy)

# no-op on exception-only views without an explicit permission
if explicit_val is None and info.exception_only:
if policy is None or permission is None:
# all security is disabled on this view if no policy or permission
return view

if policy and (permission is not None):
def permitted(context, request):
return policy.permits(request, context, permission)

def permitted(context, request):
return policy.permits(request, context, permission)
def secured_view(context, request):
result = permitted(context, request)
if result:
return view(context, request)
view_name = getattr(view, '__name__', view)
msg = getattr(
request,
'authdebug_message',
'Unauthorized: %s failed permission check' % view_name,
)
raise HTTPForbidden(msg, result=result)

def secured_view(context, request):
result = permitted(context, request)
if result:
return view(context, request)
view_name = getattr(view, '__name__', view)
msg = getattr(
request,
'authdebug_message',
'Unauthorized: %s failed permission check' % view_name,
)
raise HTTPForbidden(msg, result=result)

secured_view.__call_permissive__ = view
secured_view.__permitted__ = permitted
secured_view.__permission__ = permission
return secured_view
else:
return view
secured_view.__call_permissive__ = view
secured_view.__permitted__ = permitted
secured_view.__permission__ = permission
return secured_view


def _authdebug_view(view, info):
wrapped_view = view
# XXX this view logic is slightly different from the _secured_view above
# because we want it to run in more situations than _secured_view - we are
# trying to log helpful info about basically any view that is executed -
# basically we only skip it if it's a default exception view with no
# special permissions

settings = info.settings
permission = explicit_val = info.options.get('permission')
if permission is None:
permission = info.registry.queryUtility(IDefaultPermission)
policy = info.registry.queryUtility(ISecurityPolicy)
logger = info.registry.queryUtility(IDebugLogger)
if not settings or not settings.get('debug_authorization', False):
# no-op if debug_authorization is disabled
return view

# no-op on exception-only views without an explicit permission
if explicit_val is None and info.exception_only:
permission = info.options.get('permission')

if info.exception_only and (
permission is None or permission == NO_PERMISSION_REQUIRED
):
# no logging on any exception views with no permissions (the default)
return view

if settings and settings.get('debug_authorization', False):
if permission is None:
# allow views registered within configurations that have a
# default permission to explicitly override the default
# permission, replacing it with no permission at all
permission = info.registry.queryUtility(IDefaultPermission)

def authdebug_view(context, request):
view_name = getattr(request, 'view_name', None)
policy = info.registry.queryUtility(ISecurityPolicy)
logger = info.registry.queryUtility(IDebugLogger)

if policy:
if permission is NO_PERMISSION_REQUIRED:
msg = 'Allowed (NO_PERMISSION_REQUIRED)'
elif permission is None:
msg = 'Allowed (no permission registered)'
else:
result = policy.permits(request, context, permission)
msg = str(result)
def authdebug_view(context, request):
if policy:
if permission is NO_PERMISSION_REQUIRED:
msg = 'Allowed (NO_PERMISSION_REQUIRED)'
elif permission is None:
msg = 'Allowed (no permission registered)'
else:
msg = 'Allowed (no security policy in use)'

view_name = getattr(request, 'view_name', None)
url = getattr(request, 'url', None)
msg = (
'debug_authorization of url %s (view name %r against '
'context %r): %s' % (url, view_name, context, msg)
)
if logger:
logger.debug(msg)
if request is not None:
request.authdebug_message = msg
return view(context, request)
result = policy.permits(request, context, permission)
msg = str(result)
else:
msg = 'Allowed (no security policy in use)'

wrapped_view = authdebug_view
view_name = getattr(request, 'view_name', None)
url = getattr(request, 'url', None)
msg = (
'debug_authorization of url %s (view name %r against '
'context %r): %s' % (url, view_name, context, msg)
)
if logger:
logger.debug(msg)
if request is not None:
request.authdebug_message = msg
return view(context, request)

return wrapped_view
return authdebug_view


def rendered_view(view, info):
Expand Down

0 comments on commit 6c00625

Please sign in to comment.