diff --git a/static/styles/portico-signin.scss b/static/styles/portico-signin.scss index c9f3c666f0..10b5dff3fc 100644 --- a/static/styles/portico-signin.scss +++ b/static/styles/portico-signin.scss @@ -635,7 +635,7 @@ button.login-google-button { transform: translateX(15px) translateY(13px); } -.azure-wrapper::before { +.azuread-wrapper::before { content: "\f17a"; position: absolute; diff --git a/templates/zerver/login.html b/templates/zerver/login.html index c738c20cbe..6eb291b637 100644 --- a/templates/zerver/login.html +++ b/templates/zerver/login.html @@ -143,27 +143,16 @@ {% endif %} - {% if github_auth_enabled %} + {% for backend in social_backends %}
-
+
- {% endif %} - - {% if azuread_auth_enabled %} -
-
- - -
-
- {% endif %} + {% endfor %}
{% if email_auth_enabled %} diff --git a/zerver/context_processors.py b/zerver/context_processors.py index 9bf3a55bd4..d05fb41b49 100644 --- a/zerver/context_processors.py +++ b/zerver/context_processors.py @@ -2,6 +2,7 @@ from typing import Any, Dict, Optional from django.http import HttpRequest from django.conf import settings +from django.urls import reverse from zerver.models import UserProfile, get_realm, Realm from zproject.backends import ( @@ -10,6 +11,7 @@ from zproject.backends import ( require_email_format_usernames, auth_enabled_helper, AUTH_BACKEND_NAME_MAP, + SOCIAL_AUTH_BACKENDS, ) from zerver.lib.bugdown import convert as bugdown_convert from zerver.lib.send_email import FromAddress @@ -147,4 +149,17 @@ def zulip_default_context(request: HttpRequest) -> Dict[str, Any]: name_lower = auth_backend_name.lower() key = "%s_auth_enabled" % (name_lower,) context[key] = auth_enabled_helper([auth_backend_name], realm) + + social_backends = [] + for backend in SOCIAL_AUTH_BACKENDS: + if not auth_enabled_helper([backend.auth_backend_name], realm): + continue + social_backends.append({ + 'name': backend.name, + 'display_name': backend.auth_backend_name, + 'login_url': reverse('login-social', args=(backend.name,)), + 'sort_order': backend.sort_order, + }) + context['social_backends'] = sorted(social_backends, key=lambda x: x['sort_order']) + return context diff --git a/zproject/backends.py b/zproject/backends.py index a71d9d1f7f..0418c9e984 100644 --- a/zproject/backends.py +++ b/zproject/backends.py @@ -650,6 +650,8 @@ def social_auth_finish(backend: Any, class SocialAuthMixin(ZulipAuthMixin): auth_backend_name = "undeclared" + # Used to determine how to order buttons on login form + sort_order = 0 def auth_complete(self, *args: Any, **kwargs: Any) -> Optional[HttpResponse]: """This is a small wrapper around the core `auth_complete` method of @@ -676,6 +678,7 @@ class SocialAuthMixin(ZulipAuthMixin): class GitHubAuthBackend(SocialAuthMixin, GithubOAuth2): auth_backend_name = "GitHub" + sort_order = 50 def get_verified_emails(self, *args: Any, **kwargs: Any) -> List[str]: access_token = kwargs["response"]["access_token"] @@ -727,6 +730,7 @@ class GitHubAuthBackend(SocialAuthMixin, GithubOAuth2): raise AssertionError("Invalid configuration") class AzureADAuthBackend(SocialAuthMixin, AzureADOAuth2): + sort_order = 100 auth_backend_name = "AzureAD" AUTH_BACKEND_NAME_MAP = { @@ -737,9 +741,11 @@ AUTH_BACKEND_NAME_MAP = { 'RemoteUser': ZulipRemoteUserBackend, } # type: Dict[str, Any] OAUTH_BACKEND_NAMES = ["Google"] # type: List[str] +SOCIAL_AUTH_BACKENDS = [] # type: List[BaseOAuth2] # Authomatically add all of our social auth backends to relevant data structures. for social_auth_subclass in SocialAuthMixin.__subclasses__(): AUTH_BACKEND_NAME_MAP[social_auth_subclass.auth_backend_name] = social_auth_subclass if issubclass(social_auth_subclass, BaseOAuth2): OAUTH_BACKEND_NAMES.append(social_auth_subclass.auth_backend_name) + SOCIAL_AUTH_BACKENDS.append(social_auth_subclass)