social_backends: Remove sort_order from social backend dicts.

These are returned through the API, at the /server_settings
endpoint. It's better to just return the list of dicts with a guarantee
of being sorted in the correct order, than to clutter things with the
sort_order field.
This commit is contained in:
Mateusz Mandera 2019-11-02 04:35:39 +01:00 committed by Tim Abbott
parent 339f742578
commit 5a39e70bce
4 changed files with 38 additions and 15 deletions

View File

@ -58,10 +58,9 @@ Fetch global settings for a Zulip server.
authentication backends (such as google/github/SAML). Each dictionary specifies
the name and icon that should be displayed on the login buttons (`display_name`
and `display_icon`, where `display_icon` can be the empty string, if no icon
is to be displayed), the URLs that should be accessed to initiate login/signup
with the backend (`login_url` and `signup_url`) and `sort_order` (number
specifying in what order to show the login buttons for the social backends -
those with higher `sort_order` should be shown first).
is to be displayed) and the URLs that should be accessed to initiate login/signup
with the backend (`login_url` and `signup_url`). The list is sorted in the order
in which these authentication methods should be displayed.
[ldap-auth]: https://zulip.readthedocs.io/en/latest/production/authentication-methods.html#ldap-including-active-directory

View File

@ -2241,24 +2241,21 @@ paths:
"display_name": "SAML",
"display_logo": "",
"login_url": "/accounts/login/social/saml/idp_name",
"signup_url": "/accounts/register/social/saml/idp_name",
"sort_order": 9999
"signup_url": "/accounts/register/social/saml/idp_name"
},
{
"name": "google",
"display_name": "Google",
"display_logo": "/static/images/landing-page/logos/googl_e-icon.png",
"login_url": "/accounts/login/social/google",
"signup_url": "/accounts/register/social/google",
"sort_order": 150
"signup_url": "/accounts/register/social/google"
},
{
"name": "github",
"display_name": "GitHub",
"display_logo": "/static/images/landing-page/logos/github-icon.png",
"login_url": "/accounts/login/social/github",
"signup_url": "/accounts/register/social/github",
"sort_order": 100
"signup_url": "/accounts/register/social/github"
}
]
}

View File

@ -57,7 +57,7 @@ from zproject.backends import ZulipDummyBackend, EmailAuthBackend, \
ZulipLDAPConfigurationError, ZulipLDAPExceptionOutsideDomain, \
ZulipLDAPException, query_ldap, sync_user_from_ldap, SocialAuthMixin, \
PopulateUserLDAPError, SAMLAuthBackend, saml_auth_enabled, email_belongs_to_ldap, \
get_social_backend_dicts
get_social_backend_dicts, AzureADAuthBackend
from zerver.views.auth import (maybe_send_to_registration,
_subdomain_token_salt)
@ -1829,6 +1829,27 @@ class DevGetEmailsTest(ZulipTestCase):
result = self.client_get("/api/v1/dev_list_users")
self.assert_json_error_contains(result, "Dev environment not enabled.", 400)
class SocialBackendDictsTests(ZulipTestCase):
def test_get_social_backend_dicts_correctly_sorted(self) -> None:
with self.settings(
AUTHENTICATION_BACKENDS=('zproject.backends.EmailAuthBackend',
'zproject.backends.GitHubAuthBackend',
'zproject.backends.GoogleAuthBackend',
'zproject.backends.SAMLAuthBackend',
'zproject.backends.AzureADAuthBackend')
):
social_backends = get_social_backend_dicts()
# First backends in the list should be SAML:
self.assertIn('saml:', social_backends[0]['name'])
self.assertEqual(
[social_backend['name'] for social_backend in social_backends[1:]],
[social_backend.name for social_backend in sorted(
[GitHubAuthBackend, AzureADAuthBackend, GoogleAuthBackend],
key=lambda x: x.sort_order,
reverse=True
)]
)
class FetchAuthBackends(ZulipTestCase):
def assert_on_error(self, error: Optional[str]) -> None:
if error:
@ -1860,6 +1881,7 @@ class FetchAuthBackends(ZulipTestCase):
result = self.client_get("/api/v1/server_settings", subdomain="", HTTP_USER_AGENT="")
check_result(result)
self.assertEqual(result.json()['social_backends'], get_social_backend_dicts())
result = self.client_get("/api/v1/server_settings", subdomain="", HTTP_USER_AGENT="ZulipInvalid")
self.assertTrue(result.json()["is_incompatible"])

View File

@ -1257,7 +1257,6 @@ SocialBackendDictT = TypedDict('SocialBackendDictT', {
'display_logo': str,
'login_url': str,
'signup_url': str,
'sort_order': int,
})
def create_standard_social_backend_dict(social_backend: SocialAuthMixin) -> SocialBackendDictT:
@ -1268,7 +1267,6 @@ def create_standard_social_backend_dict(social_backend: SocialAuthMixin) -> Soci
display_logo=social_backend.display_logo,
login_url=reverse('login-social', args=(social_backend.name,)),
signup_url=reverse('signup-social', args=(social_backend.name,)),
sort_order=social_backend.sort_order
)
def list_saml_backend_dicts(realm: Optional[Realm]=None) -> List[SocialBackendDictT]:
@ -1280,22 +1278,27 @@ def list_saml_backend_dicts(realm: Optional[Realm]=None) -> List[SocialBackendDi
display_logo=idp_dict.get('display_logo', SAMLAuthBackend.display_logo),
login_url=reverse('login-social-extra-arg', args=('saml', idp_name)),
signup_url=reverse('signup-social-extra-arg', args=('saml', idp_name)),
sort_order=SAMLAuthBackend.sort_order - len(result)
) # type: SocialBackendDictT
result.append(saml_dict)
return result
def get_social_backend_dicts(realm: Optional[Realm]=None) -> List[SocialBackendDictT]:
"""
Returns a list of dictionaries that represent social backends, sorted
in the order in which they should be displayed.
"""
result = []
for backend in SOCIAL_AUTH_BACKENDS:
# SOCIAL_AUTH_BACKENDS is already sorted in the correct order,
# so we don't need to worry about sorting here.
if auth_enabled_helper([backend.auth_backend_name], realm):
if backend != SAMLAuthBackend:
result.append(create_standard_social_backend_dict(backend))
else:
result += list_saml_backend_dicts(realm)
return sorted(result, key=lambda x: x['sort_order'], reverse=True)
return result
AUTH_BACKEND_NAME_MAP = {
'Dev': DevAuthBackend,
@ -1310,6 +1313,8 @@ for social_auth_subclass in SocialAuthMixin.__subclasses__():
AUTH_BACKEND_NAME_MAP[social_auth_subclass.auth_backend_name] = social_auth_subclass
SOCIAL_AUTH_BACKENDS.append(social_auth_subclass)
SOCIAL_AUTH_BACKENDS = sorted(SOCIAL_AUTH_BACKENDS, key=lambda x: x.sort_order, reverse=True)
# Provide this alternative name for backwards compatibility with
# installations that had the old backend enabled.
GoogleMobileOauth2Backend = GoogleAuthBackend