76 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			76 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Python
		
	
	
	
from django.conf import settings
 | 
						|
from django.utils.translation import ugettext as _
 | 
						|
 | 
						|
from django.core.cache import cache
 | 
						|
 | 
						|
from allauth.account.utils import send_email_confirmation
 | 
						|
from oauth2_provider.contrib.rest_framework.authentication import (
 | 
						|
    OAuth2Authentication as BaseOAuth2Authentication,
 | 
						|
)
 | 
						|
from rest_framework import exceptions
 | 
						|
 | 
						|
from funkwhale_api.users import models as users_models
 | 
						|
 | 
						|
 | 
						|
def should_verify_email(user):
 | 
						|
    if user.is_superuser:
 | 
						|
        return False
 | 
						|
    has_unverified_email = not user.has_verified_primary_email
 | 
						|
    mandatory_verification = settings.ACCOUNT_EMAIL_VERIFICATION != "optional"
 | 
						|
    return has_unverified_email and mandatory_verification
 | 
						|
 | 
						|
 | 
						|
class UnverifiedEmail(Exception):
 | 
						|
    def __init__(self, user):
 | 
						|
        self.user = user
 | 
						|
 | 
						|
 | 
						|
def resend_confirmation_email(request, user):
 | 
						|
    THROTTLE_DELAY = 500
 | 
						|
    cache_key = "auth:resent-email-confirmation:{}".format(user.pk)
 | 
						|
    if cache.get(cache_key):
 | 
						|
        return False
 | 
						|
 | 
						|
    done = send_email_confirmation(request, user)
 | 
						|
    cache.set(cache_key, True, THROTTLE_DELAY)
 | 
						|
    return done
 | 
						|
 | 
						|
 | 
						|
class OAuth2Authentication(BaseOAuth2Authentication):
 | 
						|
    def authenticate(self, request):
 | 
						|
        try:
 | 
						|
            return super().authenticate(request)
 | 
						|
        except UnverifiedEmail as e:
 | 
						|
            request.oauth2_error = {"error": "unverified_email"}
 | 
						|
            resend_confirmation_email(request, e.user)
 | 
						|
 | 
						|
 | 
						|
class ApplicationTokenAuthentication(object):
 | 
						|
    def authenticate(self, request):
 | 
						|
        try:
 | 
						|
            header = request.headers["Authorization"]
 | 
						|
        except KeyError:
 | 
						|
            return
 | 
						|
 | 
						|
        if "Bearer" not in header:
 | 
						|
            return
 | 
						|
 | 
						|
        token = header.split()[-1].strip()
 | 
						|
 | 
						|
        try:
 | 
						|
            application = users_models.Application.objects.exclude(user=None).get(
 | 
						|
                token=token
 | 
						|
            )
 | 
						|
        except users_models.Application.DoesNotExist:
 | 
						|
            return
 | 
						|
        user = users_models.User.objects.all().for_auth().get(id=application.user_id)
 | 
						|
        if not user.is_active:
 | 
						|
            msg = _("User account is disabled.")
 | 
						|
            raise exceptions.AuthenticationFailed(msg)
 | 
						|
 | 
						|
        if should_verify_email(user):
 | 
						|
            raise UnverifiedEmail(user)
 | 
						|
 | 
						|
        request.scopes = application.scope.split()
 | 
						|
        return user, None
 |