~joe-topjian-v/django-openid-auth/jtopjian-dev

« back to all changes in this revision

Viewing changes to django_openid_auth/auth.py

Add support for requesting user details via the Attribute Exchange extension.  This allows us to retrieve user details from providers that don't implement the Simple Registration extension (e.g. Google).  Fixes bug #517393.

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
from django.conf import settings
34
34
from django.contrib.auth.models import User, Group
35
35
from openid.consumer.consumer import SUCCESS
36
 
from openid.extensions import sreg
 
36
from openid.extensions import ax, sreg
37
37
 
38
38
from django_openid_auth import teams
39
39
from django_openid_auth.models import UserOpenID
80
80
            return None
81
81
 
82
82
        if getattr(settings, 'OPENID_UPDATE_DETAILS_FROM_SREG', False):
83
 
            sreg_response = sreg.SRegResponse.fromSuccessResponse(
84
 
                openid_response)
85
 
            if sreg_response:
86
 
                self.update_user_details_from_sreg(user, sreg_response)
 
83
            details = self._extract_user_details(openid_response)
 
84
            self.update_user_details(user, details)
87
85
 
88
86
        teams_response = teams.TeamsResponse.fromSuccessResponse(
89
87
            openid_response)
92
90
 
93
91
        return user
94
92
 
 
93
    def _extract_user_details(self, openid_response):
 
94
        email = fullname = first_name = last_name = nickname = None
 
95
        sreg_response = sreg.SRegResponse.fromSuccessResponse(openid_response)
 
96
        if sreg_response:
 
97
            email = sreg_response.get('email')
 
98
            fullname = sreg_response.get('fullname')
 
99
            nickname = sreg_response.get('nickname')
 
100
 
 
101
        # If any attributes are provided via Attribute Exchange, use
 
102
        # them in preference.
 
103
        fetch_response = ax.FetchResponse.fromSuccessResponse(openid_response)
 
104
        if fetch_response:
 
105
            email = fetch_response.getSingle(
 
106
                'http://axschema.org/contact/email', email)
 
107
            fullname = fetch_response.getSingle(
 
108
                'http://axschema.org/namePerson', fullname)
 
109
            first_name = fetch_response.getSingle(
 
110
                'http://axschema.org/namePerson/first', first_name)
 
111
            last_name = fetch_response.getSingle(
 
112
                'http://axschema.org/namePerson/last', last_name)
 
113
            nickname = fetch_response.getSingle(
 
114
                'http://axschema.org/namePerson/friendly', nickname)
 
115
 
 
116
        if fullname and not (first_name or last_name):
 
117
            # Django wants to store first and last names separately,
 
118
            # so we do our best to split the full name.
 
119
            if ' ' in fullname:
 
120
                first_name, last_name = fullname.rsplit(None, 1)
 
121
            else:
 
122
                first_name = u''
 
123
                last_name = fullname
 
124
 
 
125
        return dict(email=email, nickname=nickname,
 
126
                    first_name=first_name, last_name=last_name)
 
127
 
95
128
    def create_user_from_openid(self, openid_response):
96
 
        sreg_response = sreg.SRegResponse.fromSuccessResponse(openid_response)
97
 
        if sreg_response:
98
 
            nickname = sreg_response.get('nickname', 'openiduser')
99
 
            email = sreg_response.get('email', '')
100
 
        else:
101
 
            nickname = 'openiduser'
102
 
            email = ''
 
129
        details = self._extract_user_details(openid_response)
 
130
        nickname = details['nickname'] or 'openiduser'
 
131
        email = details['email'] or ''
103
132
 
104
133
        # Pick a username for the user based on their nickname,
105
134
        # checking for conflicts.
115
144
            i += 1
116
145
 
117
146
        user = User.objects.create_user(username, email, password=None)
118
 
 
119
 
        if sreg_response:
120
 
            self.update_user_details_from_sreg(user, sreg_response)
 
147
        self.update_user_details(user, details)
121
148
 
122
149
        self.associate_openid(user, openid_response)
123
150
        return user
142
169
 
143
170
        return user_openid
144
171
 
145
 
    def update_user_details_from_sreg(self, user, sreg_response):
146
 
        fullname = sreg_response.get('fullname')
147
 
        if fullname:
148
 
            # Do our best here ...
149
 
            if ' ' in fullname:
150
 
                user.first_name, user.last_name = fullname.rsplit(None, 1)
151
 
            else:
152
 
                user.first_name = u''
153
 
                user.last_name = fullname
 
172
    def update_user_details(self, user, details):
 
173
        updated = False
 
174
        if details['first_name']:
 
175
            user.first_name = details['first_name']
 
176
            updated = True
 
177
        if details['last_name']:
 
178
            user.last_name = details['last_name']
 
179
            updated = True
 
180
        if details['email']:
 
181
            user.email = details['email']
 
182
            updated = True
154
183
 
155
 
        email = sreg_response.get('email')
156
 
        if email:
157
 
            user.email = email
158
 
        user.save()
 
184
        if updated:
 
185
            user.save()
159
186
 
160
187
    def update_groups_from_teams(self, user, teams_response):
161
188
        teams_mapping_auto = getattr(settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO', False)