diff --git a/jdav_web/members/tests.py b/jdav_web/members/tests.py index 7f04666..1490f00 100644 --- a/jdav_web/members/tests.py +++ b/jdav_web/members/tests.py @@ -1,22 +1,33 @@ +from django.contrib.auth import models as authmodels +from django.contrib.admin.sites import AdminSite +from django.contrib.messages import get_messages from django.contrib.auth.models import User -from django.test import TestCase, Client +from django.test import TestCase, Client, RequestFactory from django.utils import timezone, translation from django.conf import settings from django.urls import reverse -from .models import Member, Group, PermissionMember, PermissionGroup, Freizeit, GEMEINSCHAFTS_TOUR, MUSKELKRAFT_ANREISE +from .models import Member, Group, PermissionMember, PermissionGroup, Freizeit, GEMEINSCHAFTS_TOUR, MUSKELKRAFT_ANREISE,\ + MemberNoteList, NewMemberOnList from django.db import connection from django.db.migrations.executor import MigrationExecutor +from .admin import FreizeitAdmin -class Migrator: - def __init__(self, connection=connection): - self.executor = MigrationExecutor(connection) - def migrate(self, app_label: str, migration: str): - target = [(app_label, migration)] - self.executor.loader.build_graph() - self.executor.migrate(target) - self.apps = self.executor.loader.project_state(target).apps +def create_custom_user(username, groups, prename, lastname): + user = User.objects.create_user( + username=username, password='secret' + ) + member = Member.objects.create(prename=prename, lastname=lastname, birth_date=timezone.localdate(), email=settings.TEST_MAIL) + member.user = user + member.save() + user.is_staff = True + user.save() + + for group in groups: + g = authmodels.Group.objects.get(name=group) + user.groups.add(g) + return user class MemberTestCase(TestCase): @@ -108,16 +119,25 @@ class PDFTestCase(TestCase): tour_type=GEMEINSCHAFTS_TOUR, tour_approach=MUSKELKRAFT_ANREISE, difficulty=1) + self.note = MemberNoteList.objects.create(title='Cool list') + + for i in range(7): + m = Member.objects.create(prename='Lise {}'.format(i), lastname='Walter', birth_date=timezone.now().date(), + email=settings.TEST_MAIL) + NewMemberOnList.objects.create(member=m, comments='a' * i, memberlist=self.ex) + NewMemberOnList.objects.create(member=m, comments='a' * i, memberlist=self.note) User.objects.create_superuser( username='superuser', password='secret' ) + standard = create_custom_user('standard', ['Standard'], 'Paul', 'Wulter') - def _test_pdf(self, name, invalid=False): + def _test_pdf(self, name, model='freizeit', invalid=False, username='superuser'): c = Client() - c.login(username='superuser', password='secret') + c.login(username=username, password='secret') - url = reverse('admin:members_freizeit_action', args=(self.ex.pk,)) + pk = self.ex.pk if model == 'freizeit' else self.note.pk + url = reverse('admin:members_%s_action' % model, args=(pk,)) response = c.post(url, {name: 'hoho'}) if not invalid: self.assertEqual(response.status_code, 200, 'Response code is not 200.') @@ -126,33 +146,115 @@ class PDFTestCase(TestCase): self.assertEqual(response.status_code, 302, 'Response code is not 302.') def test_crisis_intervention_list(self): - return self._test_pdf('crisis_intervention_list') + self._test_pdf('crisis_intervention_list') + self._test_pdf('crisis_intervention_list', username='standard', invalid=True) def test_notes_list(self): - return self._test_pdf('notes_list') + self._test_pdf('notes_list') + self._test_pdf('notes_list', username='standard', invalid=True) def test_seminar_report(self): - return self._test_pdf('seminar_report') + self._test_pdf('seminar_report') + self._test_pdf('seminar_report', username='standard', invalid=True) - def test_wrong_action(self): + def test_membernote_summary(self): + self._test_pdf('summary', model='membernotelist') + self._test_pdf('summary', model='membernotelist', username='standard', invalid=True) + + def test_wrong_action_freizeit(self): return self._test_pdf('asdf', invalid=True) + def test_wrong_action_membernotelist(self): + return self._test_pdf('asdf', invalid=True, model='membernotelist') -class MemberAdminTestCase(TestCase): - def setUp(self): + +class AdminTestCase(TestCase): + def setUp(self, model): + self.factory = RequestFactory() + self.model = model + if model is not None: + self.admin = FreizeitAdmin(model, AdminSite()) User.objects.create_superuser( username='superuser', password='secret' ) - for i in range(100): - self.m = Member.objects.create(prename='Fritz {}'.format(i), lastname='Walter', birth_date=timezone.now().date(), - email=settings.TEST_MAIL) + standard = create_custom_user('standard', ['Standard'], 'Paul', 'Wulter') + trainer = create_custom_user('trainer', ['Standard', 'Trainings'], 'Lise', 'Lotte') + treasurer = create_custom_user('treasurer', ['Standard', 'Finance'], 'Lara', 'Litte') + materialwarden = create_custom_user('materialwarden', ['Standard', 'Material'], 'Loro', 'Lutte') + + paul = standard.member + + staff = Group.objects.create(name='Jugendleiter') + cool_kids = Group.objects.create(name='cool kids') + super_kids = Group.objects.create(name='super kids') + p1 = PermissionMember.objects.create(member=paul) + p1.view_groups.add(cool_kids) + p1.list_groups.add(super_kids) + p1.list_groups.add(cool_kids) + + for i in range(3): + m = Member.objects.create(prename='Fritz {}'.format(i), lastname='Walter', birth_date=timezone.now().date(), + email=settings.TEST_MAIL) + m.group.add(cool_kids) + m.save() + for i in range(7): + m = Member.objects.create(prename='Lise {}'.format(i), lastname='Walter', birth_date=timezone.now().date(), + email=settings.TEST_MAIL) + m.group.add(super_kids) + m.save() + for i in range(5): + m = Member.objects.create(prename='Lulla {}'.format(i), lastname='Hulla', birth_date=timezone.now().date(), + email=settings.TEST_MAIL) + m.group.add(staff) + m.save() + m = Member.objects.create(prename='Peter', lastname='Hulla', birth_date=timezone.now().date(), + email=settings.TEST_MAIL) + m.group.add(staff) + p1.list_members.add(m) def _login(self, name): c = Client() - c.login(username=name, password='secret') + res = c.login(username=name, password='secret') + # make sure we logged in + assert res return c + +class PermissionTestCase(AdminTestCase): + def setUp(self): + super().setUp(model=None) + + def test_standard_permissions(self): + u = User.objects.get(username='standard') + self.assertTrue(u.has_perm('members.view_member')) + + def test_queryset_standard(self): + u = User.objects.get(username='standard') + queryset = u.member.filter_queryset_by_permissions(model=Member) + super_kids = Group.objects.get(name='super kids') + super_kid = super_kids.member_set.first() + self.assertTrue(super_kid in queryset, 'super kid is not in queryset for Paul.') + + def test_queryset_trainer(self): + u = User.objects.get(username='trainer') + queryset = u.member.filter_queryset_by_permissions(model=Member) + self.assertEqual(set(queryset), {u.member}, 'Filtering trainer queryset yields more the trainer.') + + +class MemberAdminTestCase(AdminTestCase): + def setUp(self): + super().setUp(model=Member) + cool_kids = Group.objects.get(name='cool kids') + super_kids = Group.objects.get(name='super kids') + mega_kids = Group.objects.create(name='mega kids') + + for i in range(1): + m = Member.objects.create(prename='Peter {}'.format(i), lastname='Walter', birth_date=timezone.now().date(), + email=settings.TEST_MAIL) + m.group.add(mega_kids) + m.save() + def test_changelist(self): c = self._login('superuser') @@ -163,7 +265,9 @@ class MemberAdminTestCase(TestCase): def test_change(self): c = self._login('superuser') - url = reverse('admin:members_member_change', args=(self.m.pk,)) + mega_kids = Group.objects.get(name='mega kids') + mega_kid = mega_kids.member_set.first() + url = reverse('admin:members_member_change', args=(mega_kid.pk,)) response = c.get(url) self.assertEqual(response.status_code, 200, 'Response code is not 200.') @@ -171,3 +275,167 @@ class MemberAdminTestCase(TestCase): url = reverse('admin:members_member_change', args=(71233,)) response = c.get(url) self.assertEqual(response.status_code, 302, 'Response code is not 302.') + + def test_changelist_standard(self): + c = self._login('standard') + + url = reverse('admin:members_member_changelist') + response = c.get(url) + self.assertEqual(response.status_code, 200, 'Response code is not 200.') + + results = response.context['results'] + for result in results: + name_or_link_field = result[1] + group_field = result[4] + self.assertFalse('mega kids' in group_field, 'Standard can list a mega kid.') + if 'cool kids' in group_field: + self.assertTrue('href' in name_or_link_field) + elif 'super kids' in group_field: + self.assertFalse('href' in name_or_link_field) + + + def test_changelist_trainer(self): + c = self._login('trainer') + + url = reverse('admin:members_member_changelist') + response = c.get(url) + # should not redirect + self.assertEqual(response.status_code, 200, 'Response code is not 200.') + + # trainers can view everyone, so there should be links in every row + results = response.context['results'] + for result in results: + name_or_link_field = result[1] + group_field = result[4] + self.assertTrue('href' in name_or_link_field) + + + def test_changelist_materialwarden(self): + u = User.objects.get(username='materialwarden') + c = self._login('materialwarden') + + url = reverse('admin:members_member_changelist') + response = c.get(url) + # should not redirect + self.assertEqual(response.status_code, 200, 'Response code is not 200.') + + # materialwarden people can list everyone, but only view themselves by default + results = response.context['results'] + for result in results: + name_or_link_field = result[1] + group_field = result[4] + self.assertFalse('href' in name_or_link_field and str(u.member.pk) not in name_or_link_field) + + # now set member to None + m = u.member + m.user = None + m.save() + + response = c.get(url) + # should not redirect + self.assertEqual(response.status_code, 200, 'Response code is not 200.') + + # since materialwarden has no member associated, no one should be viewable + results = response.context['results'] + for result in results: + name_or_link_field = result[1] + group_field = result[4] + self.assertFalse('href' in name_or_link_field) + + + def test_change_standard(self): + u = User.objects.get(username='standard') + self.assertTrue(hasattr(u, 'member')) + c = self._login('standard') + + cool_kids = Group.objects.get(name='cool kids') + cool_kid = cool_kids.member_set.first() + + self.assertTrue(u.has_perm('members.view_obj_member', cool_kid)) + self.assertFalse(u.has_perm('members.change_obj_member', cool_kid)) + self.assertFalse(u.has_perm('members.delete_obj_member', cool_kid)) + self.assertTrue(hasattr(u, 'member')) + url = reverse('admin:members_member_change', args=(cool_kid.pk,)) + response = c.get(url, follow=True) + + super_kids = Group.objects.get(name='super kids') + super_kid = super_kids.member_set.first() + url = reverse('admin:members_member_change', args=(super_kid.pk,)) + response = c.get(url, follow=True) + final = response.redirect_chain[-1][0] + final_target = reverse('admin:members_member_changelist') + self.assertEqual(response.status_code, 200, 'Response code is not 200.') + self.assertEqual(final, final_target, 'Did redirect to wrong url.') + + +class FreizeitAdminTestCase(AdminTestCase): + def setUp(self): + super().setUp(model=Freizeit) + ex = Freizeit.objects.create(name='Wild trip', kilometers_traveled=120, + tour_type=GEMEINSCHAFTS_TOUR, + tour_approach=MUSKELKRAFT_ANREISE, + difficulty=1) + + for i in range(7): + m = Member.objects.create(prename='Lise {}'.format(i), lastname='Walter', birth_date=timezone.now().date(), + email=settings.TEST_MAIL) + NewMemberOnList.objects.create(member=m, comments='a' * i, memberlist=ex) + + def test_changelist(self): + c = self._login('superuser') + + url = reverse('admin:members_freizeit_changelist') + response = c.get(url) + self.assertEqual(response.status_code, 200, 'Response code is not 200.') + + def test_change(self): + c = self._login('superuser') + + ex = Freizeit.objects.get(name='Wild trip') + url = reverse('admin:members_freizeit_change', args=(ex.pk,)) + response = c.get(url) + self.assertEqual(response.status_code, 200, 'Response code is not 200.') + + # if excursion does not exist, expect redirect + url = reverse('admin:members_freizeit_change', args=(71233,)) + response = c.get(url) + self.assertEqual(response.status_code, 302, 'Response code is not 302.') + + def test_add(self): + c = self._login('standard') + + url = reverse('admin:members_freizeit_add') + response = c.get(url) + self.assertEqual(response.status_code, 200, 'Response code is not 200.') + + u = User.objects.get(username='standard') + + request = self.factory.get(url) + request.user = u + #staff = Group.objects.get(name='Jugendleiter') + field = Freizeit._meta.get_field('jugendleiter') + queryset = self.admin.formfield_for_manytomany(field, request).queryset + self.assertQuerysetEqual(queryset, u.member.filter_queryset_by_permissions(model=Member), + msg='Field queryset does not match filtered queryset from models.', + ordered=False) + + u.member.user = None + queryset = self.admin.formfield_for_manytomany(field, request).queryset + self.assertQuerysetEqual(queryset, Member.objects.none()) + + c = self._login('materialwarden') + response = c.get(url) + self.assertEqual(response.status_code, 200, 'Response code is not 200.') + + u = User.objects.get(username='materialwarden') + + request.user = u + field = Freizeit._meta.get_field('jugendleiter') + queryset = self.admin.formfield_for_manytomany(field, request).queryset + # material warden can list everyone + self.assertQuerysetEqual(queryset, Member.objects.all(), + msg='Field queryset does not match all members.', + ordered=False) + + queryset = self.admin.formfield_for_manytomany(field, None).queryset + self.assertQuerysetEqual(queryset, Member.objects.none())