From 3c82ab98f3d9d6bdc667352da8977964e27b8d8d Mon Sep 17 00:00:00 2001
From: Tanner Prestegard <tanner.prestegard@ligo.org>
Date: Mon, 22 Oct 2018 15:24:49 -0500
Subject: [PATCH] New 'groups_allowed' decorator for views

Can be used to restrict access to a view to only the groups
whose names are passed as arguments to the decorator.
---
 config/urls.py            | 12 +++++++++---
 gracedb/ligoauth/utils.py | 25 +++++++++++++++++++++++++
 gracedb/ligoauth/views.py |  8 ++++++++
 3 files changed, 42 insertions(+), 3 deletions(-)
 create mode 100644 gracedb/ligoauth/utils.py
 create mode 100644 gracedb/ligoauth/views.py

diff --git a/config/urls.py b/config/urls.py
index 776d3e716..44d1e7b96 100644
--- a/config/urls.py
+++ b/config/urls.py
@@ -1,11 +1,11 @@
 
 # Changed for Django 1.11 upgrade
-from django.conf.urls import url, include
 from django.conf import settings
+from django.conf.urls import url, include
 
 # Uncomment the next two lines to enable the admin:
 from django.contrib import admin
-admin.autodiscover()
+from django.contrib.auth.views import logout
 from django.views.generic import TemplateView
 
 # Import feeds
@@ -13,9 +13,13 @@ from events.feeds import EventFeed, feedview
 
 # After Django 1.10, have to import views directly, rather
 # than just using a string
+import events.reports
 import events.views
+from ligoauth.views import gracedb_login
 import search.views
-import events.reports
+
+# Django admin auto-discover
+admin.autodiscover()
 
 feeds = {
     'latest' : EventFeed
@@ -43,6 +47,8 @@ urlpatterns = [
     url(r'^reports/cbc_report/(?P<format>(json|flex))?$',
         events.reports.cbc_report, name="cbc_report"),
     url(r'^latest/$', search.views.latest, name="latest"),
+    url(r'^login/$', gracedb_login, name='login'),
+    url(r'^logout/$', logout, {'next_page': '/'}, name='logout'),
     #(r'^reports/(?P<path>.+)$', 'django.views.static.serve',
     #        {'document_root': settings.LATENCY_REPORT_DEST_DIR}),
     url(r'^search/$', search.views.search, name="mainsearch"),
diff --git a/gracedb/ligoauth/utils.py b/gracedb/ligoauth/utils.py
new file mode 100644
index 000000000..91cf80f57
--- /dev/null
+++ b/gracedb/ligoauth/utils.py
@@ -0,0 +1,25 @@
+from django.http import HttpResponseForbidden
+from django.utils.functional import wraps
+
+def groups_allowed(group_names):
+    """
+    Decorator to allow access to specified group(s).
+    Usage:
+        @groups_allowed(settings.LVC_GROUP)
+        @groups_allowed([settings.LVC_GROUP, settings.LVEM_OBSERVERS_GROUP])
+    """
+
+    if isinstance(group_names, str):
+        group_names = [group_names]
+    def decorator(view_func):
+        @wraps(view_func)
+        def wrapper(request, *args, **kwargs):
+            user_groups = [g.name for g in request.user.groups.all()]
+            if set(group_names).isdisjoint(user_groups):
+                # Use a template
+                return HttpResponseForbidden("You are not a member of {0}".format(group_names))
+            return view_func(request, *args, **kwargs)
+
+        return wrapper
+    return decorator
+
diff --git a/gracedb/ligoauth/views.py b/gracedb/ligoauth/views.py
new file mode 100644
index 000000000..e92a442ad
--- /dev/null
+++ b/gracedb/ligoauth/views.py
@@ -0,0 +1,8 @@
+from django.http import HttpResponseRedirect
+from django.utils.http import urlquote
+from django.conf import settings
+
+def gracedb_login(request):
+    full_login_url = "{base}?target={path}".format(base=settings.LOGIN_URL,
+        path=urlquote(request.META.get('HTTP_REFERER', '/')))
+    return HttpResponseRedirect(full_login_url)
-- 
GitLab