2024-07-13 23:25:20 -05:00
|
|
|
# -*- coding: utf-8; -*-
|
|
|
|
|
|
|
|
from unittest import TestCase
|
|
|
|
|
|
|
|
from wuttjamaican import auth as mod
|
|
|
|
from wuttjamaican.conf import WuttaConfig
|
|
|
|
|
2024-07-14 23:20:44 -05:00
|
|
|
try:
|
|
|
|
import sqlalchemy as sa
|
|
|
|
except ImportError:
|
|
|
|
pass
|
|
|
|
else:
|
2024-07-13 23:25:20 -05:00
|
|
|
|
|
|
|
|
2024-07-14 23:20:44 -05:00
|
|
|
class TestAuthHandler(TestCase):
|
2024-07-13 23:25:20 -05:00
|
|
|
|
2024-07-14 23:20:44 -05:00
|
|
|
def setUp(self):
|
|
|
|
self.config = WuttaConfig()
|
|
|
|
self.app = self.config.get_app()
|
|
|
|
self.handler = mod.AuthHandler(self.config)
|
|
|
|
|
|
|
|
self.engine = sa.create_engine('sqlite://')
|
|
|
|
self.app.model.Base.metadata.create_all(bind=self.engine)
|
|
|
|
self.session = self.make_session()
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
self.session.close()
|
|
|
|
self.app.model.Base.metadata.drop_all(bind=self.engine)
|
|
|
|
|
|
|
|
def make_session(self):
|
|
|
|
return self.app.make_session(bind=self.engine)
|
|
|
|
|
|
|
|
def test_authenticate_user(self):
|
|
|
|
model = self.app.model
|
|
|
|
barney = model.User(username='barney')
|
|
|
|
self.handler.set_user_password(barney, 'goodpass')
|
|
|
|
self.session.add(barney)
|
|
|
|
self.session.commit()
|
|
|
|
|
|
|
|
# login ok
|
|
|
|
user = self.handler.authenticate_user(self.session, 'barney', 'goodpass')
|
|
|
|
self.assertIs(user, barney)
|
|
|
|
|
|
|
|
# can also pass user instead of username
|
|
|
|
user = self.handler.authenticate_user(self.session, barney, 'goodpass')
|
|
|
|
self.assertIs(user, barney)
|
|
|
|
|
|
|
|
# bad password
|
|
|
|
user = self.handler.authenticate_user(self.session, 'barney', 'BADPASS')
|
|
|
|
self.assertIsNone(user)
|
|
|
|
|
|
|
|
# bad username
|
|
|
|
user = self.handler.authenticate_user(self.session, 'NOBODY', 'goodpass')
|
|
|
|
self.assertIsNone(user)
|
|
|
|
|
|
|
|
# inactive user
|
|
|
|
user = self.handler.authenticate_user(self.session, 'barney', 'goodpass')
|
|
|
|
self.assertIs(user, barney)
|
|
|
|
barney.active = False
|
|
|
|
user = self.handler.authenticate_user(self.session, 'barney', 'goodpass')
|
|
|
|
self.assertIsNone(user)
|
|
|
|
|
|
|
|
def test_get_role(self):
|
|
|
|
model = self.app.model
|
|
|
|
myrole = model.Role(name="My Role")
|
|
|
|
self.session.add(myrole)
|
|
|
|
self.session.commit()
|
|
|
|
|
|
|
|
# empty key is ignored
|
|
|
|
role = self.handler.get_role(self.session, None)
|
|
|
|
self.assertIsNone(role)
|
|
|
|
|
|
|
|
# key may be uuid
|
|
|
|
role = self.handler.get_role(self.session, myrole.uuid)
|
|
|
|
self.assertIs(role, myrole)
|
|
|
|
|
|
|
|
# key may be name
|
|
|
|
role = self.handler.get_role(self.session, myrole.name)
|
|
|
|
self.assertIs(role, myrole)
|
|
|
|
|
|
|
|
# key may be represented within a setting
|
|
|
|
self.config.usedb = True
|
|
|
|
role = self.handler.get_role(self.session, 'mykey')
|
|
|
|
self.assertIsNone(role)
|
|
|
|
setting = model.Setting(name='wutta.role.mykey', value=myrole.uuid)
|
|
|
|
self.session.add(setting)
|
|
|
|
self.session.commit()
|
|
|
|
role = self.handler.get_role(self.session, 'mykey')
|
|
|
|
self.assertIs(role, myrole)
|
|
|
|
|
|
|
|
def test_get_user(self):
|
|
|
|
model = self.app.model
|
|
|
|
myuser = model.User(username='myuser')
|
|
|
|
self.session.add(myuser)
|
|
|
|
self.session.commit()
|
|
|
|
|
|
|
|
# empty obj is ignored
|
|
|
|
user = self.handler.get_user(None)
|
|
|
|
self.assertIsNone(user)
|
|
|
|
|
|
|
|
# user is returned as-is
|
|
|
|
user = self.handler.get_user(myuser)
|
|
|
|
self.assertIs(user, myuser)
|
|
|
|
|
2024-07-17 17:46:13 -05:00
|
|
|
# match on User.uuid
|
|
|
|
user = self.handler.get_user(myuser.uuid, session=self.session)
|
|
|
|
self.assertIs(user, myuser)
|
|
|
|
|
|
|
|
# match on User.username
|
|
|
|
user = self.handler.get_user(myuser.username, session=self.session)
|
|
|
|
self.assertIs(user, myuser)
|
|
|
|
|
2024-07-14 23:20:44 -05:00
|
|
|
# find user from person
|
|
|
|
myperson = model.Person(full_name='My Name')
|
|
|
|
self.session.add(myperson)
|
|
|
|
user.person = myperson
|
|
|
|
self.session.commit()
|
|
|
|
user = self.handler.get_user(myperson)
|
|
|
|
self.assertIs(user, myuser)
|
|
|
|
|
|
|
|
def test_make_user(self):
|
|
|
|
model = self.app.model
|
|
|
|
|
|
|
|
# empty user
|
|
|
|
user = self.handler.make_user()
|
|
|
|
self.assertIsInstance(user, model.User)
|
|
|
|
self.assertIsNone(user.username)
|
|
|
|
|
|
|
|
# user is added to session
|
|
|
|
user = self.handler.make_user(session=self.session)
|
|
|
|
self.assertIn(user, self.session)
|
|
|
|
self.session.rollback()
|
|
|
|
self.assertNotIn(user, self.session)
|
|
|
|
|
|
|
|
# default username
|
|
|
|
# nb. this behavior requires a session
|
|
|
|
user = self.handler.make_user(session=self.session)
|
|
|
|
self.assertEqual(user.username, 'newuser')
|
|
|
|
|
|
|
|
def test_delete_user(self):
|
|
|
|
model = self.app.model
|
|
|
|
|
|
|
|
# basics
|
|
|
|
myuser = model.User(username='myuser')
|
|
|
|
self.session.add(myuser)
|
|
|
|
self.session.commit()
|
|
|
|
user = self.session.query(model.User).one()
|
|
|
|
self.assertIs(user, myuser)
|
|
|
|
self.handler.delete_user(user)
|
|
|
|
self.session.commit()
|
|
|
|
self.assertEqual(self.session.query(model.User).count(), 0)
|
|
|
|
|
|
|
|
def test_make_preferred_username(self):
|
|
|
|
model = self.app.model
|
|
|
|
|
|
|
|
# default
|
|
|
|
name = self.handler.make_preferred_username(self.session)
|
|
|
|
self.assertEqual(name, 'newuser')
|
|
|
|
|
|
|
|
# person/first+last
|
|
|
|
person = model.Person(first_name='Barney', last_name='Rubble')
|
|
|
|
name = self.handler.make_preferred_username(self.session, person=person)
|
|
|
|
self.assertEqual(name, 'barney.rubble')
|
|
|
|
|
|
|
|
# person/first
|
|
|
|
person = model.Person(first_name='Barney')
|
|
|
|
name = self.handler.make_preferred_username(self.session, person=person)
|
|
|
|
self.assertEqual(name, 'barney')
|
|
|
|
|
|
|
|
# person/last
|
|
|
|
person = model.Person(last_name='Rubble')
|
|
|
|
name = self.handler.make_preferred_username(self.session, person=person)
|
|
|
|
self.assertEqual(name, 'rubble')
|
|
|
|
|
|
|
|
def test_make_unique_username(self):
|
|
|
|
model = self.app.model
|
|
|
|
|
|
|
|
# default
|
|
|
|
name = self.handler.make_unique_username(self.session)
|
|
|
|
self.assertEqual(name, 'newuser')
|
|
|
|
user = model.User(username=name)
|
|
|
|
self.session.add(user)
|
|
|
|
self.session.commit()
|
|
|
|
|
|
|
|
# counter invoked if name exists
|
|
|
|
name = self.handler.make_unique_username(self.session)
|
|
|
|
self.assertEqual(name, 'newuser01')
|
|
|
|
user = model.User(username=name)
|
|
|
|
self.session.add(user)
|
|
|
|
self.session.commit()
|
|
|
|
|
|
|
|
# starts by getting preferred name
|
|
|
|
person = model.Person(first_name='Barney', last_name='Rubble')
|
|
|
|
name = self.handler.make_unique_username(self.session, person=person)
|
|
|
|
self.assertEqual(name, 'barney.rubble')
|
|
|
|
user = model.User(username=name)
|
|
|
|
self.session.add(user)
|
|
|
|
self.session.commit()
|
|
|
|
|
|
|
|
# counter invoked if name exists
|
|
|
|
name = self.handler.make_unique_username(self.session, person=person)
|
|
|
|
self.assertEqual(name, 'barney.rubble01')
|
|
|
|
|
|
|
|
def test_set_user_password(self):
|
|
|
|
model = self.app.model
|
|
|
|
myuser = model.User(username='myuser')
|
|
|
|
self.session.add(myuser)
|
|
|
|
|
|
|
|
# basics
|
|
|
|
self.assertIsNone(myuser.password)
|
|
|
|
self.handler.set_user_password(myuser, 'goodpass')
|
|
|
|
self.session.commit()
|
|
|
|
self.assertIsNotNone(myuser.password)
|
|
|
|
# nb. password is hashed
|
|
|
|
self.assertNotEqual(myuser.password, 'goodpass')
|
|
|
|
|
|
|
|
# confirm login works with new password
|
|
|
|
user = self.handler.authenticate_user(self.session, 'myuser', 'goodpass')
|
|
|
|
self.assertIs(user, myuser)
|
|
|
|
|
|
|
|
def test_get_role_administrator(self):
|
|
|
|
model = self.app.model
|
|
|
|
|
|
|
|
self.assertEqual(self.session.query(model.Role).count(), 0)
|
|
|
|
role = self.handler.get_role_administrator(self.session)
|
|
|
|
self.assertEqual(self.session.query(model.Role).count(), 1)
|
|
|
|
self.assertEqual(role.name, "Administrator")
|
|
|
|
|
|
|
|
def test_get_role_anonymous(self):
|
|
|
|
model = self.app.model
|
|
|
|
|
|
|
|
self.assertEqual(self.session.query(model.Role).count(), 0)
|
|
|
|
role = self.handler.get_role_anonymous(self.session)
|
|
|
|
self.assertEqual(self.session.query(model.Role).count(), 1)
|
|
|
|
self.assertEqual(role.name, "Anonymous")
|
|
|
|
|
|
|
|
def test_get_role_authenticated(self):
|
|
|
|
model = self.app.model
|
|
|
|
|
|
|
|
self.assertEqual(self.session.query(model.Role).count(), 0)
|
|
|
|
role = self.handler.get_role_authenticated(self.session)
|
|
|
|
self.assertEqual(self.session.query(model.Role).count(), 1)
|
|
|
|
self.assertEqual(role.name, "Authenticated")
|
|
|
|
|
|
|
|
def test_get_permissions(self):
|
|
|
|
model = self.app.model
|
|
|
|
|
|
|
|
# empty default for role
|
|
|
|
role = model.Role()
|
|
|
|
perms = self.handler.get_permissions(self.session, role)
|
|
|
|
self.assertIsInstance(perms, set)
|
|
|
|
self.assertEqual(len(perms), 0)
|
|
|
|
|
|
|
|
# empty default for user
|
|
|
|
user = model.User()
|
|
|
|
perms = self.handler.get_permissions(self.session, user)
|
|
|
|
self.assertIsInstance(perms, set)
|
|
|
|
self.assertEqual(len(perms), 0)
|
|
|
|
|
|
|
|
# role perms
|
|
|
|
myrole = model.Role(name='My Role')
|
|
|
|
self.session.add(myrole)
|
|
|
|
self.handler.grant_permission(myrole, 'foo')
|
|
|
|
self.session.commit()
|
|
|
|
perms = self.handler.get_permissions(self.session, myrole)
|
|
|
|
self.assertEqual(perms, {'foo'})
|
|
|
|
|
|
|
|
# user perms
|
|
|
|
myuser = model.User(username='myuser')
|
|
|
|
self.session.add(myuser)
|
|
|
|
self.session.commit()
|
|
|
|
perms = self.handler.get_permissions(self.session, myuser)
|
|
|
|
self.assertEqual(len(perms), 0)
|
|
|
|
myuser.roles.append(myrole)
|
|
|
|
self.session.commit()
|
|
|
|
perms = self.handler.get_permissions(self.session, myuser)
|
|
|
|
self.assertEqual(perms, {'foo'})
|
|
|
|
|
|
|
|
# invalid principal
|
|
|
|
perms = self.handler.get_permissions(self.session, RuntimeError)
|
|
|
|
self.assertEqual(perms, set())
|
|
|
|
|
|
|
|
# missing principal
|
|
|
|
perms = self.handler.get_permissions(self.session, None)
|
|
|
|
self.assertEqual(perms, set())
|
|
|
|
|
|
|
|
def test_has_permission(self):
|
|
|
|
model = self.app.model
|
|
|
|
|
|
|
|
# false default for role
|
|
|
|
role = model.Role()
|
|
|
|
self.assertFalse(self.handler.has_permission(self.session, role, 'foo'))
|
|
|
|
|
|
|
|
# empty default for user
|
|
|
|
user = model.User()
|
|
|
|
self.assertFalse(self.handler.has_permission(self.session, user, 'foo'))
|
|
|
|
|
|
|
|
# role perms
|
|
|
|
myrole = model.Role(name='My Role')
|
|
|
|
self.session.add(myrole)
|
|
|
|
self.session.commit()
|
|
|
|
self.assertFalse(self.handler.has_permission(self.session, myrole, 'foo'))
|
|
|
|
self.handler.grant_permission(myrole, 'foo')
|
|
|
|
self.session.commit()
|
|
|
|
self.assertTrue(self.handler.has_permission(self.session, myrole, 'foo'))
|
|
|
|
|
|
|
|
# user perms
|
|
|
|
myuser = model.User(username='myuser')
|
|
|
|
self.session.add(myuser)
|
|
|
|
self.session.commit()
|
|
|
|
self.assertFalse(self.handler.has_permission(self.session, myuser, 'foo'))
|
|
|
|
myuser.roles.append(myrole)
|
|
|
|
self.session.commit()
|
|
|
|
self.assertTrue(self.handler.has_permission(self.session, myuser, 'foo'))
|
|
|
|
|
|
|
|
# invalid principal
|
|
|
|
self.assertFalse(self.handler.has_permission(self.session, RuntimeError, 'foo'))
|
|
|
|
|
|
|
|
# missing principal
|
|
|
|
self.assertFalse(self.handler.has_permission(self.session, None, 'foo'))
|
|
|
|
|
|
|
|
def test_grant_permission(self):
|
|
|
|
model = self.app.model
|
|
|
|
myrole = model.Role(name='My Role')
|
|
|
|
self.session.add(myrole)
|
|
|
|
self.session.commit()
|
|
|
|
|
|
|
|
# no perms yet
|
|
|
|
self.assertEqual(self.session.query(model.Permission).count(), 0)
|
|
|
|
|
|
|
|
# grant one perm, and confirm
|
|
|
|
self.handler.grant_permission(myrole, 'foo')
|
|
|
|
self.session.commit()
|
|
|
|
self.assertEqual(self.session.query(model.Permission).count(), 1)
|
|
|
|
perm = self.session.query(model.Permission).one()
|
|
|
|
self.assertIs(perm.role, myrole)
|
|
|
|
self.assertEqual(perm.permission, 'foo')
|
|
|
|
|
|
|
|
# grant same perm again, confirm just one exists
|
|
|
|
self.handler.grant_permission(myrole, 'foo')
|
|
|
|
self.session.commit()
|
|
|
|
self.assertEqual(self.session.query(model.Permission).count(), 1)
|
|
|
|
perm = self.session.query(model.Permission).one()
|
|
|
|
self.assertIs(perm.role, myrole)
|
|
|
|
self.assertEqual(perm.permission, 'foo')
|
|
|
|
|
|
|
|
def test_revoke_permission(self):
|
|
|
|
model = self.app.model
|
|
|
|
myrole = model.Role(name='My Role')
|
|
|
|
self.session.add(myrole)
|
|
|
|
self.handler.grant_permission(myrole, 'foo')
|
|
|
|
self.session.commit()
|
|
|
|
|
|
|
|
# just the one perm
|
|
|
|
self.assertEqual(self.session.query(model.Permission).count(), 1)
|
|
|
|
|
|
|
|
# revoke it, then confirm
|
|
|
|
self.handler.revoke_permission(myrole, 'foo')
|
|
|
|
self.session.commit()
|
|
|
|
self.assertEqual(self.session.query(model.Permission).count(), 0)
|
|
|
|
|
|
|
|
# revoke again, confirm
|
|
|
|
self.handler.revoke_permission(myrole, 'foo')
|
|
|
|
self.session.commit()
|
|
|
|
self.assertEqual(self.session.query(model.Permission).count(), 0)
|