/usr/lib/python2.7/dist-packages/pyramid/security.py is in python-pyramid 1.6+dfsg-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 | from zope.deprecation import deprecated
from zope.interface import providedBy
from pyramid.interfaces import (
IAuthenticationPolicy,
IAuthorizationPolicy,
ISecuredView,
IView,
IViewClassifier,
)
from pyramid.compat import map_
from pyramid.threadlocal import get_current_registry
Everyone = 'system.Everyone'
Authenticated = 'system.Authenticated'
Allow = 'Allow'
Deny = 'Deny'
_marker = object()
class AllPermissionsList(object):
""" Stand in 'permission list' to represent all permissions """
def __iter__(self):
return ()
def __contains__(self, other):
return True
def __eq__(self, other):
return isinstance(other, self.__class__)
ALL_PERMISSIONS = AllPermissionsList()
DENY_ALL = (Deny, Everyone, ALL_PERMISSIONS)
NO_PERMISSION_REQUIRED = '__no_permission_required__'
def _get_registry(request):
try:
reg = request.registry
except AttributeError:
reg = get_current_registry() # b/c
return reg
def _get_authentication_policy(request):
registry = _get_registry(request)
return registry.queryUtility(IAuthenticationPolicy)
def has_permission(permission, context, request):
"""
A function that calls :meth:`pyramid.request.Request.has_permission`
and returns its result.
.. deprecated:: 1.5
Use :meth:`pyramid.request.Request.has_permission` instead.
.. versionchanged:: 1.5a3
If context is None, then attempt to use the context attribute of self;
if not set, then the AttributeError is propagated.
"""
return request.has_permission(permission, context)
deprecated(
'has_permission',
'As of Pyramid 1.5 the "pyramid.security.has_permission" API is now '
'deprecated. It will be removed in Pyramid 1.8. Use the '
'"has_permission" method of the Pyramid request instead.'
)
def authenticated_userid(request):
"""
A function that returns the value of the property
:attr:`pyramid.request.Request.authenticated_userid`.
.. deprecated:: 1.5
Use :attr:`pyramid.request.Request.authenticated_userid` instead.
"""
return request.authenticated_userid
deprecated(
'authenticated_userid',
'As of Pyramid 1.5 the "pyramid.security.authenticated_userid" API is now '
'deprecated. It will be removed in Pyramid 1.8. Use the '
'"authenticated_userid" attribute of the Pyramid request instead.'
)
def unauthenticated_userid(request):
"""
A function that returns the value of the property
:attr:`pyramid.request.Request.unauthenticated_userid`.
.. deprecated:: 1.5
Use :attr:`pyramid.request.Request.unauthenticated_userid` instead.
"""
return request.unauthenticated_userid
deprecated(
'unauthenticated_userid',
'As of Pyramid 1.5 the "pyramid.security.unauthenticated_userid" API is '
'now deprecated. It will be removed in Pyramid 1.8. Use the '
'"unauthenticated_userid" attribute of the Pyramid request instead.'
)
def effective_principals(request):
"""
A function that returns the value of the property
:attr:`pyramid.request.Request.effective_principals`.
.. deprecated:: 1.5
Use :attr:`pyramid.request.Request.effective_principals` instead.
"""
return request.effective_principals
deprecated(
'effective_principals',
'As of Pyramid 1.5 the "pyramid.security.effective_principals" API is '
'now deprecated. It will be removed in Pyramid 1.8. Use the '
'"effective_principals" attribute of the Pyramid request instead.'
)
def remember(request, userid=_marker, **kw):
"""
Returns a sequence of header tuples (e.g. ``[('Set-Cookie', 'foo=abc')]``)
on this request's response.
These headers are suitable for 'remembering' a set of credentials
implied by the data passed as ``userid`` and ``*kw`` using the
current :term:`authentication policy`. Common usage might look
like so within the body of a view function (``response`` is
assumed to be a :term:`WebOb` -style :term:`response` object
computed previously by the view code):
.. code-block:: python
from pyramid.security import remember
headers = remember(request, 'chrism', password='123', max_age='86400')
response = request.response
response.headerlist.extend(headers)
return response
If no :term:`authentication policy` is in use, this function will
always return an empty sequence. If used, the composition and
meaning of ``**kw`` must be agreed upon by the calling code and
the effective authentication policy.
.. deprecated:: 1.6
Renamed the ``principal`` argument to ``userid`` to clarify its
purpose.
"""
if userid is _marker:
principal = kw.pop('principal', _marker)
if principal is _marker:
raise TypeError(
'remember() missing 1 required positional argument: '
'\'userid\'')
else:
deprecated(
'principal',
'The "principal" argument was deprecated in Pyramid 1.6. '
'It will be removed in Pyramid 1.9. Use the "userid" '
'argument instead.')
userid = principal
policy = _get_authentication_policy(request)
if policy is None:
return []
return policy.remember(request, userid, **kw)
def forget(request):
"""
Return a sequence of header tuples (e.g. ``[('Set-Cookie',
'foo=abc')]``) suitable for 'forgetting' the set of credentials
possessed by the currently authenticated user. A common usage
might look like so within the body of a view function
(``response`` is assumed to be an :term:`WebOb` -style
:term:`response` object computed previously by the view code):
.. code-block:: python
from pyramid.security import forget
headers = forget(request)
response.headerlist.extend(headers)
return response
If no :term:`authentication policy` is in use, this function will
always return an empty sequence.
"""
policy = _get_authentication_policy(request)
if policy is None:
return []
return policy.forget(request)
def principals_allowed_by_permission(context, permission):
""" Provided a ``context`` (a resource object), and a ``permission``
(a string or unicode object), if a :term:`authorization policy` is
in effect, return a sequence of :term:`principal` ids that possess
the permission in the ``context``. If no authorization policy is
in effect, this will return a sequence with the single value
:mod:`pyramid.security.Everyone` (the special principal
identifier representing all principals).
.. note::
even if an :term:`authorization policy` is in effect,
some (exotic) authorization policies may not implement the
required machinery for this function; those will cause a
:exc:`NotImplementedError` exception to be raised when this
function is invoked.
"""
reg = get_current_registry()
policy = reg.queryUtility(IAuthorizationPolicy)
if policy is None:
return [Everyone]
return policy.principals_allowed_by_permission(context, permission)
def view_execution_permitted(context, request, name=''):
""" If the view specified by ``context`` and ``name`` is protected
by a :term:`permission`, check the permission associated with the
view using the effective authentication/authorization policies and
the ``request``. Return a boolean result. If no
:term:`authorization policy` is in effect, or if the view is not
protected by a permission, return ``True``. If no view can view found,
an exception will be raised.
.. versionchanged:: 1.4a4
An exception is raised if no view is found.
"""
reg = _get_registry(request)
provides = [IViewClassifier] + map_(providedBy, (request, context))
# XXX not sure what to do here about using _find_views or analogue;
# for now let's just keep it as-is
view = reg.adapters.lookup(provides, ISecuredView, name=name)
if view is None:
view = reg.adapters.lookup(provides, IView, name=name)
if view is None:
raise TypeError('No registered view satisfies the constraints. '
'It would not make sense to claim that this view '
'"is" or "is not" permitted.')
return Allowed(
'Allowed: view name %r in context %r (no permission defined)' %
(name, context))
return view.__permitted__(context, request)
class PermitsResult(int):
def __new__(cls, s, *args):
inst = int.__new__(cls, cls.boolval)
inst.s = s
inst.args = args
return inst
@property
def msg(self):
return self.s % self.args
def __str__(self):
return self.msg
def __repr__(self):
return '<%s instance at %s with msg %r>' % (self.__class__.__name__,
id(self),
self.msg)
class Denied(PermitsResult):
""" An instance of ``Denied`` is returned when a security-related
API or other :app:`Pyramid` code denies an action unrelated to
an ACL check. It evaluates equal to all boolean false types. It
has an attribute named ``msg`` describing the circumstances for
the deny."""
boolval = 0
class Allowed(PermitsResult):
""" An instance of ``Allowed`` is returned when a security-related
API or other :app:`Pyramid` code allows an action unrelated to
an ACL check. It evaluates equal to all boolean true types. It
has an attribute named ``msg`` describing the circumstances for
the allow."""
boolval = 1
class ACLPermitsResult(int):
def __new__(cls, ace, acl, permission, principals, context):
inst = int.__new__(cls, cls.boolval)
inst.permission = permission
inst.ace = ace
inst.acl = acl
inst.principals = principals
inst.context = context
return inst
@property
def msg(self):
s = ('%s permission %r via ACE %r in ACL %r on context %r for '
'principals %r')
return s % (self.__class__.__name__,
self.permission,
self.ace,
self.acl,
self.context,
self.principals)
def __str__(self):
return self.msg
def __repr__(self):
return '<%s instance at %s with msg %r>' % (self.__class__.__name__,
id(self),
self.msg)
class ACLDenied(ACLPermitsResult):
""" An instance of ``ACLDenied`` represents that a security check made
explicitly against ACL was denied. It evaluates equal to all boolean
false types. It also has the following attributes: ``acl``, ``ace``,
``permission``, ``principals``, and ``context``. These attributes
indicate the security values involved in the request. Its __str__ method
prints a summary of these attributes for debugging purposes. The same
summary is available as the ``msg`` attribute."""
boolval = 0
class ACLAllowed(ACLPermitsResult):
""" An instance of ``ACLAllowed`` represents that a security check made
explicitly against ACL was allowed. It evaluates equal to all boolean
true types. It also has the following attributes: ``acl``, ``ace``,
``permission``, ``principals``, and ``context``. These attributes
indicate the security values involved in the request. Its __str__ method
prints a summary of these attributes for debugging purposes. The same
summary is available as the ``msg`` attribute."""
boolval = 1
class AuthenticationAPIMixin(object):
def _get_authentication_policy(self):
reg = _get_registry(self)
return reg.queryUtility(IAuthenticationPolicy)
@property
def authenticated_userid(self):
""" Return 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.
.. versionadded:: 1.5
"""
policy = self._get_authentication_policy()
if policy is None:
return None
return policy.authenticated_userid(self)
@property
def unauthenticated_userid(self):
""" Return an object 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
: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.
.. versionadded:: 1.5
"""
policy = self._get_authentication_policy()
if policy is None:
return None
return policy.unauthenticated_userid(self)
@property
def effective_principals(self):
""" Return the list of 'effective' :term:`principal` identifiers
for the ``request``. If no :term:`authentication policy` is in effect,
this will return a one-element list containing the
:data:`pyramid.security.Everyone` principal.
.. versionadded:: 1.5
"""
policy = self._get_authentication_policy()
if policy is None:
return [Everyone]
return policy.effective_principals(self)
class AuthorizationAPIMixin(object):
def has_permission(self, permission, context=None):
""" Given a permission and an optional context, returns an instance of
:data:`pyramid.security.Allowed` if the permission is granted to this
request with the provided context, or the context already associated
with the request. Otherwise, returns an instance of
:data:`pyramid.security.Denied`. This method delegates to the current
authentication and authorization policies. Returns
:data:`pyramid.security.Allowed` unconditionally if no authentication
policy has been registered for this request. If ``context`` is not
supplied or is supplied as ``None``, the context used is the
``request.context`` attribute.
:param permission: Does this request have the given permission?
:type permission: unicode, str
:param context: A resource object or ``None``
:type context: object
:returns: `pyramid.security.PermitsResult`
.. versionadded:: 1.5
"""
if context is None:
context = self.context
reg = _get_registry(self)
authn_policy = reg.queryUtility(IAuthenticationPolicy)
if authn_policy is None:
return Allowed('No authentication policy in use.')
authz_policy = reg.queryUtility(IAuthorizationPolicy)
if authz_policy is None:
raise ValueError('Authentication policy registered without '
'authorization policy') # should never happen
principals = authn_policy.effective_principals(self)
return authz_policy.permits(context, principals, permission)
|