23
23
24
24
from djangosaml2 .signals import pre_user_save
25
25
26
+ from . import settings as saml_settings
27
+
26
28
try :
27
29
from django .contrib .auth .models import SiteProfileNotAvailable
28
30
except ImportError :
@@ -83,8 +85,8 @@ def authenticate(self, session_info=None, attribute_mapping=None,
83
85
use_name_id_as_username = getattr (
84
86
settings , 'SAML_USE_NAME_ID_AS_USERNAME' , False )
85
87
86
- django_user_main_attribute = getattr (
87
- settings , 'SAML_DJANGO_USER_MAIN_ATTRIBUTE' , 'username' )
88
+ django_user_main_attribute = saml_settings . SAML_DJANGO_USER_MAIN_ATTRIBUTE
89
+ django_user_main_attribute_lookup = saml_settings . SAML_DJANGO_USER_MAIN_ATTRIBUTE_LOOKUP
88
90
89
91
logger .debug ('attributes: %s' , attributes )
90
92
saml_user = None
@@ -95,11 +97,7 @@ def authenticate(self, session_info=None, attribute_mapping=None,
95
97
else :
96
98
logger .error ('The nameid is not available. Cannot find user without a nameid.' )
97
99
else :
98
- logger .debug ('attribute_mapping: %s' , attribute_mapping )
99
- for saml_attr , django_fields in attribute_mapping .items ():
100
- if (django_user_main_attribute in django_fields
101
- and saml_attr in attributes ):
102
- saml_user = attributes [saml_attr ][0 ]
100
+ saml_user = self .get_attribute_value (django_user_main_attribute , attributes , attribute_mapping )
103
101
104
102
if saml_user is None :
105
103
logger .error ('Could not find saml_user value' )
@@ -108,46 +106,21 @@ def authenticate(self, session_info=None, attribute_mapping=None,
108
106
if not self .is_authorized (attributes , attribute_mapping ):
109
107
return None
110
108
111
- user = None
112
-
113
109
main_attribute = self .clean_user_main_attribute (saml_user )
114
110
115
- user_query_args = {django_user_main_attribute : main_attribute }
116
-
117
111
# Note that this could be accomplished in one try-except clause, but
118
112
# instead we use get_or_create when creating unknown users since it has
119
113
# built-in safeguards for multiple threads.
120
- User = get_saml_user_model ()
121
- if create_unknown_user :
122
- logger .debug ('Check if the user "%s" exists or create otherwise' ,
123
- main_attribute )
124
- try :
125
- user , created = User .objects .get_or_create (** user_query_args )
126
- except MultipleObjectsReturned :
127
- logger .error ("There are more than one user with %s = %s" ,
128
- django_user_main_attribute , main_attribute )
129
- return None
130
-
131
- if created :
132
- logger .debug ('New user created' )
133
- user = self .configure_user (user , attributes , attribute_mapping )
134
- else :
135
- logger .debug ('User updated' )
136
- user = self .update_user (user , attributes , attribute_mapping )
137
- else :
138
- logger .debug ('Retrieving existing user "%s"' , main_attribute )
139
- try :
140
- user = User .objects .get (** user_query_args )
141
- user = self .update_user (user , attributes , attribute_mapping )
142
- except User .DoesNotExist :
143
- logger .error ('The user "%s" does not exist' , main_attribute )
144
- return None
145
- except MultipleObjectsReturned :
146
- logger .error ("There are more than one user with %s = %s" ,
147
- django_user_main_attribute , main_attribute )
148
- return None
114
+ return self .get_saml2_user (
115
+ create_unknown_user , main_attribute , attributes , attribute_mapping )
149
116
150
- return user
117
+ def get_attribute_value (self , django_field , attributes , attribute_mapping ):
118
+ saml_user = None
119
+ logger .debug ('attribute_mapping: %s' , attribute_mapping )
120
+ for saml_attr , django_fields in attribute_mapping .items ():
121
+ if django_field in django_fields and saml_attr in attributes :
122
+ saml_user = attributes [saml_attr ][0 ]
123
+ return saml_user
151
124
152
125
def is_authorized (self , attributes , attribute_mapping ):
153
126
"""Hook to allow custom authorization policies based on
@@ -164,6 +137,65 @@ def clean_user_main_attribute(self, main_attribute):
164
137
"""
165
138
return main_attribute
166
139
140
+ def get_user_query_args (self , main_attribute ):
141
+ django_user_main_attribute = getattr (
142
+ settings , 'SAML_DJANGO_USER_MAIN_ATTRIBUTE' , 'username' )
143
+ django_user_main_attribute_lookup = getattr (
144
+ settings , 'SAML_DJANGO_USER_MAIN_ATTRIBUTE_LOOKUP' , '' )
145
+
146
+ return {
147
+ django_user_main_attribute + django_user_main_attribute_lookup : main_attribute
148
+ }
149
+
150
+ def get_saml2_user (self , create , main_attribute , attributes , attribute_mapping ):
151
+ if create :
152
+ return self ._get_or_create_saml2_user (main_attribute , attributes , attribute_mapping )
153
+
154
+ return self ._get_saml2_user (main_attribute , attributes , attribute_mapping )
155
+
156
+ def _get_or_create_saml2_user (self , main_attribute , attributes , attribute_mapping ):
157
+ logger .debug ('Check if the user "%s" exists or create otherwise' ,
158
+ main_attribute )
159
+ django_user_main_attribute = saml_settings .SAML_DJANGO_USER_MAIN_ATTRIBUTE
160
+ django_user_main_attribute_lookup = saml_settings .SAML_DJANGO_USER_MAIN_ATTRIBUTE_LOOKUP
161
+ user_query_args = self .get_user_query_args (main_attribute )
162
+ user_create_defaults = {django_user_main_attribute : main_attribute }
163
+
164
+ User = get_saml_user_model ()
165
+ try :
166
+ user , created = User .objects .get_or_create (
167
+ defaults = user_create_defaults , ** user_query_args )
168
+ except MultipleObjectsReturned :
169
+ logger .error ("There are more than one user with %s = %s" ,
170
+ django_user_main_attribute , main_attribute )
171
+ return None
172
+
173
+ if created :
174
+ logger .debug ('New user created' )
175
+ user = self .configure_user (user , attributes , attribute_mapping )
176
+ else :
177
+ logger .debug ('User updated' )
178
+ user = self .update_user (user , attributes , attribute_mapping )
179
+ return user
180
+
181
+ def _get_saml2_user (self , main_attribute , attributes , attribute_mapping ):
182
+ User = get_saml_user_model ()
183
+ django_user_main_attribute = saml_settings .SAML_DJANGO_USER_MAIN_ATTRIBUTE
184
+ user_query_args = self .get_user_query_args (main_attribute )
185
+
186
+ logger .debug ('Retrieving existing user "%s"' , main_attribute )
187
+ try :
188
+ user = User .objects .get (** user_query_args )
189
+ user = self .update_user (user , attributes , attribute_mapping )
190
+ except User .DoesNotExist :
191
+ logger .error ('The user "%s" does not exist' , main_attribute )
192
+ return None
193
+ except MultipleObjectsReturned :
194
+ logger .error ("There are more than one user with %s = %s" ,
195
+ django_user_main_attribute , main_attribute )
196
+ return None
197
+ return user
198
+
167
199
def configure_user (self , user , attributes , attribute_mapping ):
168
200
"""Configures a user after creation and returns the updated user.
169
201
@@ -217,7 +249,8 @@ def update_user(self, user, attributes, attribute_mapping,
217
249
logger .debug ('Sending the pre_save signal' )
218
250
signal_modified = any (
219
251
[response for receiver , response
220
- in pre_user_save .send_robust (sender = user ,
252
+ in pre_user_save .send_robust (sender = user .__class__ ,
253
+ instance = user ,
221
254
attributes = attributes ,
222
255
user_modified = user_modified )]
223
256
)
@@ -236,9 +269,9 @@ def _set_attribute(self, obj, attr, value):
236
269
237
270
Return True if the attribute was changed and False otherwise.
238
271
"""
239
- field = obj ._meta .get_field_by_name (attr )
240
- if len (value ) > field [ 0 ] .max_length :
241
- cleaned_value = value [:field [ 0 ] .max_length ]
272
+ field = obj ._meta .get_field (attr )
273
+ if len (value ) > field .max_length :
274
+ cleaned_value = value [:field .max_length ]
242
275
logger .warn ('The attribute "%s" was trimmed from "%s" to "%s"' ,
243
276
attr , value , cleaned_value )
244
277
else :
0 commit comments