diff options
Diffstat (limited to 'pydis_site/utils/account.py')
-rw-r--r-- | pydis_site/utils/account.py | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/pydis_site/utils/account.py b/pydis_site/utils/account.py new file mode 100644 index 00000000..9faad986 --- /dev/null +++ b/pydis_site/utils/account.py @@ -0,0 +1,64 @@ +from typing import Any, Dict + +from allauth.account.adapter import DefaultAccountAdapter +from allauth.exceptions import ImmediateHttpResponse +from allauth.socialaccount.adapter import DefaultSocialAccountAdapter +from allauth.socialaccount.models import SocialLogin +from django.contrib.auth.models import User +from django.contrib.messages import ERROR, add_message +from django.http import HttpRequest +from django.shortcuts import redirect +from django.urls import reverse + + +class AccountAdapter(DefaultAccountAdapter): + """An Allauth account adapter that prevents signups via form submission.""" + + def is_open_for_signup(self, request: HttpRequest) -> bool: + """ + Checks whether or not the site is open for signups. + + We override this to always return False so that users may never sign up using + Allauth's signup form endpoints, to be on the safe side - since we only want users + to sign up using their Discord account. + """ + return False + + +class SocialAccountAdapter(DefaultSocialAccountAdapter): + """An Allauth SocialAccount adapter that prevents signups via non-Discord connections.""" + + def is_open_for_signup(self, request: HttpRequest, social_login: SocialLogin) -> bool: + """ + Checks whether or not the site is open for signups. + + We override this method in order to prevent users from creating a new account using + a non-Discord connection, as we require this connection for our users. + """ + if social_login.account.provider != "discord": + add_message( + request, ERROR, + "You must login with Discord before connecting another account. Your account " + "details have not been saved." + ) + + raise ImmediateHttpResponse(redirect(reverse("home"))) + + return True + + def populate_user(self, request: HttpRequest, + social_login: SocialLogin, + data: Dict[str, Any]) -> User: + """ + Method used to populate a Django User with data. + + We override this so that the Django user is created with the username#discriminator, + instead of just the username, as Django users must have unique usernames. For display + purposes, we also set the `name` key, which is used for `first_name` in the database. + """ + if social_login.account.provider == "discord": + discriminator = social_login.account.extra_data["discriminator"] + data["username"] = f"{data['username']}#{discriminator}" + data["name"] = data["username"] + + return super().populate_user(request, social_login, data) |