From: gfawcett Date: Sun, 1 Mar 2009 21:18:50 +0000 (+0000) Subject: generic make-a-user from backend data source X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=fbf4f90ebb1ea4c87bf46d5136e877feb7877faa;p=Syrup.git generic make-a-user from backend data source git-svn-id: svn://svn.open-ils.org/ILS-Contrib/servres/trunk@132 6d9bc8c9-1ec2-4278-b937-99fde70a366f --- diff --git a/conifer/custom/auth_evergreen.py b/conifer/custom/auth_evergreen.py index 23d8c34..f7c361e 100644 --- a/conifer/custom/auth_evergreen.py +++ b/conifer/custom/auth_evergreen.py @@ -11,17 +11,7 @@ class EvergreenAuthBackend(EvergreenAuthServer): def authenticate(self, username=None, password=None): pwd_valid = self.login(username, password) if pwd_valid: - try: - user = User.objects.get(username=username) - except User.DoesNotExist: - u = self.lookup(username) - user = User(username=username, - first_name= u['first_name'], - last_name = u['last_name'], - email = u['email']) - user.set_unusable_password() - user.save() - return user + return self.maybe_initialize_user(username) return None def get_user(self, user_id): @@ -29,3 +19,33 @@ class EvergreenAuthBackend(EvergreenAuthServer): return User.objects.get(pk=user_id) except User.DoesNotExist: return None + + def maybe_initialize_user(self, username, look_local=True): + """Look up user in Django db; if not found, fetch user detail + from backend and set up a local user object. Return None if no + such user exists in either Django or the backend. + + Setting look_local=False skips the Django search and heads + straight to the backend; this shaves a database call when + walking a set of backends to initialize a user. Skipping + look_local on a username that already exists in Django will + certainly lead to an integrity error. + + This method is NOT part of the Django backend interface. + """ + user = None + if look_local: + try: + user = User.objects.get(username=username) + except User.DoesNotExist: + pass + if user is None: + u = self.lookup(username) + if u: # user found in Evergreen. + user = User(username=username, + first_name = u['first_name'], + last_name = u['last_name'], + email = u['email']) + user.set_unusable_password() + user.save() + return user diff --git a/conifer/syrup/models.py b/conifer/syrup/models.py index dfc6553..1059b0b 100644 --- a/conifer/syrup/models.py +++ b/conifer/syrup/models.py @@ -1,6 +1,7 @@ from django.db import models as m from django.contrib.auth.models import User from django.contrib.auth.models import AnonymousUser +from django.contrib.auth import get_backends from datetime import datetime from genshi import Markup import re @@ -75,6 +76,33 @@ class UserProfile(m.Model): .order_by('-user__last_name','-user__first_name') #---------------------------------------------------------------------- +# Initializing an external user account + +# For usernames that come from external authentication sources (LDAP, +# Evergreen, etc.) we need a general way to look up a user who may not +# yet have a Django account. For example, you might want to add user +# 'xsmith' as the instructor for a course. If 'xsmith' is in LDAP but +# not yet in Django, it would be nice if a Django record were lazily +# created for him upon lookup. + +# That's what 'maybe_initialize_user' is for: participating backends +# provide a 'maybe_initialize_user' method which creates a new User +# record if one doesn't exist. Otherwise, 'maybe_initialize_user' is +# equivalent to 'User.objects.get(username=username)'. + +_backends_that_can_initialize_users = [ + be for be in get_backends() if hasattr(be, 'maybe_initialize_user')] + +def maybe_initialize_user(username): + try: + return User.objects.get(username=username) + except User.DoesNotExist: + for be in _backends_that_can_initialize_users: + user = be.maybe_initialize_user(username, look_local=False) + if user: + return user + +#---------------------------------------------------------------------- # LIBRARIES, SERVICE DESKS class LibraryUnit(m.Model):