Repository: mozilla/telemetry-analysis-service

Issue:
Add user column to spark job table on dashboard
To only be seen by admins in the "Spark job maintainers" group.


Discussion:

Resolving patch:
diff --git a/atmo/urls.py b/atmo/urls.py
--- a/atmo/urls.py
+++ b/atmo/urls.py
@@ -15,7 +15,7 @@
 admin.site.login = login_required(admin.site.login)
 
 urlpatterns = [
-    url(r'^$', views.dashboard, name='dashboard'),
+    url(r'^$', views.DashboardView.as_view(), name='dashboard'),
     url(r'^admin/', include(admin.site.urls)),
 
     url(r'clusters/', include('atmo.clusters.urls')),
diff --git a/atmo/views.py b/atmo/views.py
--- a/atmo/views.py
+++ b/atmo/views.py
@@ -6,8 +6,9 @@
 from django.http import HttpResponseServerError
 from django.shortcuts import redirect
 from django.template import Context, TemplateDoesNotExist, loader
-from django.template.response import TemplateResponse
+from django.utils.decorators import method_decorator
 from django.views.decorators.csrf import requires_csrf_token
+from django.views.generic.base import TemplateView
 from guardian.shortcuts import get_objects_for_group, get_objects_for_user
 
 from .clusters.models import Cluster
@@ -15,83 +16,94 @@
 from .jobs.models import SparkJob
 
 
-@login_required
-@modified_date
-def dashboard(request):
+@method_decorator(login_required, name='dispatch')
+@method_decorator(modified_date, name='dispatch')
+class DashboardView(TemplateView):
+    template_name = 'atmo/dashboard.html'
+    http_method_names = ['get', 'head']
     # allowed filters for clusters
-    default_cluster_filter = 'active'
-    clusters_filters = ['active', 'terminated', 'failed', 'all']
-
-    # the cluster filter defaults to active ones
-    clusters_shown = request.GET.get('clusters', default_cluster_filter)
-    if clusters_shown not in clusters_filters:
-        clusters_shown = default_cluster_filter
-
-    # get the model manager method depending on the cluster filter
-    # and call it to get the base queryset
-    clusters = get_objects_for_user(
-        request.user,
-        'clusters.view_cluster',
-        getattr(Cluster.objects, clusters_shown)().order_by('-start_date'),
-        use_groups=False,
-        with_superuser=False,
-    )
-
-    sparkjob_qs = SparkJob.objects.all().order_by('-start_date')
-    group = Group.objects.filter(name='Spark job maintainers').first()
-    is_sparkjob_maintainer = group and group in request.user.groups.all()
-
+    active_cluster_filter = 'active'
+    default_cluster_filter = active_cluster_filter
+    clusters_filters = [active_cluster_filter, 'terminated', 'failed', 'all']
     # Filters for jobs.
-    default_job_filter = 'mine'
-    jobs_filters = ['mine', 'all']
-
-    jobs_shown = request.GET.get('jobs', default_job_filter)
-    if jobs_shown not in jobs_filters:
-        jobs_shown = default_job_filter
-
-    # Redirect if user isn't in the right group.
-    if jobs_shown == 'all' and not is_sparkjob_maintainer:
-        return redirect('dashboard')
-
-    if jobs_shown == 'mine':
-        spark_jobs = get_objects_for_user(
-            request.user,
-            'jobs.view_sparkjob',
-            sparkjob_qs,
+    all_job_filter = 'all'
+    mine_job_filter = 'mine'
+    default_job_filter = mine_job_filter
+    jobs_filters = [mine_job_filter, all_job_filter]
+    maintainer_group_name = 'Spark job maintainers'
+
+    def dispatch(self, request, *args, **kwargs):
+        self.clusters_shown = self.request.GET.get('clusters', self.default_cluster_filter)
+        if self.clusters_shown not in self.clusters_filters:
+            self.clusters_shown = self.default_cluster_filter
+
+        self.jobs_maintainer_group = Group.objects.filter(name=self.maintainer_group_name).first()
+        self.is_sparkjob_maintainer = (
+            self.jobs_maintainer_group and
+            self.jobs_maintainer_group in self.request.user.groups.all()
+        )
+
+        self.jobs_shown = self.request.GET.get('jobs', self.default_job_filter)
+        if self.jobs_shown not in self.jobs_filters:
+            self.jobs_shown = self.default_job_filter
+
+        # Redirect if user isn't in the right group.
+        if self.jobs_shown == self.all_job_filter and not self.is_sparkjob_maintainer:
+            return redirect('dashboard')
+        return super().dispatch(request, *args, **kwargs)
+
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+
+        # get the model manager method depending on the cluster filter
+        # and call it to get the base queryset
+        clusters = get_objects_for_user(
+            self.request.user,
+            'clusters.view_cluster',
+            getattr(Cluster.objects, self.clusters_shown)().order_by('-start_date'),
             use_groups=False,
             with_superuser=False,
         )
-    elif jobs_shown == 'all':
-        spark_jobs = get_objects_for_group(
-            group,
-            'jobs.view_sparkjob',
-            sparkjob_qs,
-            any_perm=False,
-            accept_global_perms=False,
-        )
 
-    # a list of modification datetimes of the clusters and Spark jobs to use
-    # for getting the last changes on the dashboard
-    cluster_mod_datetimes = list(clusters.values_list('modified_at', flat=True))
-    spark_job_mod_datetimes = [
-        spark_job.latest_run.modified_at
-        for spark_job in spark_jobs.with_runs().order_by('-runs__modified_at')
-    ]
-    modified_datetimes = sorted(cluster_mod_datetimes + spark_job_mod_datetimes, reverse=True)
-
-    context = {
-        'clusters': clusters,
-        'clusters_shown': clusters_shown,
-        'clusters_filters': clusters_filters,
-        'spark_jobs': spark_jobs,
-        'jobs_shown': jobs_shown,
-        'jobs_filters': jobs_filters,
-        'is_sparkjob_maintainer': is_sparkjob_maintainer,
-    }
-    if modified_datetimes:
-        context['modified_date'] = modified_datetimes[0]
-
-    return TemplateResponse(request, 'atmo/dashboard.html', context=context)
+        sparkjob_qs = SparkJob.objects.all().order_by('-start_date')
+
+        if self.jobs_shown == self.mine_job_filter:
+            spark_jobs = get_objects_for_user(
+                self.request.user,
+                'jobs.view_sparkjob',
+                sparkjob_qs,
+                use_groups=False,
+                with_superuser=False,
+            )
+        elif self.jobs_shown == self.all_job_filter:
+            spark_jobs = get_objects_for_group(
+                self.jobs_maintainer_group,
+                'jobs.view_sparkjob',
+                sparkjob_qs,
+                any_perm=False,
+                accept_global_perms=False,
+            )
+        else:
+            spark_jobs = sparkjob_qs.none()
+
+        context.update({
+            'clusters': clusters,
+            'spark_jobs': spark_jobs,
+        })
+
+        # a list of modification datetimes of the clusters and Spark jobs to use
+        # for getting the last changes on the dashboard
+        cluster_mod_datetimes = list(clusters.values_list('modified_at', flat=True))
+        spark_job_mod_datetimes = [
+            spark_job.latest_run.modified_at
+            for spark_job in spark_jobs.with_runs().order_by('-runs__modified_at')
+        ]
+        modified_datetimes = sorted(cluster_mod_datetimes + spark_job_mod_datetimes, reverse=True)
+
+        if modified_datetimes:
+            context['modified_date'] = modified_datetimes[0]
+
+        return context
 
 
 @requires_csrf_token


Test patch: