<commit_before>"""
Commonly needed custom view mixins.

Note that these do *not* use something like django-braces' UserPassesTestMixin,
because we may need to use multiple tests in one view (e.g. must be a
coordinator AND must have agreed to the terms of use). If we used that mixin,
test functions and login URLs would overwrite each other. Using the dispatch
function and super() means we can chain as many access tests as we'd like.
"""
from urllib import urlencode
from urlparse import ParseResult

from django.contrib import messages
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse_lazy
from django.http import HttpResponseRedirect

from TWLight.users.groups import get_coordinators


coordinators = get_coordinators()


class CoordinatorOrSelf(object):
    """
    Restricts visibility to:
    * The designated Coordinator for partner related to the object; or
    * The Editor who owns (or is) the object in the view; or
    * Superusers.

    This mixin assumes that the decorated view has a get_object method, and that
    the object in question has a ForeignKey, 'user', to the User model, or else
    is an instance of User.
    """

    def test_func_coordinator_or_self(self, user):
        obj_owner_test = False # Set default.
        try:
            obj = self.get_object()
            if obj:
                if isinstance(obj, User):
                    obj_owner_test = (obj.pk == user.pk)
                else:
                    obj_owner_test = (self.get_object().user.pk == user.pk)
        except AttributeError:
            # Keep the default.
            pass

        obj_coordinator_test = False # Set default.
        try:
            obj = self.get_object()
            if obj:
                    obj_coordinator_test = (self.get_object().partner.coordinator.editor.user.pk == user.pk)
        except AttributeError:
            # Keep the default.
            pass

        return (user.is_superuser or
                obj_coordinator_test or
                obj_owner_test)


    def dispatch(self, request, *args, **kwargs):
        if not self.test_func_coordinator_or_self(request.user):
            messages.add_message(request, messages.WARNING, 'You must be the '
                    'designated coordinator or the owner to do that.')
            raise PermissionDenied

        return super(CoordinatorOrSelf, self).dispatch(
            request, *args, **kwargs)<commit_msg>Put a finer point on the Coordinators or self checks in TWLight/view_mixins.py<commit_after>"""
Commonly needed custom view mixins.

Note that these do *not* use something like django-braces' UserPassesTestMixin,
because we may need to use multiple tests in one view (e.g. must be a
coordinator AND must have agreed to the terms of use). If we used that mixin,
test functions and login URLs would overwrite each other. Using the dispatch
function and super() means we can chain as many access tests as we'd like.
"""
from urllib import urlencode
from urlparse import ParseResult

from django.contrib import messages
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse_lazy
from django.http import HttpResponseRedirect

from TWLight.applications.models import Application
from TWLight.users.models import Editor
from TWLight.users.groups import get_coordinators


coordinators = get_coordinators()


class CoordinatorOrSelf(object):
    """
    Restricts visibility to:
    * The designated Coordinator for partner related to the object; or
    * The Editor who owns (or is) the object in the view; or
    * Superusers.

    This mixin assumes that the decorated view has a get_object method, and that
    the object in question has a ForeignKey, 'user', to the User model, or else
    is an instance of User.
    """

    def test_func_coordinator_or_self(self, user):
        obj_owner_test = False # Set default.

        try:
            obj = self.get_object()
            if obj:
                if isinstance(obj, User):
                    obj_owner_test = (obj.pk == user.pk)
                else:
                    obj_owner_test = (obj.user.pk == user.pk)
        except AttributeError:
            # Keep the default.
            pass

        obj_coordinator_test = False # Set default.
        try:
            obj = self.get_object()
            if obj:
                    if isinstance(obj, Editor):
                        obj_coordinator_test = (obj.applications.filter(partner__coordinator__pk=user.pk).exists())
                    elif isinstance(obj, Application):
                        obj_coordinator_test = (obj.partner.coordinator.pk == user.pk)
        except AttributeError:
            # Keep the default.
            pass

        return (user.is_superuser or
                obj_coordinator_test or
                obj_owner_test)


    def dispatch(self, request, *args, **kwargs):
        if not self.test_func_coordinator_or_self(request.user):
            messages.add_message(request, messages.WARNING, 'You must be the '
                    'designated coordinator or the owner to do that.')
            raise PermissionDenied

        return super(CoordinatorOrSelf, self).dispatch(
            request, *args, **kwargs)
{'fraction_non_alphanumeric': 0.06587374199451052, 'fraction_numerical': 0.0, 'mean_word_length': 2.508344030808729, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5733847', 'n_tokens_mistral': 1472, 'n_tokens_neox': 1414, 'n_words': 530}