|
""" |
|
Converts users/tokens from python-social-auth to django-allauth |
|
Makes some assumptions (i.e. single SocialApp of 'facebook' already added) |
|
""" |
|
|
|
from django.core.management.base import NoArgsCommand |
|
from django.db import connection, IntegrityError |
|
from allauth.socialaccount.models import SocialAccount, SocialToken |
|
from users.models import User |
|
import json |
|
|
|
|
|
# social_auth_usersocialauth.provider: socialaccount_socialapp.id |
|
SOCIAL_MAPPINGS = { |
|
'facebook': '1', |
|
} |
|
|
|
|
|
class Command(NoArgsCommand): |
|
"""Converts python-social-auth database tokens to allauth ones""" |
|
|
|
help = __doc__ |
|
|
|
def dictfetchall(self, cursor): |
|
"""Return all rows from a cursor as a dict""" |
|
columns = [col[0] for col in cursor.description] |
|
return [ |
|
dict(zip(columns, row)) |
|
for row in cursor.fetchall() |
|
] |
|
|
|
def handle_noargs(self, **options): |
|
|
|
errors = 0 # counter for errors encountered (script will convert what it can) |
|
skipped = 0 # counter for known issues we skip past |
|
|
|
with connection.cursor() as cursor: |
|
cursor.execute("SELECT * from social_auth_usersocialauth ORDER BY id DESC") # recent first |
|
usersocialauth = self.dictfetchall(cursor) |
|
|
|
for line in usersocialauth: |
|
|
|
if not line.get('uid'): |
|
print("Skipping, no UID") |
|
skipped += 1 |
|
continue |
|
|
|
if line.get('provider') not in SOCIAL_MAPPINGS: |
|
print("Skipping %s, no valid social mapping for %s" % (line['uid'], line['provider'])) |
|
skipped += 1 |
|
continue |
|
|
|
if line.get('user_id') in [None or '' or ' ']: |
|
print("Skipping %s, no user id" % line['uid']) |
|
skipped += 1 |
|
continue |
|
|
|
extra_data = line.get('extra_data') |
|
if extra_data: |
|
extra_data_json = json.loads(extra_data) |
|
|
|
(last_login, date_joined) = User.objects\ |
|
.values_list('last_login', 'date_joined')\ |
|
.get(id=line['user_id']) |
|
|
|
print("Adding SocialAccount for %s (%s)" % (line['uid'], errors)) |
|
|
|
try: |
|
# We create/overwrite records always; assume a prior run may have failed. |
|
s, _ = SocialAccount.objects.get_or_create( |
|
provider=line['provider'], |
|
uid=line['uid'], |
|
user_id=line['user_id'], |
|
) |
|
except IntegrityError as e: |
|
print(e) |
|
errors += 1 |
|
continue |
|
|
|
s.last_login = last_login |
|
s.extra_data = {} # this was used for token information, not relevant in this context |
|
s.date_joined = date_joined |
|
s.save() |
|
|
|
if extra_data_json: |
|
access_token = extra_data_json.get('access_token') |
|
if not access_token: |
|
continue |
|
|
|
print("Adding SocialToken for %s" % line['uid']) |
|
|
|
t, _ = SocialToken.objects.get_or_create( |
|
account_id=s.id, |
|
app_id=SOCIAL_MAPPINGS[line.get('provider')], |
|
) |
|
|
|
t.token = access_token |
|
t.expires_at = extra_data_json.get('expires_at') |
|
t.save() |
|
|
|
print("Errors: %s, Skipped Records: %s" % (errors, skipped)) |