Просмотр исходного кода

WIP misago-specific social auth pipeline items

Rafał Pitoń 7 лет назад
Родитель
Сommit
033d2d6729
3 измененных файлов с 87 добавлено и 7 удалено
  1. 7 0
      misago/core/errorpages.py
  2. 18 3
      misago/core/exceptions.py
  3. 62 4
      misago/users/social/pipeline.py

+ 7 - 0
misago/core/errorpages.py

@@ -4,6 +4,7 @@ from django.utils.translation import ugettext as _
 from social_core import exceptions as social_exceptions
 
 from misago.admin.views.errorpages import admin_csrf_failure, admin_error_page
+from misago.core.exceptions import SocialAuthFailed, SocialAuthBanned
 from misago.users.social.utils import get_social_auth_backend_name
 
 from .utils import get_exception_message, is_request_to_misago
@@ -59,6 +60,7 @@ def page_not_found(request, exception):
 
 def social_auth_failed(request, exception):
     backend_name = None
+    ban = None
     message = None
     help_text = None
 
@@ -89,11 +91,16 @@ def social_auth_failed(request, exception):
             help_text = _("The sign in process has been canceled by user.")
         if isinstance(exception, social_exceptions.AuthUnreachableProvider):
             help_text = _("The other service could not be reached.")
+        if isinstance(exception, SocialAuthFailed):
+            help_text = exception.message
+        if isinstance(exception, SocialAuthBanned):
+            ban = exception.ban
     else:
         message = _("Unexpected problem has been encountered during sign in process.")
 
     return render(request, 'misago/errorpages/social.html', {
         'backend_name': backend_name,
+        'ban': ban,
         'message': message,
         'help_text': help_text,
     }, status=400)

+ 18 - 3
misago/core/exceptions.py

@@ -1,8 +1,9 @@
 from django.core.exceptions import PermissionDenied
+from social_core.exceptions import AuthException
 
 
 class AjaxError(Exception):
-    """you've tried to do something over AJAX but misago blurped"""
+    """You've tried to do something over AJAX but misago blurped"""
 
     def __init__(self, message=None, code=406):
         self.message = message
@@ -15,11 +16,25 @@ class Banned(PermissionDenied):
             self.ban = ban
 
 
+class SocialAuthFailed(AuthException):
+    """Exception used to return error messages from Misago's social auth to user."""
+    def __init__(self, backend, message):
+        self.backend = backend
+        self.message = message
+
+
+class SocialAuthBanned(AuthException):
+    """Exception used to return ban message from Misago's social auth to user."""
+    def __init__(self, backend, ban):
+        self.backend = backend
+        self.ban = ban
+
+
 class ExplicitFirstPage(Exception):
-    """the url that was used to reach view contained explicit first page"""
+    """The url that was used to reach view contained explicit first page"""
     pass
 
 
 class OutdatedSlug(Exception):
-    """the url that was used to reach view contained outdated slug"""
+    """The url that was used to reach view contained outdated slug"""
     pass

+ 62 - 4
misago/users/social/pipeline.py

@@ -1,14 +1,72 @@
+from django.contrib.auth import get_user_model
+from django.utils.translation import ugettext as _
+
+from misago.core.exceptions import SocialAuthFailed, SocialAuthBanned
+
+from misago.users.bans import get_request_ip_ban, get_user_ban
+
+from .utils import get_social_auth_backend_name
+
+
+UserModel = get_user_model()
+
+
 def validate_ip_not_banned(strategy, details, backend, user=None, *args, **kwargs):
-    pass
+    """Pipeline step that interrupts pipeline if found user is non-staff and IP banned"""
+    if user and user.acl.is_staff:
+        return None
+    
+    ip_ban = get_request_ip_ban(strategy.request)
+    if ip_ban:
+        raise SocialAuthBanned(ip_ban)
+
+
+def validate_user_not_banned(strategy, details, backend, user=None, *args, **kwargs):
+    """Pipeline step that interrupts pipeline if found user is non-staff and banned"""
+    if user and user.acl.is_staff:
+        return None
+
+    user_ban = get_user_ban(user)
+    if user_ban:
+        raise SocialAuthBanned(user_ban)
 
 
 def associate_by_email(strategy, details, backend, user=None, *args, **kwargs):
-    pass
+    """If user with e-mail from provider exists in database and is active,
+    this step authenticates them.
+    """
+    if user:
+        return None
+
+    email = details.get('email')
+    if not email:
+        return
+
+    try:
+        user = UserModel.objects.get_by_email(email)
+    except UserModel.DoesNotExist:
+        return None
+
+    if not user.is_active:
+        backend_name = get_social_auth_backend_name(backend.name)
+        raise SocialAuthFailed(
+            backend,
+            _(
+                "The e-mail address associated with your %(backend)s account is "
+                "not available for use on this site."
+            ) % {'backend': backend_name}
+        )
+
+    return {'user': user, 'is_new': False}
 
 
 def create_user(strategy, details, backend, user=None, *args, **kwargs):
-    pass
+    """Aggressively attempt to register and sign in new user"""
+    if user:
+        return None
 
 
 def create_user_with_form(strategy, details, backend, user=None, *args, **kwargs):
-    pass
+    """Alternatively to create_user lets user confirm account creation before authenticating"""
+    if user:
+        return None