"""
Tests dealing with user management and credetials storage.
"""

#c Copyright 2008-2021, the GAVO project
#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 svcs
from gavo.protocols import creds


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 = testhelpers.FakeRequest(user="testing", password="testing")
		self.assertEqual(req.getAuthUser(), "testing")

	def testBytesAuth(self):
		req = testhelpers.FakeRequest(user=b"testing", password="testing")
		self.assertEqual(req.getAuthUser(), "testing")

	def testBadAuth(self):
		req = testhelpers.FakeRequest(user="testing", password="not-testing")
		self.assertEqual(req.getAuthUser(), None)

	def testNoAuth(self):
		req = testhelpers.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):
		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", ""))

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)
