-
Notifications
You must be signed in to change notification settings - Fork 60
Description
Hi, in my user model I am using the email address field as the username, i.e. in my User model:
USERNAME_FIELD = 'email'
This means that my User has no 'username' property.
As such, when I call CognitoUser.get_user(), I am getting an error when it tries to reconstruct my User model from the database:
File "/Users/anye/bcve/lib/python3.5/site-packages/warrant/init.py", line 460, in get_user
metadata=user_metadata,attr_map=attr_map)
File "/Users/anye/bcve/lib/python3.5/site-packages/django_warrant/backend.py", line 37, in get_user_obj
defaults=user_attrs)
File "/Users/anye/bcve/lib/python3.5/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/anye/bcve/lib/python3.5/site-packages/django/db/models/query.py", line 476, in update_or_create
lookup, params = self._extract_model_params(defaults, **kwargs)
File "/Users/anye/bcve/lib/python3.5/site-packages/django/db/models/query.py", line 534, in _extract_model_params
"', '".join(sorted(invalid_params)),
django.core.exceptions.FieldError: Invalid field name(s) for model User: 'username'.
I tried adding a mapping between username and email but that did not help the issue. My mapping looks like:
COGNITO_ATTR_MAPPING={
'email': 'email',
'given_name': 'first_name',
'family_name': 'last_name',
'username': 'email'
}
Update:
I think the problem is actually twofold; it happens either when trying to create unknown users or get the User from cognito:
backend.py
it's the CognitoUser.user_class.objects.update_or_create() and CognitoUser.user_class.objects.get(username=username) methods that are throwing the exception because it assumes there is a username field on the user_class.
def get_user_obj(self,username=None,attribute_list=[],metadata={},attr_map={}):
user_attrs = cognito_to_dict(attribute_list,CognitoUser.COGNITO_ATTR_MAPPING)
django_fields = [f.name for f in CognitoUser.user_class._meta.get_fields()]
extra_attrs = {}
for k, v in user_attrs.items():
if k not in django_fields:
extra_attrs.update({k: user_attrs.pop(k, None)})
if getattr(settings, 'CREATE_UNKNOWN_USERS', True):
user, created = CognitoUser.user_class.objects.update_or_create(
username=username,
defaults=user_attrs)
else:
try:
user = CognitoUser.user_class.objects.get(username=username)
for k, v in iteritems(user_attrs):
setattr(user, k, v)
user.save()
except CognitoUser.user_class.DoesNotExist:
user = None
if user:
for k, v in extra_attrs.items():
setattr(user, k, v)
return user
I'm not sure if fixing this is going to require overriding these methods from the Warrant library, since those are assuming a username field, or whether you can simply add conditional logic here to either get/update_or_create by either username or USERNAME_FIELD?