Closed Frohus closed 1 year ago
If that assert fires, that is due to:
@property
def is_existing(self):
"""When `False`, this social login represents a temporary account, not
yet backed by a database record.
"""
return self.user.pk is not None
So, that means that somehow a real user is already attached to the sociallogin, which should not be possible at this point. Are you using a custom adapter by any chance? You might want to try setting a breakpont there and inspect that user and try and determine why it has a pk
.
No, I'm not using a custom adapter.
That's the user object that is being used in is_existing()
(print(self.user.__dict__)
).
This is just a temporary user as no such user exists in the User table, nor does the EmailAddress or SocialAccount before or after the social login attempt
Note: I've got a custom user model that inherits from AbstractBaseUser, and a custom BaseModel that uses uuid field id
as the primary key.
{
'_state': <django.db.models.base.ModelState object at 0x7f9fd2246310>,
'password': '!hCeuO10Pb8757roh73dmUTba3mFJ7XyNOWs2Wsun',
'last_login': None,
'is_superuser': False,
'id': UUID('438cde65-15ec-45f3-bb59-caabd3ca1e08'),
'created_at': None,
'updated_at': None,
'first_name': 'dasdasd',
'last_name': 'adsasd',
'email': 'lajdasddaljk@gmail.com',
'is_staff': False,
'is_active': True
}
I see. With regular pk fields, if a model has a pk of value None
that implies that the model was not saved yet. In your case, the model does have a pk value, yet it does not point to a DB record. How is the UUID field defined?
Likely, this is what #3419 was pointing at.
Can you try this commit: 38514495 ?
That's the pk field
id = models.UUIDField(
primary_key=True,
db_index=True,
default=uuid.uuid4,
editable=False,
unique=True,
)
3851449 makes no difference as user.pk is linked to the id field and is returning the uuid of the temporary User
The other way to determine if User exists in the DB could be by checking:
@property
def is_existing(self):
"""When `False`, this social login represents a temporary account, not
yet backed by a database record.
"""
return self.user._state.adding is False
Tried it and it works. Also it's seem more universal than always asuming user uses default primary key.
https://docs.djangoproject.com/en/4.2/ref/models/instances/#state
3851449 makes no difference as user.pk is linked to the id field and is returning the uuid of the temporary User
The changes made there do:
if self.user.pk is None:
return False
return get_user_model().objects.filter(pk=self.user.pk).exists()
So:
user.pk
is None
it is likely a regular int based auto field -- and hence not an existing account.pk
is there, in your case, its value is a UUID of a user account that does not exist yet in case of a new signup, or, an actual account in case the .exists()
returns True
.Did you try running that?
As for _state
-- that is populated based on whether or not the instance originates from a queryset. Yet, SocialLogin
instances can end up being serialized and stored in a session. When deserializing, the instances no longer originate from a queryset, meaning, the state is lost.
Apologies, I read the code and thought it wouldn't work without trying, it was late evening and I was half asleep 😄 . Tried it now and it works
Thanks for confirming. Now, the question is, was this the only issue or is there more needed before #3419 can be closed ?
I have persistent users inside my app before registration. I want to use allauth to associate them with their social accounts and use information from their social accounts to fill user's data.
Previously I used override like this in my custom SocialAccountAdapter
class:
def new_user(self, request, sociallogin):
user = request.user
if user.id and user.date_registered is None:
return user
return super().new_user(request, sociallogin)
After this change this obviously does not work, as social login fails with AssertionError. Any tips for a workaround? Besides not keeping persistent users before registration in the first place.
Using:
I'm stuck on making social auth work for a couple of days now. It always fails in
complete_social_login
atassert not sociallogin.is_existing
after the login is confirmed with the provider stage whether I use an existing local account or a completely new one.The
sociallogin.user
that is passed tocomplete_social_login
is always populated with a User instance (<django.db.models.base.ModelState object at 0x7fbac15b1dd0>) for some reason even if I use a completely new account sosociallogin.is_existing
always returns True. This is happening for both GitHub and Google logins.The URL is created with
href="{% provider_login_url 'github' %}"
and it redirects to Github and allows me to authorize the app just fine.This is my config
I tried changing the existing socialaccount config not none of the config worked
Error trace