1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
|
"""
Tests dealing with user management and credetials storage.
"""
#c Copyright 2008-2024, the GAVO project <gavo@ari.uni-heidelberg.de>
#c
#c This program is free software, covered by the GNU GPL. See the
#c COPYING file in the source distribution.
from gavo.helpers import testhelpers
import tresc
from gavo import base
from gavo import svcs
from gavo.helpers import trialhelpers
from gavo.protocols import creds
class UserManagementTest(testhelpers.VerboseTest):
resources = [("conn", tresc.dbConnection)]
def tearDown(self):
self.conn.rollback()
creds.delUser(self.conn, "deleteme")
def testAdding(self):
creds.addUser(self.conn, "deleteme", "deleteme",
"Argl! Stuff spilled out from a unit test.")
with testhelpers.forceConnection(self.conn):
self.assertTrue(
creds.hasCredentials("deleteme", "deleteme", "deleteme"))
self.assertFalse(
creds.hasCredentials("deleteme", "deleteme", "admin"))
self.assertFalse(
creds.hasCredentials("deleteme", "deletee", "deleteme"))
def testPasswordCrypting(self):
creds.addUser(self.conn, "deleteme", "deleteme",
"Argl! Stuff spilled out from a unit test.")
storedForm = next(self.conn.query(
"select password from dc.users where username='deleteme'"))[0]
self.assertTrue(storedForm.startswith("scrypt:"))
def testChanging(self):
creds.addUser(self.conn, "deleteme", "deleteme",
"Argl! Stuff spilled out from a unit test.")
oldStoredForm = next(self.conn.query(
"select password from dc.users where username='deleteme'"))[0]
creds.changeUser(self.conn, "deleteme", "changed", "New spill.")
newStoredForm, newRemark = next(self.conn.query(
"select password, remarks from dc.users where username='deleteme'"))
self.assertEqual(newRemark, "New spill.")
self.assertNotEqual(oldStoredForm, newStoredForm)
creds.changeUser(self.conn, "deleteme", "changedAgain")
newestStoredForm = next(self.conn.query(
"select password from dc.users where username='deleteme'"))
self.assertNotEqual(newStoredForm, newestStoredForm)
def testChangingRaises(self):
# this also serves as a test for delUser, as this will fail if it's
# not done its work
self.assertRaisesWithMsg(base.ReportableError,
"User deleteme does not exist.",
creds.changeUser,
(self.conn, "deleteme", "should not work"))
class GroupsMembershipTest(testhelpers.VerboseTest):
resources = [('querier', tresc.testUsers)]
def testGroupsForUser(self):
self.assertEqual(creds.getGroupsForUser("X_test", "wrongpass"),
set(), "Wrong password should yield empty set but doesn't")
self.assertEqual(creds.getGroupsForUser("X_test", "megapass"),
set(["X_test", "Y_test"]))
self.assertEqual(creds.getGroupsForUser("Y_test", "megapass"),
set(["Y_test"]))
class AuthUserTest(testhelpers.VerboseTest):
def testOkAuth(self):
req = trialhelpers.FakeRequest(user="testing", password="testing")
self.assertEqual(req.getAuthUser(), "testing")
def testBytesAuth(self):
req = trialhelpers.FakeRequest(user=b"testing", password="testing")
self.assertEqual(req.getAuthUser(), "testing")
def testBadAuth(self):
req = trialhelpers.FakeRequest(user="testing", password="not-testing")
self.assertEqual(req.getAuthUser(), None)
def testNoAuth(self):
req = trialhelpers.FakeRequest(password="testing")
self.assertEqual(req.getAuthUser(), None)
class GavoAdminTest(testhelpers.VerboseTest):
def testGavoAdminMatches(self):
self.assertTrue(creds.hasCredentials(
"gavoadmin", "this is the unittest suite", "sharks"))
def testGavoAdminGroups(self):
self.assertTrue("just anything" in
creds.getGroupsForUser("gavoadmin", "this is the unittest suite"))
def testGavoAdminBadPW(self):
self.assertFalse(creds.hasCredentials(
"gavoadmin", "I made this up", "sharks"))
def testNoAdminWithoutPW(self):
creds.getHashedAdminPassword.cache_clear()
try:
with testhelpers.tempConfig(("web", "adminpasswd", "")):
self.assertFalse(creds.hasCredentials(
"gavoadmin", "this is the unittest suite", "sharks"))
self.assertFalse(creds.hasCredentials(
"gavoadmin", "", "sharks"))
self.assertFalse("just anything" in
creds.getGroupsForUser("gavoadmin", "this is the unittest suite"))
self.assertFalse("just anything" in
creds.getGroupsForUser("gavoadmin", ""))
finally:
creds.getHashedAdminPassword.cache_clear()
def testHashedPW(self):
creds.getHashedAdminPassword.cache_clear()
try:
with testhelpers.tempConfig(("web", "adminpasswd", "scrypt:/FXYR1B7"
"biWqPmLYMqO1ZzVenR9n58fVKDRczcHInLUHoeOP3XUB63cRNFyMOJqelXOqU1YS6"
"KzstnfRJxRRg8kpqWeczbfLq5Y3VjIeCQE=")):
self.assertFalse(creds.hasCredentials(
"gavoadmin", "this is the unittest suite", "sharks"))
self.assertTrue(creds.hasCredentials(
"gavoadmin", "gronk", "sharks"))
self.assertTrue("just anything" in
creds.getGroupsForUser("gavoadmin", "gronk"))
finally:
creds.getHashedAdminPassword.cache_clear()
class SamplePW(testhelpers.TestResource):
def make(self, _):
pw = "Hágebütte"
storedForm = creds.hashPassword(pw)
return pw, storedForm
class PasswordHashingTest(testhelpers.VerboseTest):
resources = [("sample", SamplePW())]
def testComparison(self):
pw, storedForm = self.sample
self.assertTrue(creds.hashMatches(pw, storedForm))
def testSaltPresent(self):
pw, storedForm = self.sample
self.assertTrue(storedForm.startswith("scrypt:"))
self.assertTrue(storedForm != creds.hashPassword(pw),
"No salt added to passwords?")
def testOverlongRejected(self):
_, hash = self.sample
self.assertRaisesWithMsg(svcs.ForbiddenURI,
"You passed in an overlong password."
" The server will not even look at it.",
creds.hashMatches,
("hack"*30, self.sample))
def testBadStoredForm(self):
self.assertRaisesWithMsg(ValueError,
"Bad hash serialisation: 'bizarre:382901fk'",
creds.hashMatches,
("foo", "bizarre:382901fk"))
if __name__=="__main__":
testhelpers.main(PasswordHashingTest)
|