Skip to content
This repository has been archived by the owner on Jul 21, 2022. It is now read-only.

Commit

Permalink
Cut down on doc strings now that proper documentation is written
Browse files Browse the repository at this point in the history
I could be convinced to bring them back, but still in a less limited format than before
  • Loading branch information
justanr committed Apr 15, 2018
1 parent e86d2e6 commit e21331e
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 101 deletions.
12 changes: 0 additions & 12 deletions src/flask_allows/allows.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,6 @@ def requires(self, *requirements, **opts):
"""
Decorator to enforce requirements on routes
.. code-block:: python
allows = Allows(app)
@app.route('/<username>/edit', methods=['GET', 'POST'])
@allows.requires(
IsAuthenticated(),
Or(IsSameUser(), CanEditUser())
)
def edit_user(username):
pass
:param requirements iterable: Collection of requirements
to impose on view
:param throws optional: Exception to throw for this route, if provided
Expand Down
51 changes: 12 additions & 39 deletions src/flask_allows/permission.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,19 @@


class Permission(object):
"""Permission works with the current instance of Allows to provide a context
for checking requirements. If the requirements are not met, an exception is
raised:
.. code-block:: Python
from flask_allows.permissions import Permission
from myrequirements import IsAdmin
def some_function():
with Permission(IsAdmin()):
return "Awesome!"
By default, Permission will delegate to the current Allows instance for
identity loading, however, an explicit identity can be provided by passing
an identity keyword.
.. code-block:: Python
with Permission(IsAdmin(), identity=user):
print("Doing the thing...")
Permission also delegates to the current Allows instance for determining
what exception to throw. But by providing an exception with the `throws`
keyword, it can be overriden:
.. code-block:: Python
with Permission(IsAdmin(), throws=Forbidden("You ain't no admin!")):
print("Happy message board adminstrator day!")
In addition to being a context manager, Permission can be used as a boolean
as well. In this case, Permission does not raise an exception if the
requirements are not met.
.. code-block:: Python
if Permission(IsAdmin()):
add_admin_stuff_to_response()
"""
Used to check requirements as a boolean or context manager.
:param requirements iterable: Collection of requirements to check against
:param throws optional: Exception to throw when used as a context manager,
if provided it takes precedence over the exception stored on the current
application's registered :class:`~flask_allows.allows.Allows` instance
:param on_fail optional: Value or function to use as the on_fail when used
as a context manager, if provided takes precedence over the on_fail
configured on current application's registered
:class:`~flask_allows.allows.Allows` instance
"""

def __init__(self, *requirements, **opts):
self.ext = _allows._get_current_object()
self.requirements = requirements
Expand Down
62 changes: 12 additions & 50 deletions src/flask_allows/requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@


class Requirement(with_metaclass(ABCMeta)):
"""Base for object based Requirements in Flask-Allows. This is quite
"""
Base for object based Requirements in Flask-Allows. This is quite
useful for requirements that have complex logic that is too much to fit
inside of a single function.
"""
Expand All @@ -20,64 +21,25 @@ def __repr__(self):


class ConditionalRequirement(Requirement):
"""ConditionalRequirement allows settings up very complex requirements such
as: Is this user authenticated *and* is the request a read only method, *or*
is the user an adminstrator, or is the user a moderator *and* the user is
assigned to this section? Such a complex requirement can be difficult to
write as a *single* requirement, but instead ConditionalRequirement can
compose individual permissions into a more complex permission:
.. code-block:: python
from mypermissions import IsAdmin, IsModerator, Authenticated, ReadOnly
from flask_allows import And, Or
"""
Used to combine requirements together in ways other than all-or-nothing,
such as with an or-reducer (any requirement must be True)::
complex = Or(IsAdmin(), IsModerator(), And(Authenticated(), ReadOnly()))
from flask_allows import Or
ConditionalRequirement also supports the concept of `Not` as well.
requires(Or(user_is_admin, user_is_moderator))
.. code-block:: python
or negating a requirement::
from mypermissions import IsBanned
from flask_allows import Not
@requires(Not(IsBanned()))
There are also shortcuts to each of these once a requirement is wrapped
inside a conditional requirement:
.. code-block:: python
from flask_allows import C, And, Or, Not
from mypermissions import IsAuthenticated, ReadOnly
Or(IsAuthenticated(), ReadOnly())
C(IsAuthenticated()) | C(ReadOnly())
requires(Not(user_logged_in))
And(IsAuthenticated(), ReadOnly())
C(IsAuthenticated) & C(ReadOnly)
Combinations may also nested::
Not(IsAuthenticated())
~C(IsAuthenticated())
ConditionalRequirement is also extensible to support any function that
accepts two boolean arguments and returns a boolean. For example, a Xor
condition can be represented as:
.. code-block:: python
Xored(IsAuthenticated(), ReadOnly(), op=operator.xor)
And these custom conditional can be negated as well by passing True to the
negated keyword.
Finally, ConditionalRequirement can be instructed to only check requirements
until a certain result is returned by passing the `until` keyword with
either `True` or `False`.
And, Or and Not are implemented by simply passing different keyword
arguments, instead of subclassing.
Or(user_is_admin, And(user_is_moderator, HasPermission('view_admin')))
"""

def __init__(self, *requirements, **kwargs):
self.requirements = requirements
self.op = kwargs.get('op', operator.and_)
Expand Down

0 comments on commit e21331e

Please sign in to comment.