Source code for django_facebook.auth_backends

from django.contrib.auth import backends
from django.db.models.query_utils import Q
from django.db.utils import DatabaseError
from django_facebook import settings as facebook_settings
from django_facebook.utils import get_profile_model, is_user_attribute, \
    get_user_model
import operator

try:
    reduce = reduce
except NameError:
    from functools import reduce


[docs]class FacebookBackend(backends.ModelBackend): ''' Django Facebook authentication backend This backend hides the difference between authenticating with - a django 1.5 custom user model - profile models, which were used prior to 1.5 **Example usage** >>> FacebookBackend().authenticate(facebook_id=myid) '''
[docs] def authenticate(self, facebook_id=None, facebook_email=None): ''' Route to either the user or profile table depending on which type of user customization we are using (profile was used in Django < 1.5, user is the new way in 1.5 and up) ''' user_attribute = is_user_attribute('facebook_id') if user_attribute: user = self.user_authenticate(facebook_id, facebook_email) else: user = self.profile_authenticate(facebook_id, facebook_email) return user
[docs] def user_authenticate(self, facebook_id=None, facebook_email=None): ''' Authenticate the facebook user by id OR facebook_email We filter using an OR to allow existing members to connect with their facebook ID using email. This decorator works with django's custom user model :param facebook_id: Optional string representing the facebook id. :param facebook_email: Optional string with the facebook email. :return: The signed in :class:`User`. ''' user_model = get_user_model() if facebook_id or facebook_email: # match by facebook id or email auth_conditions = [] if facebook_id: auth_conditions.append(Q(facebook_id=facebook_id)) if facebook_email: auth_conditions.append(Q(email__iexact=facebook_email)) # or the operations auth_condition = reduce(operator.or_, auth_conditions) # get the users in one query users = list(user_model.objects.filter(auth_condition)) # id matches vs email matches id_matches = [u for u in users if u.facebook_id == facebook_id] email_matches = [u for u in users if u.facebook_id != facebook_id] # error checking if len(id_matches) > 1: raise ValueError( 'found multiple facebook id matches. this shouldnt be allowed, check your unique constraints. users found %s' % users) # give the right user user = None if id_matches: user = id_matches[0] elif email_matches: user = email_matches[0] if user and facebook_settings.FACEBOOK_FORCE_PROFILE_UPDATE_ON_LOGIN: user.fb_update_required = True return user
[docs] def profile_authenticate(self, facebook_id=None, facebook_email=None): ''' Authenticate the facebook user by id OR facebook_email We filter using an OR to allow existing members to connect with their facebook ID using email. :param facebook_id: Optional string representing the facebook id :param facebook_email: Optional string with the facebook email :return: The signed in :class:`User`. ''' if facebook_id or facebook_email: profile_class = get_profile_model() profile_query = profile_class.objects.all().order_by('user') profile_query = profile_query.select_related('user') profile = None # filter on email or facebook id, two queries for better # queryplan with large data sets if facebook_id: profiles = profile_query.filter(facebook_id=facebook_id)[:1] profile = profiles[0] if profiles else None if profile is None and facebook_email: try: profiles = profile_query.filter( user__email__iexact=facebook_email)[:1] profile = profiles[0] if profiles else None except DatabaseError: try: user = get_user_model( ).objects.get(email=facebook_email) except get_user_model().DoesNotExist: user = None profile = user.get_profile() if user else None if profile: # populate the profile cache while we're getting it anyway user = profile.user user._profile = profile if facebook_settings.FACEBOOK_FORCE_PROFILE_UPDATE_ON_LOGIN: user.fb_update_required = True return user