# -*- encoding: utf-8 -*- import logging from django.conf import settings from django.http import HttpResponse from django.contrib.auth.backends import BaseBackend from .models import DiscordUser log = logging.getLogger(__name__) class DiscordAuthenticationBackend(BaseBackend): """ Authentication Backend for Discord Users. """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def authenticate(self, request: HttpResponse, discord_user_data: dict) -> DiscordUser: """ Creates or finds an existing user, and returns it. "Authenticate" may not be the best name for this method... Parameters ---------- request : django.http.HttpResponse The HTTP request object. discord_user_data : dict A dictionary containing the raw user data. Returns ------- DiscordUser The newly created or existing instance of DiscordUser, based on the provided `discord_user_data`. """ # TODO: # also check the new `token_expires` field to see if the token is invalid # then request a new token, instead of making the user login again # # UPDATE: # is this even possible or necessary with the scope of this app? # # https://discord.com/developers/docs/game-sdk/applications#data-models discord_user_id = discord_user_data["id"] existing_user = self.get_user(discord_user_id) log.debug("authenticating, does user exist: %s", bool(existing_user)) if existing_user: # The previous access token may have expired, so update it. existing_user.update(discord_user_data) # existing_user.access_token = discord_user_data["access_token"] existing_user.save() return existing_user # Provide superuser permissions for specified users if discord_user_id in settings.SUPERUSER_IDS: return DiscordUser.objects.create_superuser(discord_user_data) return DiscordUser.objects.create_user(discord_user_data) def get_user(self, user_id: int) -> DiscordUser | None: """ Fetch a user from their ID. Returns NoneType if not found. Parameters ---------- user_id : int The identifier for the discord user. Returns ------- DiscordUser | None Either the DiscordUser or None if not found. """ try: return DiscordUser.objects.get(pk=user_id) except DiscordUser.DoesNotExist: return None