from unittest import mock from django.contrib.auth.models import Group, Permission, User from django.core.urlresolvers import reverse from django.test import RequestFactory, TestCase from kfet.forms import UserGroupForm from kfet.models import Account from . import KFET_GENERIC_TRIGRAMME, KFET_GENERIC_USERNAME from .backends import AccountBackend, GenericBackend from .middleware import TemporaryAuthMiddleware from .models import GenericTeamToken from .utils import get_kfet_generic_user ## # Forms ## class UserGroupFormTests(TestCase): """Test suite for UserGroupForm.""" def setUp(self): # create user self.user = User.objects.create(username="foo", password="foo") # create some K-Fêt groups prefix_name = "K-Fêt " names = ["Group 1", "Group 2", "Group 3"] self.kfet_groups = [ Group.objects.create(name=prefix_name + name) for name in names ] # create a non-K-Fêt group self.other_group = Group.objects.create(name="Other group") def test_choices(self): """Only K-Fêt groups are selectable.""" form = UserGroupForm(instance=self.user) groups_field = form.fields["groups"] self.assertQuerysetEqual( groups_field.queryset, [repr(g) for g in self.kfet_groups], ordered=False ) def test_keep_others(self): """User stays in its non-K-Fêt groups.""" user = self.user # add user to a non-K-Fêt group user.groups.add(self.other_group) # add user to some K-Fêt groups through UserGroupForm data = {"groups": [group.pk for group in self.kfet_groups]} form = UserGroupForm(data, instance=user) form.is_valid() form.save() self.assertQuerysetEqual( user.groups.all(), [repr(g) for g in [self.other_group] + self.kfet_groups], ordered=False, ) class KFetGenericUserTests(TestCase): def test_exists(self): """ The account is set up when app is ready, so it should exist. """ generic = Account.objects.get_generic() self.assertEqual(generic.trigramme, KFET_GENERIC_TRIGRAMME) self.assertEqual(generic.user.username, KFET_GENERIC_USERNAME) self.assertEqual(get_kfet_generic_user(), generic.user) ## # Backends ## class AccountBackendTests(TestCase): def setUp(self): self.request = RequestFactory().get("/") def test_valid(self): acc = Account(trigramme="000") acc.change_pwd("valid") acc.save({"username": "user"}) auth = AccountBackend().authenticate(self.request, kfet_password="valid") self.assertEqual(auth, acc.user) def test_invalid(self): auth = AccountBackend().authenticate(self.request, kfet_password="invalid") self.assertIsNone(auth) class GenericBackendTests(TestCase): def setUp(self): self.request = RequestFactory().get("/") def test_valid(self): token = GenericTeamToken.objects.create_token() auth = GenericBackend().authenticate(self.request, kfet_token=token.token) self.assertEqual(auth, get_kfet_generic_user()) self.assertEqual(GenericTeamToken.objects.all().count(), 0) def test_invalid(self): auth = GenericBackend().authenticate(self.request, kfet_token="invalid") self.assertIsNone(auth) ## # Views ## class GenericLoginViewTests(TestCase): def setUp(self): user_acc = Account(trigramme="000") user_acc.save({"username": "user"}) self.user = user_acc.user self.user.set_password("user") self.user.save() team_acc = Account(trigramme="100") team_acc.save({"username": "team"}) self.team = team_acc.user self.team.set_password("team") self.team.save() self.team.user_permissions.add( Permission.objects.get(content_type__app_label="kfet", codename="is_team") ) self.url = reverse("kfet.login.generic") self.generic_user = get_kfet_generic_user() def test_url(self): self.assertEqual(self.url, "/k-fet/login/generic") def test_get(self): """ Send confirmation for user to emit POST request, instead of GET. """ self.client.login(username="team", password="team") r = self.client.get(self.url) self.assertEqual(r.status_code, 200) self.assertTemplateUsed(r, "kfet/confirm_form.html") def test_post(self): """ The kfet generic user is logged in. """ self.client.login(username="team", password="team") r = self.client.post(self.url) self.assertRedirects(r, reverse("kfet.kpsul")) self.assertEqual(r.wsgi_request.user, self.generic_user) with self.assertRaises(GenericTeamToken.DoesNotExist): GenericTeamToken.objects.get() def test_not_team(self): """ Logged in user must be a team user to initiate login as generic user. """ self.client.login(username="user", password="user") # With GET. r = self.client.get(self.url) self.assertRedirects( r, "/profil/login/?next={}".format(self.url), fetch_redirect_response=False ) # Also with POST. r = self.client.post(self.url) self.assertRedirects( r, "/profil/login/?next={}".format(self.url), fetch_redirect_response=False ) def test_post_redirect(self): """ A team user is logged in as the kfet generic user. """ self.client.login(username="team", password="team") next_url = "/any-url/" url = self.url + "?next=" + next_url r = self.client.post(url) self.assertRedirects(r, next_url, fetch_redirect_response=False) self.assertEqual(r.wsgi_request.user, self.generic_user) ## # Temporary authentication # # Includes: # - TemporaryAuthMiddleware # - temporary_auth context processor ## class TemporaryAuthTests(TestCase): def setUp(self): self.factory = RequestFactory() self.middleware = TemporaryAuthMiddleware(mock.Mock()) user1_acc = Account(trigramme="000") user1_acc.change_pwd("kfet_user1") user1_acc.save({"username": "user1"}) self.user1 = user1_acc.user self.user1.set_password("user1") self.user1.save() user2_acc = Account(trigramme="100") user2_acc.change_pwd("kfet_user2") user2_acc.save({"username": "user2"}) self.user2 = user2_acc.user self.user2.set_password("user2") self.user2.save() self.perm = Permission.objects.get( content_type__app_label="kfet", codename="is_team" ) self.user2.user_permissions.add(self.perm) def test_middleware_header(self): """ A user can be authenticated if ``HTTP_KFETPASSWORD`` header of a request contains a valid kfet password. """ request = self.factory.get("/", HTTP_KFETPASSWORD="kfet_user2") request.user = self.user1 self.middleware(request) self.assertEqual(request.user, self.user2) self.assertEqual(request.real_user, self.user1) def test_middleware_post(self): """ A user can be authenticated if ``KFETPASSWORD`` of POST data contains a valid kfet password. """ request = self.factory.post("/", {"KFETPASSWORD": "kfet_user2"}) request.user = self.user1 self.middleware(request) self.assertEqual(request.user, self.user2) self.assertEqual(request.real_user, self.user1) def test_middleware_invalid(self): """ The given password must be a password of an Account. """ request = self.factory.post("/", {"KFETPASSWORD": "invalid"}) request.user = self.user1 self.middleware(request) self.assertEqual(request.user, self.user1) self.assertFalse(hasattr(request, "real_user")) def test_context_processor(self): """ Context variables give the real authenticated user and his permissions. """ self.client.login(username="user1", password="user1") r = self.client.get("/k-fet/accounts/", HTTP_KFETPASSWORD="kfet_user2") self.assertEqual(r.context["user"], self.user1) self.assertNotIn("kfet.is_team", r.context["perms"]) def test_auth_not_persistent(self): """ The authentication is temporary, i.e. for one request. """ self.client.login(username="user1", password="user1") r1 = self.client.get("/k-fet/accounts/", HTTP_KFETPASSWORD="kfet_user2") self.assertEqual(r1.wsgi_request.user, self.user2) r2 = self.client.get("/k-fet/accounts/") self.assertEqual(r2.wsgi_request.user, self.user1)