accounts: Add context_processor and middleware.
authorRaphaël Barrois <raphael.barrois@polytechnique.org>
Sat, 2 Feb 2013 20:32:57 +0000 (21:32 +0100)
committerRaphaël Barrois <raphael.barrois@polytechnique.org>
Sat, 2 Feb 2013 20:32:59 +0000 (21:32 +0100)
Signed-off-by: Raphaël Barrois <raphael.barrois@polytechnique.org>
xnet/accounts/context_processors.py [new file with mode: 0644]
xnet/accounts/decorators.py
xnet/accounts/middleware.py [new file with mode: 0644]
xnet/settings.py

diff --git a/xnet/accounts/context_processors.py b/xnet/accounts/context_processors.py
new file mode 100644 (file)
index 0000000..770b2a5
--- /dev/null
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+
+
+def xnet(request):
+    """Returns context variables required by X.net sites."""
+    return {
+        'group': getattr(request, 'group', None),
+        'membership': getattr(request, 'membership', None),
+    }
index bc29091..ec2a8df 100644 (file)
@@ -6,7 +6,41 @@ from django.shortcuts import get_object_or_404
 from .models import XGroup, Membership
 
 
+def with_group(view_func):
+    """Converts a group slug into a XGroup object.
+
+    Example:
+    >>> @with_group
+    ... def my_view(request, group, *args, **kwargs):
+    ...     # group is now a XGroup instance
+    """
+
+    @functools.wraps(view_func)
+    def wrapped_view_func(request, group_slug, *args, **kwargs):
+        group = get_object_or_404(XGroup, short=group_slug)
+
+        request.group = group
+
+        return view_func(request, group, *args, **kwargs)
+
+    return wrapped_view_func
+
+
 class group_required(object):
+    """Force a minimum group membership level.
+
+    Also combines with_group features:
+    - fetches the XGroup object,
+    - sets request.group
+    - sets request.membership
+
+    Usage:
+
+    >>> @group_required(level=Membership.LEVEL_MEMBER)
+    ... def my_view(request, group, *args, **kwargs):
+    ...     pass
+    """
+
     def __init__(self, level=Membership.LEVEL_MEMBER):
         self.level = level
 
@@ -14,13 +48,21 @@ class group_required(object):
         @functools.wraps(view_func)
         def wrapped_view_func(request, group_slug, *args, **kwargs):
             group = get_object_or_404(XGroup, short=group_slug)
-            membership = request.user.memberships.filter(
-                xgroup=group,
-                level__gte=self.level,
-                state='enabled',
-            )
-            if membership.exists():
-                return view_func(request, group, *args, membership=membership[0], **kwargs)
+
+            try:
+                membership = request.user.memberships.get(
+                    xgroup=group,
+                    level__gte=self.level,
+                    state='enabled',
+                )
+            except Membership.DoesNotExist:
+                membership = None
+
+            request.group = group
+            request.membership = membership
+
+            if membership:
+                return view_func(request, group, *args, membership=membership, **kwargs)
             else:
                 return HttpResponseForbidden()
         return wrapped_view_func
diff --git a/xnet/accounts/middleware.py b/xnet/accounts/middleware.py
new file mode 100644 (file)
index 0000000..5b3e57a
--- /dev/null
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+
+
+class XnetAccountMiddleware(object):
+    """Ensures request.group and request.membership are defined."""
+
+    def process_request(self, request):
+        request.group = None
+        request.membership = None
index 4260933..a23093c 100644 (file)
@@ -49,6 +49,16 @@ OCALE_PATHS = (
     os.path.join(ROOT_DIR, 'locale'),
 )
 
+TEMPLATE_CONTEXT_PROCESSORS = (
+    'django.contrib.auth.context_processors.auth',
+    'django.core.context_processors.debug',
+    'django.core.context_processors.i18n',
+    'django.core.context_processors.media',
+    'django.core.context_processors.static',
+    'django.core.context_processors.tz',
+    'django.contrib.messages.context_processors.messages',
+    'xnet.accounts.context_processors.xnet',
+)
 
 SITE_ID = 1
 
@@ -99,7 +109,7 @@ STATICFILES_FINDERS = (
 )
 
 # Make this unique, and don't share it with anybody.
-SECRET_KEY = 'iq9w_94mr$p$a3sr%*cnvt8z($-)zjk1o8wx45dw(6z3%(mwzo'
+SECRET_KEY = 'FOR DEV ONLY!!'
 
 # List of callables that know how to import templates from various sources.
 TEMPLATE_LOADERS = (
@@ -113,6 +123,7 @@ MIDDLEWARE_CLASSES = (
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'xnet.accounts.middleware.XnetAccountMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
     # Uncomment the next line for simple clickjacking protection:
     # 'django.middleware.clickjacking.XFrameOptionsMiddleware',