import unittest from patchbay_web import security from patchbay_web.conf import Config from .helpers import AppCase class AuthTest(AppCase): def test_sysop_password_hashed_on_start(self): conf = Config(self.conf_path) self.assertTrue(conf.get("sysoppassword").startswith("$scrypt$")) with open(self.conf_path) as f: self.assertIn("# test config", f.read()) def test_login_2fa(self): r = self.login() self.assertEqual(r.status_code, 302) self.assertEqual(self.mails[-1][0], "admin@example.org") self.assertEqual(self.client.get("/patch").status_code, 200) def test_wrong_password(self): r = self.login(password="nope") self.assertEqual(r.status_code, 401) self.assertEqual(self.mails, []) def test_wrong_code_then_expired_attempts(self): tok = self.csrf() self.client.post("/login", data={"username": "admin", "password": "correct horse battery", "csrf_token": tok}) tok = self.token_from("/verify") for _ in range(5): r = self.client.post("/verify", data={"code": "000000", "csrf_token": tok}) r = self.client.post("/verify", data={"code": "000000", "csrf_token": tok}) self.assertEqual(r.status_code, 302) # sent back to login self.assertEqual(self.client.get("/patch").status_code, 302) def test_csrf_required(self): self.login() r = self.client.post("/settings/users/add", data={"username": "bob"}) self.assertEqual(r.status_code, 400) def test_requires_login(self): self.assertEqual(self.client.get("/settings").status_code, 302) self.assertEqual(self.client.get("/api/graph").status_code, 401) def test_help_page(self): self.assertEqual(self.client.get("/help").status_code, 302) self.login() r = self.client.get("/help") self.assertEqual(r.status_code, 200) self.assertIn(b"Transparent source spoofing", r.data) def test_user_management_sysop_only(self): self.login() tok = self.token() r = self.client.post("/settings/users/add", data={ "username": "bob", "email": "bob@example.org", "password": "0123456789x", "csrf_token": tok}) self.assertEqual(r.status_code, 302) self.client.post("/logout", data={"csrf_token": tok}) self.assertEqual(self.login("bob", "0123456789x").status_code, 302) tok = self.token() r = self.client.post("/settings/users/add", data={ "username": "eve", "email": "e@example.org", "password": "0123456789x", "csrf_token": tok}) self.assertEqual(r.status_code, 403) def test_rate_limit(self): for _ in range(10): self.login(password="bad") self.assertEqual(self.login().status_code, 429) class SecurityTest(unittest.TestCase): def test_hash_roundtrip(self): h = security.hash_password("hunter22") self.assertTrue(security.verify_password("hunter22", h)) self.assertFalse(security.verify_password("hunter23", h)) self.assertFalse(security.verify_password("x", None)) if __name__ == "__main__": unittest.main()