Metadata-Version: 2.1
Name: django-churlish
Version: 0.1.0
Summary: URL configuration via runtime database objects
Author: Keryn Knight
Author-email: python-package@kerynknight.com
License: BSD License
Keywords: django urls
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Framework :: Django
Classifier: Natural Language :: English
Classifier: Environment :: Web Environment
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
License-File: LICENSE
Requires-Dist: Django>=1.4.11
Requires-Dist: django-model-utils>=2.0

===============
django-churlish
===============

A URLish way to handle enabling or locking down certain things.

Based around the idea that a URL represents, ideally, a namespace of children.

If you've ever wanted to be able to do something like::

    url('xyz/', login_required(include('my.urlconf')))

easily, or in a dynamic way, this might be interesting.

Provides a single Django Middleware, with which *partial* middlewares may be
applied to a request based on the ``request.path``.

Provides partials out-of-the-box for:

* Marking a URL (and it's descendants) as unpublished.
* Marking a URL (and it's descendants) as a redirect, before the view itself
  is called, rather than after as with ``django.contrib.redirects``
* Marking a URL (and it's descendants) as requiring login, or staff,
  or superuser status.
* Marking a URL (and it's descendants) as only available for specific users.
* Marking a URL (and it's descendants) as only available for specific groups.

Partials explanation
--------------------

Conceptually, the middleware partials are somewhat like
`Django REST Framework's`_ concept of `Permission classes`_. A valid middleware 
partial looks like::

    class LetAnyoneIn(object):
        __slots__ = ()
        def test(self, request, view, obj):
            return True

.. _Django REST Framework's: http://www.django-rest-framework.org/
.. _Permission classes: http://www.django-rest-framework.org/api-guide/permissions

The partials may also implement ``error()`` and/or ``success()``, where
an ``HttpResponse`` may force the request to return early, or an exception
may be raised::

    class NotQuiteAnyone(object):
        __slots__ = ()
        def test(self, request, view, obj):
            return request.user.pk == 1

        def error(self, request, view, obj):
            raise PermissionDenied("Nope")

        def success(self, request, view, obj):
            return HttpResponse("Yay, you're User 1!")

If enabled, the above middleware partial would cause an intentional error for
almost everyone.

Additionally, ``test`` may return ``None`` to indicate that
the partial middleware wasn't applicable.

That "obj" argument
^^^^^^^^^^^^^^^^^^^

The ``obj`` argument being provided to each middleware partial is a ``URL``
model instance. From the ``URL`` instance you may test for the existance of
related model instances which may modify eventual response.

By way of example, the ``UserRoleRequired`` (which checks for
``is_authenticated``, ``is_staff`` and ``is_superuser``) makes use of a
``SimpleAccessRestriction`` model, which has a reverse relation through the
use of a ``OneToOneField`` relating it back to the ``URL``, thus the beginning
of the partial middleware would be::

    class UnfinishedAuth(object):
        __slots__ = ()
        def test(self, request, view, obj):
            try:
                relation = obj.simpleaccessrestriction
            except ObjectDoesNotExist:
                # means the partial middleware is not applicable because
                # no configuration exists. Returning False here would indicate
                # that in the absence of configuration, *no-one* can access
                # the URL!
                return None
            # and now the rest of the permissions test!


Enabling, ordering, all that jazz
---------------------------------

The order partial middlewares are applied in is the same as the ordering
of ``inlines`` on the ``ModelAdmin`` for ``URL``

The control of whether or not a partial middleware is enabled is by implementing
a ``get_churlish_middlewares`` method on the inline class.

Exclusions
----------

Certain URL patterns are hardwired to be ignored, namely:

* the admin site, if set.
* anything under ``MEDIA_URL``
* anything under ``STATIC_URL``
* django-debug-toolbar

Additional exclusions may be provided by setting ``CHURLISH_EXCLUDES`` to
an iterable of regular expressions to match the ``request.path`` against.


----

Copyright (c) 2014, Keryn Knight
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This license applies to version 0.1.0 of django-churlish.
