Repository: learningequality/kolibri

Issue:
Class coaches can access class pages even when they are not assigned to the class
### Observed behavior
~I can access the class groups rename form as coach but I have 403 error after I submit it.~

Class Coaches can access a classroom page even if they are not assigned to the classroom.

### Expected behavior
~The class groups rename form most not accessible in coach.~

Pages from classrooms not assigned to the coach should not be accessible to the coach.
 
It should be redirected in the `auth-message` refer at the screenshot below
![screen shot 2018-04-27 at 3 13 57 pm](https://user-images.githubusercontent.com/8663934/39350597-37f87694-4a31-11e8-9d7b-eaa681a78f54.png)


### Steps to reproduce
- Log in as admin, then navigate at `class groups` page then copy the link.
- Log out as admin then Log in as coach then navigate at the `class groups` page using the link.
- Try to rename a class groups then submit it.

### Context

Tell us about your environment, including:
 * Kolibri 0.10.0.dev1.dev+git-33-g268dd8a
 * macOS 10.13.3
 * Chome Version 65.0.3325.181 (Official Build) (64-bit)

…




Discussion:
@mrpau-richard Could you provide more details on the Coach account? Is it a Class Coach or Facility Coach account?

I think it _may_ be possible for a Class Coach to view Classes they are not assigned to, but cannot edit (e.g. rename a Learner Group) any part of them.
@jonboiser yeah, It's Class Coach. I have this screenshot showing that there is an `option button enabled` and it can access to rename group form.
![screen shot 2018-05-02 at 11 57 28 am](https://user-images.githubusercontent.com/8663934/39504745-70982d14-4e00-11e8-96f7-f83aa56f2d1e.png)

But after I submitted or save it will show a `403 forbidden` error.
 
@mrpau-richard My theory is that the Class Coach has not been assigned to the Classroom you're looking at.

So the underlying issue is that we do not handle this case (coaches going directly to class pages they should not access) properly at the moment.

Compare these screenshots:

**Coach is assigned to classroom**

The text above "Class groups" is correct

![screen shot 2018-05-02 at 10 51 36 am](https://user-images.githubusercontent.com/10248067/39540248-ebb82eb8-4df6-11e8-9dfc-24daa0c76c11.png)


**Coach is not assigned to classroom**

The text above "Class groups" is not correct (like in your screenshot). Adding or renaming groups will not work.

![screen shot 2018-05-02 at 10 51 47 am](https://user-images.githubusercontent.com/10248067/39540254-efdff14c-4df6-11e8-9200-6fda85b3dc1f.png)

The reason we don't see the 'auth-message' component in this scenario is because Coaches can _view_ any class, even if they are not assigned to it.
@jonboiser I think we should disable the `options button` then, if the `Class Coach` can't rename and delete the Class group.
>  Coaches can view any class, even if they are not assigned to it
 
My understanding is that this is incorrect. I believe classes should be private and only visible to assigned coaches, facility-level coaches, and admins

@ralphiee22 This came up when we were implementing class coaches. Should we change the permissions for Classrooms so not-assigned-to-this-class Coaches get a 40X error when going to these pages?
@ralphiee22 mind fixing this in `develop`?
Regarding this, current permissions allow anybody from the same facility to READ any collection. In the backend, we do not prevent even a learner from being able to read a group. cc: @jamalex 
A possible solution is attaching the collection id to the roles in the session object (to see if a coach has access to certain classes), but I am unsure how many places in the frontend depend on that being an array as opposed to a dictionary.
> I am unsure how many places in the frontend depend on that being an array as opposed to a dictionary

These should be straightforward to track down, and for 0.12 we have plenty of time for regression testing
I think @ralphiee22's solution is the right one, so that we can make role checks on the frontend more granular, but we should bump this to 0.12.

Resolving patch:
diff --git a/kolibri/plugins/coach/api.py b/kolibri/plugins/coach/api.py
--- a/kolibri/plugins/coach/api.py
+++ b/kolibri/plugins/coach/api.py
@@ -38,48 +38,53 @@ class OptionalPageNumberPagination(pagination.PageNumberPagination):
     page_size_query_param = "page_size"
 
 
-class KolibriReportPermissions(permissions.BasePermission):
+class LessonReportPermissions(permissions.BasePermission):
+    """
+    List - check if requester has coach/admin permissions on whole facility.
+    Detail - check if requester has permissions on the Classroom.
+    """
 
-    # check if requesting user has permission for collection or user
     def has_permission(self, request, view):
-        if isinstance(view, LessonReportViewset):
-            report_pk = view.kwargs.get('pk', None)
-            if report_pk is None:
-                # If requesting list view, check if requester has coach/admin permissions on whole facility
-                collection_kind = 'facility'
-                collection_or_user_pk = request.user.facility_id
-            else:
-                # If requesting detail view, only check if requester has permissions on the Classroom
-                collection_kind = 'classroom'
-                collection_or_user_pk = Lesson.objects.get(pk=report_pk).collection.id
-
+        report_pk = view.kwargs.get('pk', None)
+        if report_pk is None:
+            collection_id = request.user.facility_id
         else:
-            if isinstance(view, ClassroomNotificationsViewset):
-                collection_kind = 'classroom'
-            else:
-                collection_kind = view.kwargs.get('collection_kind', 'user')
-            collection_or_user_pk = view.kwargs.get('collection_id', view.kwargs.get('pk'))
+            collection_id = Lesson.objects.get(pk=report_pk).collection.id
 
         allowed_roles = [role_kinds.ADMIN, role_kinds.COACH]
+
         try:
-            if 'user' == collection_kind:
-                return request.user.has_role_for(allowed_roles, FacilityUser.objects.get(pk=collection_or_user_pk))
-            else:
-                return request.user.has_role_for(allowed_roles, Collection.objects.get(pk=collection_or_user_pk))
-        except (FacilityUser.DoesNotExist, Collection.DoesNotExist, ValueError):
+            return request.user.has_role_for(allowed_roles, Collection.objects.get(pk=collection_id))
+        except (Collection.DoesNotExist, ValueError):
             return False
 
 
 class LessonReportViewset(viewsets.ReadOnlyModelViewSet):
-    permission_classes = (permissions.IsAuthenticated, KolibriReportPermissions,)
+    permission_classes = (permissions.IsAuthenticated, LessonReportPermissions,)
     serializer_class = LessonReportSerializer
     queryset = Lesson.objects.all()
 
 
+class ClassroomNotificationsPermissions(permissions.BasePermission):
+    """
+    Allow only users with admin/coach permissions on a collection.
+    """
+
+    def has_permission(self, request, view):
+        collection_id = view.kwargs.get('collection_id')
+
+        allowed_roles = [role_kinds.ADMIN, role_kinds.COACH]
+
+        try:
+            return request.user.has_role_for(allowed_roles, Collection.objects.get(pk=collection_id))
+        except (Collection.DoesNotExist, ValueError):
+            return False
+
+
 @query_params_required(collection_id=str)
 class ClassroomNotificationsViewset(viewsets.ReadOnlyModelViewSet):
 
-    permission_classes = (KolibriReportPermissions,)
+    permission_classes = (ClassroomNotificationsPermissions,)
     serializer_class = LearnerNotificationSerializer
     pagination_class = OptionalPageNumberPagination
     pagination_class.page_size = 10
diff --git a/kolibri/plugins/coach/class_summary_api.py b/kolibri/plugins/coach/class_summary_api.py
--- a/kolibri/plugins/coach/class_summary_api.py
+++ b/kolibri/plugins/coach/class_summary_api.py
@@ -9,6 +9,8 @@
 from rest_framework.response import Response
 
 from kolibri.core.auth import models as auth_models
+from kolibri.core.auth.constants import role_kinds
+from kolibri.core.auth.models import Collection
 from kolibri.core.content.models import ContentNode
 from kolibri.core.exams.models import Exam
 from kolibri.core.lessons.models import Lesson
@@ -207,11 +209,23 @@ def data(Serializer, queryset):
     return Serializer(queryset, many=True).data
 
 
-class ClassSummaryViewSet(viewsets.ViewSet):
+class ClassSummaryPermissions(permissions.BasePermission):
+    """
+    Allow only users with admin/coach permissions on the classroom.
+    """
+
+    def has_permission(self, request, view):
+        classroom_id = view.kwargs.get('pk')
+        allowed_roles = [role_kinds.ADMIN, role_kinds.COACH]
+
+        try:
+            return request.user.has_role_for(allowed_roles, Collection.objects.get(pk=classroom_id))
+        except (Collection.DoesNotExist, ValueError):
+            return False
 
-    # TODO use more granular permissions. Not sure if KolibriReportPermissions will
-    # work as is, though.
-    permission_classes = (permissions.IsAuthenticated,)
+
+class ClassSummaryViewSet(viewsets.ViewSet):
+    permission_classes = (permissions.IsAuthenticated, ClassSummaryPermissions,)
 
     def retrieve(self, request, pk):
         classroom = get_object_or_404(auth_models.Classroom, id=pk)


Test patch:
diff --git a/kolibri/plugins/coach/test/helpers.py b/kolibri/plugins/coach/test/helpers.py
new file mode 100644
--- /dev/null
+++ b/kolibri/plugins/coach/test/helpers.py
@@ -0,0 +1,55 @@
+from kolibri.core.auth.models import FacilityUser
+
+
+def create_learner(username, password, facility, classroom=None, learner_group=None):
+    """
+    Create a facility learner.
+    Assign them a classroom if specified.
+    Assign them a learner group if specified.
+    """
+
+    learner = FacilityUser.objects.create(username=username, facility=facility)
+    learner.set_password(password)
+    learner.save()
+
+    if classroom is not None:
+        classroom.add_member(learner)
+
+    if learner_group is not None:
+        learner_group.add_member(learner)
+
+    return learner
+
+
+def create_coach(username, password, facility, classroom=None, is_facility_coach=False):
+    """
+    Create a coach.
+    Assign them a classroom if specified.
+    Grant facility permissions if is_facility_coach is True.
+    """
+
+    coach = FacilityUser.objects.create(username=username, facility=facility)
+    coach.set_password(password)
+    coach.save()
+
+    if classroom is not None:
+        classroom.add_coach(coach)
+
+    if is_facility_coach:
+        facility.add_coach(coach)
+
+    return coach
+
+
+def create_facility_admin(username, password, facility):
+    """
+    Create a facility admin.
+    """
+
+    admin = FacilityUser.objects.create(username=username, facility=facility)
+    admin.set_password(password)
+    admin.save()
+
+    facility.add_admin(admin)
+
+    return admin
diff --git a/kolibri/plugins/coach/test/test_class_summary.py b/kolibri/plugins/coach/test/test_class_summary.py
--- a/kolibri/plugins/coach/test/test_class_summary.py
+++ b/kolibri/plugins/coach/test/test_class_summary.py
@@ -8,9 +8,9 @@
 from le_utils.constants import content_kinds
 from rest_framework.test import APITestCase
 
+from . import helpers
 from kolibri.core.auth.models import Classroom
 from kolibri.core.auth.models import Facility
-from kolibri.core.auth.models import FacilityUser
 from kolibri.core.auth.test.helpers import provision_device
 from kolibri.core.content.models import ContentNode
 from kolibri.core.lessons import models
@@ -27,17 +27,47 @@ def setUp(self):
         provision_device()
         self.facility = Facility.objects.create(name="MyFac")
         self.classroom = Classroom.objects.create(name='classrom', parent=self.facility)
-        self.admin = FacilityUser.objects.create(username="admin", facility=self.facility)
-        self.admin.set_password(DUMMY_PASSWORD)
-        self.admin.save()
-        self.facility.add_admin(self.admin)
+        self.another_classroom = Classroom.objects.create(name='another classrom', parent=self.facility)
+
+        self.facility_admin = helpers.create_facility_admin(
+            username="facility_admin",
+            password=DUMMY_PASSWORD,
+            facility=self.facility
+        )
+        self.facility_coach = helpers.create_coach(
+            username="facility_coach",
+            password=DUMMY_PASSWORD,
+            facility=self.facility,
+            is_facility_coach=True
+        )
+        self.classroom_coach = helpers.create_coach(
+            username="classroom_coach",
+            password=DUMMY_PASSWORD,
+            facility=self.facility,
+            classroom=self.classroom
+        )
+        self.another_classroom_coach = helpers.create_coach(
+            username="another_classroom_coach",
+            password=DUMMY_PASSWORD,
+            facility=self.facility,
+            classroom=self.another_classroom
+        )
+        self.learner = helpers.create_learner(
+            username="learner",
+            password=DUMMY_PASSWORD,
+            facility=self.facility
+        )
+
         self.lesson = models.Lesson.objects.create(
             title="title",
             is_active=True,
             collection=self.classroom,
-            created_by=self.admin
+            created_by=self.facility_admin
         )
 
+        self.basename = "kolibri:coach:classsummary"
+        self.detail_name = self.basename + "-detail"
+
     def test_non_existent_nodes_dont_show_up_in_lessons(self):
         node = ContentNode.objects.exclude(kind=content_kinds.TOPIC).first()
         last_node = ContentNode.objects.exclude(kind=content_kinds.TOPIC).last()
@@ -47,10 +77,45 @@ def test_non_existent_nodes_dont_show_up_in_lessons(self):
         self.lesson.resources = [real_data, switched_data, fake_data]
         self.lesson.save()
 
-        self.client.login(username=self.admin.username, password=DUMMY_PASSWORD)
-        response = self.client.get(reverse("kolibri:coach:classsummary-detail", kwargs={'pk': self.classroom.id}))
+        self.client.login(username=self.facility_admin.username, password=DUMMY_PASSWORD)
+        response = self.client.get(reverse(self.detail_name, kwargs={'pk': self.classroom.id}))
         node_ids = response.data['lessons'][0]['node_ids']
         self.assertIn(real_data['contentnode_id'], node_ids)
         # swapped data
         self.assertIn(last_node.id, node_ids)
         self.assertNotIn(fake_data['contentnode_id'], node_ids)
+
+    def test_anon_user_cannot_access_detail(self):
+        response = self.client.get(reverse(self.detail_name, kwargs={'pk': self.classroom.id}))
+
+        self.assertEqual(response.status_code, 403)
+
+    def test_learner_cannot_access_detail(self):
+        self.client.login(username=self.learner.username, password=DUMMY_PASSWORD)
+        response = self.client.get(reverse(self.detail_name, kwargs={'pk': self.classroom.id}))
+
+        self.assertEqual(response.status_code, 403)
+
+    def test_another_classroom_coach_cannot_access_detail(self):
+        self.client.login(username=self.another_classroom_coach.username, password=DUMMY_PASSWORD)
+        response = self.client.get(reverse(self.detail_name, kwargs={'pk': self.classroom.id}))
+
+        self.assertEqual(response.status_code, 403)
+
+    def test_classroom_coach_can_access_detail(self):
+        self.client.login(username=self.classroom_coach.username, password=DUMMY_PASSWORD)
+        response = self.client.get(reverse(self.detail_name, kwargs={'pk': self.classroom.id}))
+
+        self.assertEqual(response.status_code, 200)
+
+    def test_facility_coach_can_access_detail(self):
+        self.client.login(username=self.facility_coach.username, password=DUMMY_PASSWORD)
+        response = self.client.get(reverse(self.detail_name, kwargs={'pk': self.classroom.id}))
+
+        self.assertEqual(response.status_code, 200)
+
+    def test_facility_admin_can_access_detail(self):
+        self.client.login(username=self.facility_admin.username, password=DUMMY_PASSWORD)
+        response = self.client.get(reverse(self.detail_name, kwargs={'pk': self.classroom.id}))
+
+        self.assertEqual(response.status_code, 200)
diff --git a/kolibri/plugins/coach/test/test_classroom_notifications.py b/kolibri/plugins/coach/test/test_classroom_notifications.py
new file mode 100644
--- /dev/null
+++ b/kolibri/plugins/coach/test/test_classroom_notifications.py
@@ -0,0 +1,89 @@
+from __future__ import absolute_import
+from __future__ import print_function
+from __future__ import unicode_literals
+
+from django.core.urlresolvers import reverse
+from rest_framework.test import APITestCase
+
+from . import helpers
+from kolibri.core.auth.models import Classroom
+from kolibri.core.auth.models import Facility
+from kolibri.core.auth.test.helpers import provision_device
+
+DUMMY_PASSWORD = "password"
+
+
+class ClassroomNotificationsTestCase(APITestCase):
+
+    def setUp(self):
+        provision_device()
+        self.facility = Facility.objects.create(name='My Facility')
+        self.classroom = Classroom.objects.create(name='My Classroom', parent=self.facility)
+        self.another_classroom = Classroom.objects.create(name='My Another Classroom', parent=self.facility)
+
+        self.facility_admin = helpers.create_facility_admin(
+            username="facility_admin",
+            password=DUMMY_PASSWORD,
+            facility=self.facility
+        )
+        self.facility_coach = helpers.create_coach(
+            username="facility_coach",
+            password=DUMMY_PASSWORD,
+            facility=self.facility,
+            is_facility_coach=True
+        )
+        self.classroom_coach = helpers.create_coach(
+            username="classroom_coach",
+            password=DUMMY_PASSWORD,
+            facility=self.facility,
+            classroom=self.classroom
+        )
+        self.another_classroom_coach = helpers.create_coach(
+            username="another_classroom_coach",
+            password=DUMMY_PASSWORD,
+            facility=self.facility,
+            classroom=self.another_classroom
+        )
+        self.learner = helpers.create_learner(
+            username="learner",
+            password=DUMMY_PASSWORD,
+            facility=self.facility
+        )
+
+        self.basename = "kolibri:coach:notifications"
+        self.list_name = self.basename + "-list"
+
+    def test_anon_user_cannot_access_list(self):
+        response = self.client.get(reverse(self.list_name), {'collection_id': self.classroom.id})
+
+        self.assertEqual(response.status_code, 403)
+
+    def test_learner_cannot_access_list(self):
+        self.client.login(username=self.learner.username, password=DUMMY_PASSWORD)
+        response = self.client.get(reverse(self.list_name), {'collection_id': self.classroom.id})
+
+        self.assertEqual(response.status_code, 403)
+
+    def test_another_classroom_coach_cannot_access_list(self):
+        self.client.login(username=self.another_classroom_coach.username, password=DUMMY_PASSWORD)
+        response = self.client.get(reverse(self.list_name), {'collection_id': self.classroom.id})
+
+        self.assertEqual(response.status_code, 403)
+
+    def test_classroom_coach_can_access_list(self):
+        self.client.login(username=self.classroom_coach.username, password=DUMMY_PASSWORD)
+        response = self.client.get(reverse(self.list_name), {'collection_id': self.classroom.id})
+
+        self.assertEqual(response.status_code, 200)
+
+    def test_facility_coach_can_access_list(self):
+        self.client.login(username=self.facility_coach.username, password=DUMMY_PASSWORD)
+        response = self.client.get(reverse(self.list_name), {'collection_id': self.classroom.id})
+
+        self.assertEqual(response.status_code, 200)
+
+    def test_facility_admin_can_access_list(self):
+        self.client.login(username=self.facility_admin.username, password=DUMMY_PASSWORD)
+        response = self.client.get(reverse(self.list_name), {'collection_id': self.classroom.id})
+
+        self.assertEqual(response.status_code, 200)
diff --git a/kolibri/plugins/coach/test/test_difficult_questions.py b/kolibri/plugins/coach/test/test_difficult_questions.py
--- a/kolibri/plugins/coach/test/test_difficult_questions.py
+++ b/kolibri/plugins/coach/test/test_difficult_questions.py
@@ -8,6 +8,7 @@
 from django.core.urlresolvers import reverse
 from rest_framework.test import APITestCase
 
+from . import helpers
 from kolibri.core.auth.models import Classroom
 from kolibri.core.auth.models import Facility
 from kolibri.core.auth.models import FacilityUser
@@ -25,6 +26,8 @@
 from kolibri.core.logger.models import ExamLog
 from kolibri.core.logger.models import MasteryLog
 
+DUMMY_PASSWORD = "password"
+
 
 class ExerciseDifficultQuestionTestCase(APITestCase):
 
@@ -34,18 +37,25 @@ def setUp(self):
         self.classroom = Classroom.objects.create(name='My Classroom', parent=self.facility)
         self.group = LearnerGroup.objects.create(name='My Group', parent=self.classroom)
 
-        self.coach_user = FacilityUser.objects.create(username='admin', facility=self.facility)
-        self.coach_user.set_password('password')
-        self.coach_user.save()
-
-        self.learner_user = FacilityUser.objects.create(username='learner', facility=self.facility)
-        self.learner_user.set_password('password')
-        self.learner_user.save()
-
-        self.facility.add_coach(self.coach_user)
-        self.classroom.add_coach(self.coach_user)
-        self.classroom.add_member(self.learner_user)
-        self.group.add_member(self.learner_user)
+        self.facility_and_classroom_coach = helpers.create_coach(
+            username="facility_and_classroom_coach",
+            password=DUMMY_PASSWORD,
+            facility=self.facility,
+            classroom=self.classroom,
+            is_facility_coach=True
+        )
+        self.learner = helpers.create_learner(
+            username="learner",
+            password=DUMMY_PASSWORD,
+            facility=self.facility
+        )
+        self.classroom_group_learner = helpers.create_learner(
+            username="classroom_group_learner",
+            password=DUMMY_PASSWORD,
+            facility=self.facility,
+            classroom=self.classroom,
+            learner_group=self.group
+        )
 
         # Need ContentNodes
         self.channel_id = '15f32edcec565396a1840c5413c92450'
@@ -71,7 +81,7 @@ def setUp(self):
         self.lesson = Lesson.objects.create(
             id=self.lesson_id,
             title='My Lesson',
-            created_by=self.coach_user,
+            created_by=self.facility_and_classroom_coach,
             collection=self.classroom,
             resources=json.dumps([{
                 'contentnode_id': self.node_1.id,
@@ -81,60 +91,54 @@ def setUp(self):
         )
         self.assignment_1 = LessonAssignment.objects.create(
             lesson=self.lesson,
-            assigned_by=self.coach_user,
+            assigned_by=self.facility_and_classroom_coach,
             collection=self.classroom,
         )
         self.exercise_difficulties_basename = 'kolibri:coach:exercisedifficulties'
 
     def test_learner_cannot_access_by_classroom_id(self):
-        learner_user = FacilityUser.objects.create(username='learner', facility=self.facility)
-        learner_user.set_password('password')
-        learner_user.save()
-        self.client.login(username='learner', password='password')
+        self.client.login(username=self.learner.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}), data={'classroom_id': self.classroom.id})
         self.assertEqual(response.status_code, 403)
 
     def test_learner_cannot_access_by_lesson_id(self):
-        learner_user = FacilityUser.objects.create(username='learner', facility=self.facility)
-        learner_user.set_password('password')
-        learner_user.save()
-        self.client.login(username='learner', password='password')
+        self.client.login(username=self.learner.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}), data={'lesson_id': self.lesson.id, 'classroom_id': self.classroom.id})
         self.assertEqual(response.status_code, 403)
 
     def test_learner_cannot_access_by_group_id(self):
-        self.client.login(username='learner', password='password')
+        self.client.login(username='learner', password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}), data={'group_id': self.group.id, 'classroom_id': self.classroom.id})
         self.assertEqual(response.status_code, 403)
 
     def test_coach_classroom_id_required(self):
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail', kwargs={'pk': self.content_ids[0]}))
         self.assertEqual(response.status_code, 412)
 
     def test_coach_no_progress_by_classroom_id(self):
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}), data={'classroom_id': self.classroom.id})
         self.assertEqual(len(response.data), 0)
 
     def test_coach_no_progress_by_lesson_id(self):
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}), data={'lesson_id': self.lesson.id, 'classroom_id': self.classroom.id})
         self.assertEqual(len(response.data), 0)
 
     def test_coach_no_progress_by_group_id(self):
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}), data={'group_id': self.group.id, 'classroom_id': self.classroom.id})
@@ -178,8 +182,8 @@ def _set_one_difficult(self, user):
         )
 
     def test_coach_one_difficult_by_classroom_id(self):
-        self._set_one_difficult(self.learner_user)
-        self.client.login(username=self.coach_user.username, password='password')
+        self._set_one_difficult(self.classroom_group_learner)
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}), data={'classroom_id': self.classroom.id})
@@ -188,8 +192,8 @@ def test_coach_one_difficult_by_classroom_id(self):
         self.assertEqual(response.data[0]['correct'], 0)
 
     def test_coach_one_difficult_by_lesson_id(self):
-        self._set_one_difficult(self.learner_user)
-        self.client.login(username=self.coach_user.username, password='password')
+        self._set_one_difficult(self.classroom_group_learner)
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}), data={'lesson_id': self.lesson.id, 'classroom_id': self.classroom.id})
@@ -200,11 +204,11 @@ def test_coach_one_difficult_by_lesson_id(self):
     def test_coach_one_difficult_by_lesson_id_repeated_assignment(self):
         LessonAssignment.objects.create(
             lesson=self.lesson,
-            assigned_by=self.coach_user,
+            assigned_by=self.facility_and_classroom_coach,
             collection=self.group,
         )
-        self._set_one_difficult(self.learner_user)
-        self.client.login(username=self.coach_user.username, password='password')
+        self._set_one_difficult(self.classroom_group_learner)
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}), data={'lesson_id': self.lesson.id, 'classroom_id': self.classroom.id})
@@ -213,8 +217,8 @@ def test_coach_one_difficult_by_lesson_id_repeated_assignment(self):
         self.assertEqual(response.data[0]['correct'], 0)
 
     def test_coach_one_difficult_by_group_id(self):
-        self._set_one_difficult(self.learner_user)
-        self.client.login(username=self.coach_user.username, password='password')
+        self._set_one_difficult(self.classroom_group_learner)
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}), data={'group_id': self.group.id, 'classroom_id': self.classroom.id})
@@ -223,7 +227,7 @@ def test_coach_one_difficult_by_group_id(self):
         self.assertEqual(response.data[0]['correct'], 0)
 
     def test_coach_two_difficult_by_lesson_id(self):
-        self._set_one_difficult(self.learner_user)
+        self._set_one_difficult(self.classroom_group_learner)
         AttemptLog.objects.create(
             masterylog=self.masterylog,
             sessionlog=self.sessionlog,
@@ -231,10 +235,10 @@ def test_coach_two_difficult_by_lesson_id(self):
             end_timestamp=datetime.datetime.now(),
             complete=True,
             correct=0,
-            user=self.learner_user,
+            user=self.classroom_group_learner,
             item='nottest',
         )
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}), data={'lesson_id': self.lesson.id, 'classroom_id': self.classroom.id})
@@ -245,7 +249,7 @@ def test_coach_two_difficult_by_lesson_id(self):
         self.assertEqual(response.data[1]['correct'], 0)
 
     def test_coach_one_difficult_one_not_by_lesson_id(self):
-        self._set_one_difficult(self.learner_user)
+        self._set_one_difficult(self.classroom_group_learner)
         AttemptLog.objects.create(
             masterylog=self.masterylog,
             sessionlog=self.sessionlog,
@@ -253,10 +257,10 @@ def test_coach_one_difficult_one_not_by_lesson_id(self):
             end_timestamp=datetime.datetime.now(),
             complete=True,
             correct=1,
-            user=self.learner_user,
+            user=self.classroom_group_learner,
             item='nottest',
         )
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}), data={'lesson_id': self.lesson.id, 'classroom_id': self.classroom.id})
@@ -265,7 +269,7 @@ def test_coach_one_difficult_one_not_by_lesson_id(self):
         self.assertTrue(any(map(lambda x: x['total'] == 1 and x['correct'] == 1, response.data)))
 
     def test_coach_difficult_no_assigned_by_lesson_id(self):
-        self._set_one_difficult(self.learner_user)
+        self._set_one_difficult(self.classroom_group_learner)
         AttemptLog.objects.create(
             masterylog=self.masterylog,
             sessionlog=self.sessionlog,
@@ -273,18 +277,18 @@ def test_coach_difficult_no_assigned_by_lesson_id(self):
             end_timestamp=datetime.datetime.now(),
             complete=True,
             correct=1,
-            user=self.learner_user,
+            user=self.classroom_group_learner,
             item='nottest',
         )
         LessonAssignment.objects.all().delete()
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}), data={'lesson_id': self.lesson.id, 'classroom_id': self.classroom.id})
         self.assertEqual(len(response.data), 0)
 
     def test_coach_difficult_no_assigned_by_group_id(self):
-        self._set_one_difficult(self.learner_user)
+        self._set_one_difficult(self.classroom_group_learner)
         AttemptLog.objects.create(
             masterylog=self.masterylog,
             sessionlog=self.sessionlog,
@@ -292,11 +296,11 @@ def test_coach_difficult_no_assigned_by_group_id(self):
             end_timestamp=datetime.datetime.now(),
             complete=True,
             correct=1,
-            user=self.learner_user,
+            user=self.classroom_group_learner,
             item='nottest',
         )
         LessonAssignment.objects.all().delete()
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}), data={'group_id': self.group.id, 'classroom_id': self.classroom.id})
@@ -305,11 +309,11 @@ def test_coach_difficult_no_assigned_by_group_id(self):
         self.assertTrue(any(map(lambda x: x['total'] == 1 and x['correct'] == 1, response.data)))
 
     def test_coach_difficult_both_assigned_by_lesson_id_group_id(self):
-        self._set_one_difficult(self.learner_user)
+        self._set_one_difficult(self.classroom_group_learner)
         learner2 = FacilityUser.objects.create(username='learner2', facility=self.facility)
         self.classroom.add_member(learner2)
         self._set_one_difficult(learner2)
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}),
@@ -319,18 +323,18 @@ def test_coach_difficult_both_assigned_by_lesson_id_group_id(self):
         self.assertEqual(response.data[0]['correct'], 0)
 
     def test_coach_difficult_group_id_not_in_lesson(self):
-        self._set_one_difficult(self.learner_user)
+        self._set_one_difficult(self.classroom_group_learner)
         learner2 = FacilityUser.objects.create(username='learner2', facility=self.facility)
         self.classroom.add_member(learner2)
         self._set_one_difficult(learner2)
-        self.group.remove_member(self.learner_user)
+        self.group.remove_member(self.classroom_group_learner)
         self.assignment_1.delete()
         LessonAssignment.objects.create(
             lesson=self.lesson,
-            assigned_by=self.coach_user,
+            assigned_by=self.facility_and_classroom_coach,
             collection=self.group,
         )
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.exercise_difficulties_basename + '-detail',
             kwargs={'pk': self.content_ids[0]}),
@@ -346,57 +350,61 @@ def setUp(self):
         self.classroom = Classroom.objects.create(name='My Classroom', parent=self.facility)
         self.group = LearnerGroup.objects.create(name='My Group', parent=self.classroom)
 
-        self.coach_user = FacilityUser.objects.create(username='admin', facility=self.facility)
-        self.coach_user.set_password('password')
-        self.coach_user.save()
-
-        self.learner_user = FacilityUser.objects.create(username='learner', facility=self.facility)
-        self.learner_user.set_password('password')
-        self.learner_user.save()
-
-        self.facility.add_coach(self.coach_user)
-        self.classroom.add_coach(self.coach_user)
-        self.classroom.add_member(self.learner_user)
-        self.group.add_member(self.learner_user)
+        self.facility_and_classroom_coach = helpers.create_coach(
+            username="facility_and_classroom_coach",
+            password=DUMMY_PASSWORD,
+            facility=self.facility,
+            classroom=self.classroom,
+            is_facility_coach=True
+        )
+        self.learner = helpers.create_learner(
+            username="learner",
+            password=DUMMY_PASSWORD,
+            facility=self.facility
+        )
+        self.classroom_group_learner = helpers.create_learner(
+            username="classroom_group_learner",
+            password=DUMMY_PASSWORD,
+            facility=self.facility,
+            classroom=self.classroom,
+            learner_group=self.group
+        )
 
         self.quiz = Exam.objects.create(
             title='My Lesson',
-            creator=self.coach_user,
+            creator=self.facility_and_classroom_coach,
             collection=self.classroom,
             question_count=5,
         )
         self.assignment_1 = ExamAssignment.objects.create(
             exam=self.quiz,
-            assigned_by=self.coach_user,
+            assigned_by=self.facility_and_classroom_coach,
             collection=self.classroom,
         )
         self.quiz_difficulties_basename = 'kolibri:coach:quizdifficulties'
         self.content_id = '25f32edcec565396a1840c5413c92451'
 
     def test_learner_cannot_access(self):
-        learner_user = FacilityUser.objects.create(username='learner', facility=self.facility)
-        learner_user.set_password('password')
-        learner_user.save()
-        self.client.login(username='learner', password='password')
+        self.client.login(username=self.learner.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.quiz_difficulties_basename + '-detail', kwargs={'pk': self.quiz.id}))
         self.assertEqual(response.status_code, 403)
 
     def test_learner_cannot_access_by_group_id(self):
-        self.client.login(username='learner', password='password')
+        self.client.login(username=self.learner.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.quiz_difficulties_basename + '-detail',
             kwargs={'pk': self.quiz.id}), data={'group_id': self.group.id})
         self.assertEqual(response.status_code, 403)
 
     def test_coach_no_progress(self):
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.quiz_difficulties_basename + '-detail', kwargs={'pk': self.quiz.id}))
         self.assertEqual(len(response.data), 0)
 
     def test_coach_no_progress_by_group_id(self):
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.quiz_difficulties_basename + '-detail',
             kwargs={'pk': self.quiz.id}), data={'group_id': self.group.id})
@@ -420,8 +428,8 @@ def _set_one_difficult(self, user):
         )
 
     def test_coach_one_difficult(self):
-        self._set_one_difficult(self.learner_user)
-        self.client.login(username=self.coach_user.username, password='password')
+        self._set_one_difficult(self.classroom_group_learner)
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.quiz_difficulties_basename + '-detail', kwargs={'pk': self.quiz.id}))
         self.assertEqual(len(response.data), 1)
@@ -429,8 +437,8 @@ def test_coach_one_difficult(self):
         self.assertEqual(response.data[0]['correct'], 0)
 
     def test_coach_one_two_started_difficult(self):
-        self._set_one_difficult(self.learner_user)
-        self.client.login(username=self.coach_user.username, password='password')
+        self._set_one_difficult(self.classroom_group_learner)
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.quiz_difficulties_basename + '-detail', kwargs={'pk': self.quiz.id}))
         self.assertEqual(len(response.data), 1)
@@ -440,11 +448,11 @@ def test_coach_one_two_started_difficult(self):
     def test_coach_one_difficult_repeated_assignment(self):
         ExamAssignment.objects.create(
             exam=self.quiz,
-            assigned_by=self.coach_user,
+            assigned_by=self.facility_and_classroom_coach,
             collection=self.group,
         )
-        self._set_one_difficult(self.learner_user)
-        self.client.login(username=self.coach_user.username, password='password')
+        self._set_one_difficult(self.classroom_group_learner)
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.quiz_difficulties_basename + '-detail', kwargs={'pk': self.quiz.id}))
         self.assertEqual(len(response.data), 1)
@@ -452,8 +460,8 @@ def test_coach_one_difficult_repeated_assignment(self):
         self.assertEqual(response.data[0]['correct'], 0)
 
     def test_coach_one_difficult_by_group_id(self):
-        self._set_one_difficult(self.learner_user)
-        self.client.login(username=self.coach_user.username, password='password')
+        self._set_one_difficult(self.classroom_group_learner)
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.quiz_difficulties_basename + '-detail',
             kwargs={'pk': self.quiz.id}), data={'group_id': self.group.id})
@@ -462,18 +470,18 @@ def test_coach_one_difficult_by_group_id(self):
         self.assertEqual(response.data[0]['correct'], 0)
 
     def test_coach_two_difficult(self):
-        self._set_one_difficult(self.learner_user)
+        self._set_one_difficult(self.classroom_group_learner)
         ExamAttemptLog.objects.create(
             examlog=self.examlog,
             start_timestamp=datetime.datetime.now(),
             end_timestamp=datetime.datetime.now(),
             complete=True,
             correct=0,
-            user=self.learner_user,
+            user=self.classroom_group_learner,
             item='notatest',
             content_id=self.content_id,
         )
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.quiz_difficulties_basename + '-detail', kwargs={'pk': self.quiz.id}))
         self.assertEqual(len(response.data), 2)
@@ -483,18 +491,18 @@ def test_coach_two_difficult(self):
         self.assertEqual(response.data[1]['correct'], 0)
 
     def test_coach_one_difficult_one_not(self):
-        self._set_one_difficult(self.learner_user)
+        self._set_one_difficult(self.classroom_group_learner)
         ExamAttemptLog.objects.create(
             examlog=self.examlog,
             start_timestamp=datetime.datetime.now(),
             end_timestamp=datetime.datetime.now(),
             complete=True,
             correct=1,
-            user=self.learner_user,
+            user=self.classroom_group_learner,
             item='notatest',
             content_id=self.content_id,
         )
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.quiz_difficulties_basename + '-detail', kwargs={'pk': self.quiz.id}))
         self.assertEqual(len(response.data), 2)
@@ -502,18 +510,18 @@ def test_coach_one_difficult_one_not(self):
         self.assertTrue(any(map(lambda x: x['total'] == 1 and x['correct'] == 1, response.data)))
 
     def test_coach_difficult_by_group_id(self):
-        self._set_one_difficult(self.learner_user)
+        self._set_one_difficult(self.classroom_group_learner)
         ExamAttemptLog.objects.create(
             examlog=self.examlog,
             start_timestamp=datetime.datetime.now(),
             end_timestamp=datetime.datetime.now(),
             complete=True,
             correct=1,
-            user=self.learner_user,
+            user=self.classroom_group_learner,
             item='notatest',
             content_id=self.content_id,
         )
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.quiz_difficulties_basename + '-detail',
             kwargs={'pk': self.quiz.id}), data={'group_id': self.group.id})
@@ -522,11 +530,11 @@ def test_coach_difficult_by_group_id(self):
         self.assertTrue(any(map(lambda x: x['total'] == 1 and x['correct'] == 1, response.data)))
 
     def test_coach_difficult_both_assigned_by_group_id(self):
-        self._set_one_difficult(self.learner_user)
+        self._set_one_difficult(self.classroom_group_learner)
         learner2 = FacilityUser.objects.create(username='learner2', facility=self.facility)
         self.classroom.add_member(learner2)
         self._set_one_difficult(learner2)
-        self.client.login(username=self.coach_user.username, password='password')
+        self.client.login(username=self.facility_and_classroom_coach.username, password=DUMMY_PASSWORD)
         response = self.client.get(reverse(
             self.quiz_difficulties_basename + '-detail',
             kwargs={'pk': self.quiz.id}), data={'group_id': self.group.id})
diff --git a/kolibri/plugins/coach/test/test_lesson_report.py b/kolibri/plugins/coach/test/test_lesson_report.py
--- a/kolibri/plugins/coach/test/test_lesson_report.py
+++ b/kolibri/plugins/coach/test/test_lesson_report.py
@@ -8,15 +8,17 @@
 from django.core.urlresolvers import reverse
 from rest_framework.test import APITestCase
 
+from . import helpers
 from kolibri.core.auth.models import Classroom
 from kolibri.core.auth.models import Facility
-from kolibri.core.auth.models import FacilityUser
 from kolibri.core.auth.test.helpers import provision_device
 from kolibri.core.content.models import ContentNode
 from kolibri.core.lessons.models import Lesson
 from kolibri.core.lessons.models import LessonAssignment
 from kolibri.core.logger.models import ContentSummaryLog
 
+DUMMY_PASSWORD = "password"
+
 
 class LessonReportTestCase(APITestCase):
 
@@ -24,18 +26,45 @@ def setUp(self):
         provision_device()
         self.facility = Facility.objects.create(name='My Facility')
         self.classroom = Classroom.objects.create(name='My Classroom', parent=self.facility)
+        self.another_classroom = Classroom.objects.create(name='My Another Classroom', parent=self.facility)
 
-        self.coach_user = FacilityUser.objects.create(username='admin', facility=self.facility)
-        self.coach_user.set_password('password')
-        self.coach_user.save()
-
-        self.learner_user = FacilityUser.objects.create(username='learner', facility=self.facility)
-        self.learner_user.set_password('password')
-        self.learner_user.save()
-
-        self.facility.add_coach(self.coach_user)
-        self.classroom.add_coach(self.coach_user)
-        self.classroom.add_member(self.learner_user)
+        self.facility_admin = helpers.create_facility_admin(
+            username="facility_admin",
+            password=DUMMY_PASSWORD,
+            facility=self.facility
+        )
+        self.facility_and_classroom_coach = helpers.create_coach(
+            username="facility_and_classroom_coach",
+            password=DUMMY_PASSWORD,
+            facility=self.facility,
+            classroom=self.classroom,
+            is_facility_coach=True
+        )
+        self.facility_coach = helpers.create_coach(
+            username="facility_coach",
+            password=DUMMY_PASSWORD,
+            facility=self.facility,
+            is_facility_coach=True
+        )
+        self.classroom_coach = helpers.create_coach(
+            username="classroom_coach",
+            password=DUMMY_PASSWORD,
+            facility=self.facility,
+            classroom=self.classroom
+        )
+        self.another_classroom_coach = helpers.create_coach(
+            username="another_classroom_coach",
+            password=DUMMY_PASSWORD,
+            facility=self.facility,
+            classroom=self.another_classroom
+        )
+        self.classroom_learner = helpers.create_learner(
+            username="classroom_learner",
+            password=DUMMY_PASSWORD,
+            facility=self.facility,
+            classroom=self.classroom
+        )
+        self.learner = helpers.create_learner(username="learner", password=DUMMY_PASSWORD, facility=self.facility)
 
         # Need ContentNodes
         self.channel_id = '15f32edcec565396a1840c5413c92450'
@@ -61,7 +90,7 @@ def setUp(self):
         self.lesson = Lesson.objects.create(
             id=self.lesson_id,
             title='My Lesson',
-            created_by=self.coach_user,
+            created_by=self.facility_and_classroom_coach,
             collection=self.classroom,
             resources=json.dumps([{
                 'contentnode_id': self.node_1.id,
@@ -71,22 +100,78 @@ def setUp(self):
         )
         self.assignment_1 = LessonAssignment.objects.create(
             lesson=self.lesson,
-            assigned_by=self.coach_user,
+            assigned_by=self.facility_and_classroom_coach,
             collection=self.classroom,
         )
         self.lessonreport_basename = 'kolibri:coach:lessonreport'
         # Need ContentSummaryLog
 
-    def test_learner_cannot_access(self):
-        learner_user = FacilityUser.objects.create(username='learner', facility=self.facility)
-        learner_user.set_password('password')
-        learner_user.save()
-        self.client.login(username='learner', password='password')
+    def test_anon_user_cannot_access_list(self):
+        get_response = self.client.get(reverse(self.lessonreport_basename + '-list'))
+
+        self.assertEqual(get_response.status_code, 403)
+
+    def test_learner_cannot_access_list(self):
+        self.client.login(username=self.learner.username, password=DUMMY_PASSWORD)
+        get_response = self.client.get(reverse(self.lessonreport_basename + '-list'))
+
+        self.assertEqual(get_response.status_code, 403)
+
+    def test_classroom_coach_cannot_access_list(self):
+        self.client.login(username=self.classroom_coach.username, password=DUMMY_PASSWORD)
+        get_response = self.client.get(reverse(self.lessonreport_basename + '-list'))
+
+        self.assertEqual(get_response.status_code, 403)
+
+    def test_facility_coach_can_access_list(self):
+        self.client.login(username=self.facility_coach.username, password=DUMMY_PASSWORD)
+        get_response = self.client.get(reverse(self.lessonreport_basename + '-list'))
+
+        self.assertEqual(get_response.status_code, 200)
+
+    def test_facility_admin_can_access_list(self):
+        self.client.login(username=self.facility_admin.username, password=DUMMY_PASSWORD)
+        get_response = self.client.get(reverse(self.lessonreport_basename + '-list'))
+
+        self.assertEqual(get_response.status_code, 200)
+
+    def test_anon_user_cannot_access_detail(self):
+        get_response = self.client.get(reverse(self.lessonreport_basename + '-detail', kwargs={'pk': self.lesson.id}))
+
+        self.assertEqual(get_response.status_code, 403)
+
+    def test_learner_cannot_access_detail(self):
+        self.client.login(username=self.learner.username, password=DUMMY_PASSWORD)
+        get_response = self.client.get(reverse(self.lessonreport_basename + '-detail', kwargs={'pk': self.lesson.id}))
+
+        self.assertEqual(get_response.status_code, 403)
+
+    def test_another_classroom_coach_cannot_access_detail(self):
+        self.client.login(username=self.another_classroom_coach.username, password=DUMMY_PASSWORD)
         get_response = self.client.get(reverse(self.lessonreport_basename + '-detail', kwargs={'pk': self.lesson.id}))
+
         self.assertEqual(get_response.status_code, 403)
 
+    def test_classroom_coach_can_access_detail(self):
+        self.client.login(username=self.classroom_coach.username, password=DUMMY_PASSWORD)
+        get_response = self.client.get(reverse(self.lessonreport_basename + '-detail', kwargs={'pk': self.lesson.id}))
+
+        self.assertEqual(get_response.status_code, 200)
+
+    def test_facility_coach_can_access_detail(self):
+        self.client.login(username=self.facility_coach.username, password=DUMMY_PASSWORD)
+        get_response = self.client.get(reverse(self.lessonreport_basename + '-detail', kwargs={'pk': self.lesson.id}))
+
+        self.assertEqual(get_response.status_code, 200)
+
+    def test_facility_admin_can_access_detail(self):
+        self.client.login(username=self.facility_admin.username, password=DUMMY_PASSWORD)
+        get_response = self.client.get(reverse(self.lessonreport_basename + '-detail', kwargs={'pk': self.lesson.id}))
+
+        self.assertEqual(get_response.status_code, 200)
+
     def test_no_progress_logged(self):
-        self.client.login(username='admin', password='password')
+        self.client.login(username=self.facility_admin.username, password=DUMMY_PASSWORD)
         get_response = self.client.get(reverse(self.lessonreport_basename + '-detail', kwargs={'pk': self.lesson.id}))
         progress = get_response.data['progress']
         self.assertEqual(len(progress), 1)
@@ -97,14 +182,14 @@ def test_no_progress_logged(self):
 
     def test_some_partial_progress_logged(self):
         ContentSummaryLog.objects.create(
-            user=self.learner_user,
+            user=self.classroom_learner,
             content_id=self.node_1.content_id,
             channel_id=self.node_1.channel_id,
             kind='video',
             progress=0.5,
             start_timestamp=datetime.datetime.now(),
         )
-        self.client.login(username='admin', password='password')
+        self.client.login(username=self.facility_admin.username, password=DUMMY_PASSWORD)
         get_response = self.client.get(reverse(self.lessonreport_basename + '-detail', kwargs={'pk': self.lesson.id}))
         progress = get_response.data['progress']
         self.assertEqual(progress[0], {
@@ -114,14 +199,14 @@ def test_some_partial_progress_logged(self):
 
     def test_some_complete_progress_logged(self):
         ContentSummaryLog.objects.create(
-            user=self.learner_user,
+            user=self.classroom_learner,
             content_id=self.node_1.content_id,
             channel_id=self.node_1.channel_id,
             kind='video',
             progress=1.0,
             start_timestamp=datetime.datetime.now(),
         )
-        self.client.login(username='admin', password='password')
+        self.client.login(username=self.facility_admin.username, password=DUMMY_PASSWORD)
         get_response = self.client.get(reverse(self.lessonreport_basename + '-detail', kwargs={'pk': self.lesson.id}))
         progress = get_response.data['progress']
         self.assertEqual(progress[0], {
@@ -130,6 +215,6 @@ def test_some_complete_progress_logged(self):
         })
 
     def test_total_learners_value(self):
-        self.client.login(username='admin', password='password')
+        self.client.login(username=self.facility_admin.username, password=DUMMY_PASSWORD)
         get_response = self.client.get(reverse(self.lessonreport_basename + '-detail', kwargs={'pk': self.lesson.id}))
         self.assertEqual(get_response.data['total_learners'], 1)