3
0
Fork 0

feat: flesh out the auth handler; add people handler

can handle the basics now: authentication, perm checks etc.
This commit is contained in:
Lance Edgar 2024-07-14 23:20:44 -05:00
parent 43ca404837
commit e899d06151
12 changed files with 1031 additions and 23 deletions

View file

@ -101,17 +101,17 @@ class TestAppHandler(TestCase):
from wuttjamaican.db import model
except ImportError:
pytest.skip("test not relevant without sqlalchemy")
else:
self.assertNotIn('model', self.app.__dict__)
self.assertIs(self.app.model, model)
self.assertNotIn('model', self.app.__dict__)
self.assertIs(self.app.model, model)
def test_get_model(self):
try:
from wuttjamaican.db import model
except ImportError:
pytest.skip("test not relevant without sqlalchemy")
else:
self.assertIs(self.app.get_model(), model)
self.assertIs(self.app.get_model(), model)
def test_get_title(self):
self.assertEqual(self.app.get_title(), 'WuttJamaican')
@ -120,6 +120,44 @@ class TestAppHandler(TestCase):
uuid = self.app.make_uuid()
self.assertEqual(len(uuid), 32)
def test_get_session(self):
try:
import sqlalchemy as sa
from sqlalchemy import orm
except ImportError:
pytest.skip("test not relevant without sqlalchemy")
model = self.app.model
user = model.User()
self.assertIsNone(self.app.get_session(user))
Session = orm.sessionmaker()
engine = sa.create_engine('sqlite://')
mysession = Session(bind=engine)
mysession.add(user)
session = self.app.get_session(user)
self.assertIs(session, mysession)
def test_get_person(self):
people = self.app.get_people_handler()
with patch.object(people, 'get_person') as get_person:
get_person.return_value = 'foo'
person = self.app.get_person('bar')
get_person.assert_called_once_with('bar')
self.assertEqual(person, 'foo')
def test_get_auth_handler(self):
from wuttjamaican.auth import AuthHandler
auth = self.app.get_auth_handler()
self.assertIsInstance(auth, AuthHandler)
def test_get_people_handler(self):
from wuttjamaican.people import PeopleHandler
people = self.app.get_people_handler()
self.assertIsInstance(people, PeopleHandler)
class TestAppProvider(TestCase):

View file

@ -5,13 +5,353 @@ from unittest import TestCase
from wuttjamaican import auth as mod
from wuttjamaican.conf import WuttaConfig
try:
import sqlalchemy as sa
except ImportError:
pass
else:
class TestAuthHandler(TestCase):
def setUp(self):
self.config = WuttaConfig()
self.app = self.config.get_app()
class TestAuthHandler(TestCase):
def test_basic(self):
handler = mod.AuthHandler(self.config)
self.assertIs(handler.app, self.app)
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)
# 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)

52
tests/test_people.py Normal file
View file

@ -0,0 +1,52 @@
# -*- coding: utf-8; -*-
from unittest import TestCase
from wuttjamaican import people as mod
from wuttjamaican.conf import WuttaConfig
try:
import sqlalchemy as sa
except ImportError:
pass
else:
class TestPeopleHandler(TestCase):
def setUp(self):
self.config = WuttaConfig()
self.app = self.config.get_app()
self.handler = mod.PeopleHandler(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_get_person(self):
model = self.app.model
myperson = model.Person(full_name='Barny Rubble')
self.session.add(myperson)
self.session.commit()
# empty obj is ignored
person = self.handler.get_person(None)
self.assertIsNone(person)
# person is returned as-is
person = self.handler.get_person(myperson)
self.assertIs(person, myperson)
# find person from user
myuser = model.User(username='barney', person=myperson)
self.session.add(myuser)
self.session.commit()
person = self.handler.get_person(myuser)
self.assertIs(person, myperson)