diff --git a/src/wuttjamaican/auth.py b/src/wuttjamaican/auth.py index 41bab0f..c005f94 100644 --- a/src/wuttjamaican/auth.py +++ b/src/wuttjamaican/auth.py @@ -133,7 +133,7 @@ class AuthHandler(GenericHandler): if key: return self.get_role(session, key) - def get_user(self, obj, **kwargs): + def get_user(self, obj, session=None, **kwargs): """ Return the :class:`~wuttjamaican.db.model.auth.User` associated with the given object, if one can be found. @@ -143,19 +143,49 @@ class AuthHandler(GenericHandler): "first, most obvious" user in the event that the given object is associated with multiple users. - The default logic only knows how to navigate the Person/User - relationship, so if ``obj`` is a - :class:`~wuttjamaican.db.model.base.Person` then it will - return the "first" user account for the person (according to - :attr:`~wuttjamaican.db.model.base.Person.user`). + For instance ``obj`` may be a string in which case a lookup + may be tried on + :attr:`~wuttjamaican.db.model.auth.User.username`. Or it may + be a :class:`~wuttjamaican.db.model.base.Person` in which case + their :attr:`~wuttjamaican.db.model.base.Person.user` may be + returned. + + :param obj: Object for which user should be returned. + + :param session: Open :term:`db session`. This is optional in + some cases, i.e. one can be determined automatically if + ``obj`` is some kind of object already contained in a + session (e.g. ``Person``). But a ``session`` must be + provided if ``obj`` is a simple string and you need to do a + lookup by username etc. :returns: :class:`~wuttjamaican.db.model.auth.User` or ``None``. """ model = self.app.model + # maybe obj is already a user if isinstance(obj, model.User): return obj + # or maybe it is a string + # (nb. these lookups require a db session) + if isinstance(obj, str) and session: + + # try to match on User.uuid + user = session.get(model.User, obj) + if user: + return user + + # try to match on User.username + user = session.query(model.User)\ + .filter(model.User.username == obj)\ + .first() + if user: + return user + + # nb. obj is presumbly another type of object, e.g. Person + + # maybe we can find a person, then get user person = self.app.get_person(obj) if person: return person.user diff --git a/tests/test_auth.py b/tests/test_auth.py index 62e7a91..b5b5f76 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -102,6 +102,14 @@ else: user = self.handler.get_user(myuser) self.assertIs(user, myuser) + # 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) + # find user from person myperson = model.Person(full_name='My Name') self.session.add(myperson)