195 lines
		
	
	
	
		
			6.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			195 lines
		
	
	
	
		
			6.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # -*- coding: utf-8; -*-
 | |
| 
 | |
| from unittest.mock import MagicMock, patch
 | |
| 
 | |
| from pyramid.httpexceptions import HTTPFound, HTTPForbidden
 | |
| 
 | |
| from wuttaweb.views import auth as mod
 | |
| from wuttaweb.testing import WebTestCase
 | |
| 
 | |
| 
 | |
| class TestAuthView(WebTestCase):
 | |
| 
 | |
|     def setUp(self):
 | |
|         self.setup_web()
 | |
|         self.pyramid_config.include("wuttaweb.views.common")
 | |
| 
 | |
|     def make_view(self):
 | |
|         return mod.AuthView(self.request)
 | |
| 
 | |
|     def test_includeme(self):
 | |
|         self.pyramid_config.include("wuttaweb.views.auth")
 | |
| 
 | |
|     def test_login(self):
 | |
|         model = self.app.model
 | |
|         auth = self.app.get_auth_handler()
 | |
|         view = self.make_view()
 | |
| 
 | |
|         # until user exists, will redirect
 | |
|         self.assertEqual(self.session.query(model.User).count(), 0)
 | |
|         response = view.login(session=self.session)
 | |
|         self.assertEqual(response.status_code, 302)
 | |
| 
 | |
|         # make a user
 | |
|         barney = model.User(username="barney")
 | |
|         auth.set_user_password(barney, "testpass")
 | |
|         self.session.add(barney)
 | |
|         self.session.commit()
 | |
| 
 | |
|         # now since user exists, form will display
 | |
|         context = view.login(session=self.session)
 | |
|         self.assertIn("form", context)
 | |
| 
 | |
|         # redirect if user already logged in
 | |
|         with patch.object(self.request, "user", new=barney):
 | |
|             view = self.make_view()
 | |
|             response = view.login(session=self.session)
 | |
|         self.assertEqual(response.status_code, 302)
 | |
| 
 | |
|         # login fails w/ wrong password
 | |
|         self.request.method = "POST"
 | |
|         self.request.POST = {"username": "barney", "password": "WRONG"}
 | |
|         view = self.make_view()
 | |
|         context = view.login(session=self.session)
 | |
|         self.assertIn("form", context)
 | |
| 
 | |
|         # redirect if login succeeds
 | |
|         self.request.method = "POST"
 | |
|         self.request.POST = {"username": "barney", "password": "testpass"}
 | |
|         view = self.make_view()
 | |
|         response = view.login(session=self.session)
 | |
|         self.assertEqual(response.status_code, 302)
 | |
| 
 | |
|     def test_logout(self):
 | |
|         self.pyramid_config.add_route("login", "/login")
 | |
|         view = self.make_view()
 | |
|         self.request.session.delete = MagicMock()
 | |
|         response = view.logout()
 | |
|         self.request.session.delete.assert_called_once_with()
 | |
|         self.assertEqual(response.status_code, 302)
 | |
| 
 | |
|     def test_change_password(self):
 | |
|         model = self.app.model
 | |
|         auth = self.app.get_auth_handler()
 | |
|         barney = model.User(username="barney")
 | |
|         self.session.add(barney)
 | |
|         self.session.commit()
 | |
|         view = self.make_view()
 | |
| 
 | |
|         # unauthenticated user is redirected
 | |
|         redirect = view.change_password()
 | |
|         self.assertIsInstance(redirect, HTTPFound)
 | |
| 
 | |
|         # set initial password
 | |
|         auth.set_user_password(barney, "foo")
 | |
|         self.session.commit()
 | |
| 
 | |
|         # forbidden if prevent_edit is set for user
 | |
|         self.request.user = barney
 | |
|         barney.prevent_edit = True
 | |
|         self.assertRaises(HTTPForbidden, view.change_password)
 | |
| 
 | |
|         # okay let's test with edit allowed
 | |
|         barney.prevent_edit = False
 | |
| 
 | |
|         # view should now return context w/ form
 | |
|         context = view.change_password()
 | |
|         self.assertIn("form", context)
 | |
| 
 | |
|         # submit valid form, ensure password is changed
 | |
|         # (nb. this also would redirect user to home page)
 | |
|         self.request.method = "POST"
 | |
|         self.request.POST = {
 | |
|             "current_password": "foo",
 | |
|             # nb. new_password requires colander mapping structure
 | |
|             "__start__": "new_password:mapping",
 | |
|             "new_password": "bar",
 | |
|             "new_password-confirm": "bar",
 | |
|             "__end__": "new_password:mapping",
 | |
|         }
 | |
|         redirect = view.change_password()
 | |
|         self.assertIsInstance(redirect, HTTPFound)
 | |
|         self.session.commit()
 | |
|         self.assertFalse(auth.check_user_password(barney, "foo"))
 | |
|         self.assertTrue(auth.check_user_password(barney, "bar"))
 | |
| 
 | |
|         # at this point 'foo' is the password, now let's submit some
 | |
|         # invalid forms and make sure we get back a context w/ form
 | |
| 
 | |
|         # first try empty data
 | |
|         self.request.POST = {}
 | |
|         context = view.change_password()
 | |
|         self.assertIn("form", context)
 | |
|         dform = context["form"].get_deform()
 | |
|         self.assertEqual(dform["current_password"].errormsg, "Required")
 | |
|         self.assertEqual(dform["new_password"].errormsg, "Required")
 | |
| 
 | |
|         # now try bad current password
 | |
|         self.request.POST = {
 | |
|             "current_password": "blahblah",
 | |
|             "__start__": "new_password:mapping",
 | |
|             "new_password": "baz",
 | |
|             "new_password-confirm": "baz",
 | |
|             "__end__": "new_password:mapping",
 | |
|         }
 | |
|         context = view.change_password()
 | |
|         self.assertIn("form", context)
 | |
|         dform = context["form"].get_deform()
 | |
|         self.assertEqual(
 | |
|             dform["current_password"].errormsg, "Current password is incorrect."
 | |
|         )
 | |
| 
 | |
|         # now try bad new password
 | |
|         self.request.POST = {
 | |
|             "current_password": "bar",
 | |
|             "__start__": "new_password:mapping",
 | |
|             "new_password": "bar",
 | |
|             "new_password-confirm": "bar",
 | |
|             "__end__": "new_password:mapping",
 | |
|         }
 | |
|         context = view.change_password()
 | |
|         self.assertIn("form", context)
 | |
|         dform = context["form"].get_deform()
 | |
|         self.assertEqual(
 | |
|             dform["new_password"].errormsg,
 | |
|             "New password must be different from old password.",
 | |
|         )
 | |
| 
 | |
|     def test_become_root(self):
 | |
|         view = mod.AuthView(self.request)
 | |
| 
 | |
|         # GET not allowed
 | |
|         self.request.method = "GET"
 | |
|         self.assertRaises(HTTPForbidden, view.become_root)
 | |
| 
 | |
|         # non-admin users also not allowed
 | |
|         self.request.method = "POST"
 | |
|         self.request.is_admin = False
 | |
|         self.assertRaises(HTTPForbidden, view.become_root)
 | |
| 
 | |
|         # but admin users can become root
 | |
|         self.request.is_admin = True
 | |
|         self.assertNotIn("is_root", self.request.session)
 | |
|         redirect = view.become_root()
 | |
|         self.assertIsInstance(redirect, HTTPFound)
 | |
|         self.assertTrue(self.request.session["is_root"])
 | |
| 
 | |
|     def test_stop_root(self):
 | |
|         view = mod.AuthView(self.request)
 | |
| 
 | |
|         # GET not allowed
 | |
|         self.request.method = "GET"
 | |
|         self.assertRaises(HTTPForbidden, view.stop_root)
 | |
| 
 | |
|         # non-admin users also not allowed
 | |
|         self.request.method = "POST"
 | |
|         self.request.is_admin = False
 | |
|         self.assertRaises(HTTPForbidden, view.stop_root)
 | |
| 
 | |
|         # but admin users can stop being root
 | |
|         # (nb. there is no check whether user is currently root)
 | |
|         self.request.is_admin = True
 | |
|         self.assertNotIn("is_root", self.request.session)
 | |
|         redirect = view.stop_root()
 | |
|         self.assertIsInstance(redirect, HTTPFound)
 | |
|         self.assertFalse(self.request.session["is_root"])
 |