refreshing and replacing old user data
This commit is contained in:
parent
5a486de8f4
commit
25c168a982
@ -51,7 +51,8 @@ class DiscordAuthenticationBackend(BaseBackend):
|
||||
|
||||
if existing_user:
|
||||
# The previous access token may have expired, so update it.
|
||||
existing_user.access_token = discord_user_data["access_token"]
|
||||
existing_user.update(discord_user_data)
|
||||
# existing_user.access_token = discord_user_data["access_token"]
|
||||
existing_user.save()
|
||||
return existing_user
|
||||
|
||||
|
@ -46,6 +46,7 @@ class DiscordUserOAuth2Manager(BaseUserManager):
|
||||
mfa_enabled=user["mfa_enabled"],
|
||||
access_token=user["access_token"],
|
||||
token_expires=user["token_expires"],
|
||||
refresh_token=user["refresh_token"],
|
||||
**extra_fields
|
||||
)
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
# Generated by Django 5.0.4 on 2024-05-31 22:41
|
||||
|
||||
from django.db import migrations, models
|
||||
from django.utils import timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
@ -13,7 +14,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='discorduser',
|
||||
name='token_expires',
|
||||
field=models.DateTimeField(default=0, help_text='when to request a new access token.', verbose_name='token expires'),
|
||||
field=models.DateTimeField(default=timezone.now, help_text='when to request a new access token.', verbose_name='token expires'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
|
@ -0,0 +1,19 @@
|
||||
# Generated by Django 5.0.4 on 2024-06-01 16:45
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0002_discorduser_token_expires'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='discorduser',
|
||||
name='refresh_token',
|
||||
field=models.CharField(default='1', help_text='token for the application to request a new access token.', max_length=100, verbose_name='refresh token'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -1,5 +1,7 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
@ -7,6 +9,8 @@ from django.contrib.auth.models import PermissionsMixin
|
||||
|
||||
from .managers import DiscordUserOAuth2Manager
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DiscordUser(PermissionsMixin):
|
||||
"""
|
||||
@ -65,11 +69,15 @@ class DiscordUser(PermissionsMixin):
|
||||
max_length=100,
|
||||
help_text=_("token for the application to make api calls on behalf of the user.")
|
||||
)
|
||||
|
||||
token_expires = models.DateTimeField(
|
||||
_("token expires"),
|
||||
help_text=_("when to request a new access token.")
|
||||
)
|
||||
refresh_token = models.CharField(
|
||||
_("refresh token"),
|
||||
max_length=100,
|
||||
help_text=_("token for the application to request a new access token.")
|
||||
)
|
||||
|
||||
# Custom Attributes
|
||||
|
||||
@ -129,3 +137,23 @@ class DiscordUser(PermissionsMixin):
|
||||
|
||||
def get_username(self):
|
||||
return self.username
|
||||
|
||||
def update(self, raw: dict):
|
||||
|
||||
log.debug("updating user: %s", self.username)
|
||||
log.debug("raw update data: %s", raw)
|
||||
log.debug("public flags: %s, %s", raw["public_flags"], type(raw["public_flags"]))
|
||||
|
||||
|
||||
self.username=raw["username"]
|
||||
self.global_name=raw["global_name"]
|
||||
self.avatar=raw["avatar"]
|
||||
self.public_flags=raw["public_flags"]
|
||||
self.flags=raw["flags"]
|
||||
self.locale=raw["locale"]
|
||||
self.mfa_enabled=raw["mfa_enabled"]
|
||||
self.access_token=raw["access_token"]
|
||||
self.token_expires=raw["token_expires"]
|
||||
self.refresh_token=raw["refresh_token"]
|
||||
|
||||
self.save(force_update=True)
|
||||
|
@ -2,8 +2,10 @@
|
||||
|
||||
import logging
|
||||
import requests
|
||||
from datetime import timedelta
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils import timezone
|
||||
from django.http import JsonResponse
|
||||
from django.views.generic import View, TemplateView
|
||||
from django.shortcuts import redirect
|
||||
@ -31,17 +33,25 @@ class DiscordLoginRedirect(View):
|
||||
return redirect("auth:login")
|
||||
|
||||
code = request.GET.get("code")
|
||||
access_token, token_expires = self.exchange_code_for_token(code)
|
||||
raw_user_data = self.get_raw_user_data(access_token)
|
||||
raw_user_data["access_token"] = access_token
|
||||
raw_user_data["token_expires"] = token_expires
|
||||
exchange_data = self.exchange_code(code)
|
||||
access_token = exchange_data["access_token"]
|
||||
|
||||
# Get raw user data from discord
|
||||
raw_user_data = self.get_raw_user_data(access_token)
|
||||
|
||||
# Add the token and expires datetime to the user data
|
||||
token_expire_datetime = timezone.now() + timedelta(seconds=exchange_data["expires_in"])
|
||||
raw_user_data["token_expires"] = token_expire_datetime
|
||||
raw_user_data["access_token"] = access_token
|
||||
raw_user_data["refresh_token"] = exchange_data["refresh_token"]
|
||||
|
||||
# authenticate (creates user if not exists) and login
|
||||
discord_user = authenticate(request, discord_user_data=raw_user_data)
|
||||
login(request, discord_user)
|
||||
|
||||
return redirect("home:index")
|
||||
|
||||
def exchange_code_for_token(self, code: str) -> tuple[str, str]:
|
||||
def exchange_code(self, code: str) -> dict:
|
||||
"""
|
||||
Exchanges the given code for an access token.
|
||||
A call is made to the Discord API.
|
||||
@ -59,12 +69,27 @@ class DiscordLoginRedirect(View):
|
||||
headers=request_data["headers"]
|
||||
)
|
||||
|
||||
resp_json = response.json()
|
||||
log.debug(resp_json)
|
||||
access_token = resp_json["access_token"]
|
||||
expires = resp_json["expires"]
|
||||
return response.json()
|
||||
|
||||
return access_token, expires
|
||||
def refresh_token(self, refresh_token: str) -> dict:
|
||||
"""
|
||||
Refresh the access token if expired, using the refresh
|
||||
token. Returns a new access token, expire time and refresh
|
||||
token.
|
||||
"""
|
||||
|
||||
request_data = settings.DISCORD_REFRESH_TOKEN_REQUEST
|
||||
request_data["data"]["refresh_token"] = refresh_token
|
||||
|
||||
log.debug("request data: %s", request_data)
|
||||
|
||||
response = requests.post(
|
||||
url=f"{settings.DISCORD_API_URL}/oauth2/token",
|
||||
data=request_data["data"],
|
||||
headers=request_data["headers"]
|
||||
)
|
||||
|
||||
return response.json()
|
||||
|
||||
def get_raw_user_data(self, access_token: str):
|
||||
"""
|
||||
|
18
apps/home/migrations/0022_alter_subscription_filters.py
Normal file
18
apps/home/migrations/0022_alter_subscription_filters.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.0.4 on 2024-05-31 22:41
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0021_alter_subscription_filters'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='filters',
|
||||
field=models.ManyToManyField(blank=True, to='home.filter'),
|
||||
),
|
||||
]
|
@ -137,7 +137,15 @@ DISCORD_CODE_EXCHANGE_REQUEST = {
|
||||
"client_secret": DISCORD_SECRET,
|
||||
"grant_type": "authorization_code",
|
||||
"redirect_uri": env("DISCORD_REDIRECT_URL"),
|
||||
"scope": " ".join(DISCORD_SCOPES)
|
||||
"scope": " ".join(DISCORD_SCOPES),
|
||||
"code": ""
|
||||
}
|
||||
}
|
||||
DISCORD_REFRESH_TOKEN_REQUEST = {
|
||||
"headers": {"Content-Type": "application/x-www-form-urlencoded"},
|
||||
"data": {
|
||||
"grant_type": "refresh_token",
|
||||
"refresh_token": ""
|
||||
}
|
||||
}
|
||||
DISCORD_API_URL = env("DISCORD_API_URL")
|
||||
|
Loading…
x
Reference in New Issue
Block a user