From 46e224997e06f9c4c39718e9df6a806cafe5ba31 Mon Sep 17 00:00:00 2001 From: David Roe Date: Tue, 18 Aug 2015 17:58:20 -0700 Subject: [PATCH] Add a new dev login page for logging in without a password on the dev VM. (imported from commit ac8f2504771c9907b7e92dc91cec5f7220ce951b) --- static/styles/portico.css | 28 ++++++++++++++++++++++++++++ templates/zerver/login.html | 27 ++++++++++++++++++++++++++- zerver/context_processors.py | 6 ++++-- zerver/views/__init__.py | 21 ++++++++++++++++++--- zproject/backends.py | 24 +++++++++++++++++++++++- zproject/local_settings.py | 4 ++++ zproject/urls.py | 1 + 7 files changed, 104 insertions(+), 7 deletions(-) diff --git a/static/styles/portico.css b/static/styles/portico.css index 6591466b93..3642309faa 100644 --- a/static/styles/portico.css +++ b/static/styles/portico.css @@ -693,6 +693,17 @@ a.bottom-signup-button { margin-bottom: 50px; } +.login-page-subheader { + font-weight: 300; + font-size: 24px; + display: block; + margin: auto; + width: 300px; + text-align: center; + margin-top: -30px; + margin-bottom: 50px; +} + .feature-page-header, .api-page-header, .apps-page-header, @@ -761,6 +772,18 @@ a.bottom-signup-button { margin-bottom: 15px; } +.btn-direct { + margin-top: 0px; + margin-bottom: 0px; + padding: 8px; + color: #fff; + font-size: 18px; + background-color: #428bca; + border-color: #357ebd; + border-radius: 5px; + min-width: 300px; +} + .feature-page-header { width: auto; } @@ -792,6 +815,11 @@ a.bottom-signup-button { margin-bottom: 2px; } +.login-form .direct-label { + margin-top: 50px; + margin-bottom: 6px; +} + .login-form #id_username, .login-form #id_password { width: 100%; diff --git a/templates/zerver/login.html b/templates/zerver/login.html index 1d4841693e..733f8f8048 100644 --- a/templates/zerver/login.html +++ b/templates/zerver/login.html @@ -23,7 +23,14 @@ autofocus('#id_username');
{% endif %} + {% if password_auth_enabled or desktop_sso_dispatch %}
+ {% endif %} + {% if dev_auth_enabled %} +
+ {% csrf_token %} +
+ {% if password_auth_enabled %} + + {% endif %} +
+ {% for user_email in direct_users %} +

+ {% endfor %} +
+
+
+ {% endif %} - {% if not desktop_sso_dispatch %} + {% if google_auth_enabled %}
or
diff --git a/zerver/context_processors.py b/zerver/context_processors.py index 0e1c1c9aeb..b1a737e3a4 100644 --- a/zerver/context_processors.py +++ b/zerver/context_processors.py @@ -2,7 +2,7 @@ from __future__ import absolute_import from django.conf import settings import ujson -from zproject.backends import password_auth_enabled +from zproject.backends import password_auth_enabled, dev_auth_enabled, google_auth_enabled def add_settings(request): if hasattr(request.user, "realm"): @@ -16,7 +16,6 @@ def add_settings(request): # to the template 'not_enterprise': not settings.ENTERPRISE, 'zulip_admin': settings.ZULIP_ADMINISTRATOR, - 'password_auth_enabled': is_pw_auth_enabled, 'login_url': settings.HOME_NOT_LOGGED_IN, 'only_sso': settings.ONLY_SSO, 'external_api_path': settings.EXTERNAL_API_PATH, @@ -25,6 +24,9 @@ def add_settings(request): 'api_site_required': settings.EXTERNAL_API_PATH != "api.zulip.com", 'email_integration_enabled': settings.EMAIL_GATEWAY_BOT != "", 'email_gateway_example': settings.EMAIL_GATEWAY_EXAMPLE, + 'password_auth_enabled': is_pw_auth_enabled, + 'dev_auth_enabled': dev_auth_enabled(), + 'google_auth_enabled': google_auth_enabled(), } def add_metrics(request): diff --git a/zerver/views/__init__.py b/zerver/views/__init__.py index 4af1055ca7..a9e3e0947f 100644 --- a/zerver/views/__init__.py +++ b/zerver/views/__init__.py @@ -71,7 +71,7 @@ from zerver.lib.response import json_success, json_error, json_response from zerver.lib.unminify import SourceMap from zerver.lib.queue import queue_json_publish from zerver.lib.utils import statsd, generate_random_token, statsd_key -from zproject.backends import password_auth_enabled +from zproject.backends import password_auth_enabled, dev_auth_enabled from confirmation.models import Confirmation @@ -784,9 +784,12 @@ def finish_google_oauth2(request): return login_or_register_remote_user(request, email_address, user_profile, full_name) def login_page(request, **kwargs): + extra_context = kwargs.pop('extra_context',{}) + if dev_auth_enabled(): + extra_context['direct_users'] = sorted([u.email for u in UserProfile.objects.filter(is_bot=False, is_active=True)]) template_response = django_login_page( - request, authentication_form=OurAuthenticationForm, **kwargs) - + request, authentication_form=OurAuthenticationForm, + extra_context=extra_context, **kwargs) try: template_response.context_data['email'] = request.GET['email'] except KeyError: @@ -794,6 +797,18 @@ def login_page(request, **kwargs): return template_response +def dev_direct_login(request, **kwargs): + # This function allows logging in without a password and should only be called in development environments. + # It may be called if the DevAuthBackend is included in settings.AUTHENTICATION_BACKENDS + if (not dev_auth_enabled()) or settings.DEPLOYED: + # This check is probably not required, since authenticate would fail without an enabled DevAuthBackend. + raise Exception('Direct login not supported.') + email = request.POST['direct_email'] + user_profile = authenticate(username=email) + login(request, user_profile) + return HttpResponseRedirect("%s%s" % (settings.EXTERNAL_URI_SCHEME, + request.get_host())) + @authenticated_json_post_view @has_request_variables def json_bulk_invite_users(request, user_profile, diff --git a/zproject/backends.py b/zproject/backends.py index d64a37ddc9..567236c8e6 100644 --- a/zproject/backends.py +++ b/zproject/backends.py @@ -16,7 +16,7 @@ from oauth2client.crypt import AppIdentityError def password_auth_enabled(realm): if realm.domain == 'employees.customer16.invalid': return False - elif realm.domain == 'zulip.com' and not settings.TEST_SUITE: + elif realm.domain == 'zulip.com' and settings.DEPLOYED: # the dropbox realm is SSO only, but the unit tests still need to be # able to login return False @@ -26,6 +26,18 @@ def password_auth_enabled(realm): return True return False +def dev_auth_enabled(): + for backend in django.contrib.auth.get_backends(): + if isinstance(backend, DevAuthBackend): + return True + return False + +def google_auth_enabled(): + for backend in django.contrib.auth.get_backends(): + if isinstance(backend, GoogleMobileOauth2Backend): + return True + return False + class ZulipAuthMixin(object): def get_user(self, user_profile_id): """ Get a UserProfile object from the user_profile_id. """ @@ -162,3 +174,13 @@ class ZulipLDAPUserPopulator(ZulipLDAPAuthBackend): def authenticate(self, username, password): return None + +class DevAuthBackend(ZulipAuthMixin): + # Allow logging in as any user without a password. + # This is used for convenience when developing Zulip. + + def authenticate(self, username): + try: + return get_user_profile_by_email(username) + except UserProfile.DoesNotExist: + return None diff --git a/zproject/local_settings.py b/zproject/local_settings.py index cce160158d..c23dcf92da 100644 --- a/zproject/local_settings.py +++ b/zproject/local_settings.py @@ -174,6 +174,10 @@ EMAIL_GATEWAY_BOT = "emailgateway@zulip.com" SSO_APPEND_DOMAIN = None +## WARNING: DO NOT ENABLE DevAuthBackend UNLESS YOU WANT +## ANYONE TO BE ABLE TO LOG IN AS ANY USER. +# AUTHENTICATION_BACKENDS = ('zproject.backends.DevAuthBackend',) + AUTHENTICATION_BACKENDS = ('zproject.backends.EmailAuthBackend', 'zproject.backends.GoogleMobileOauth2Backend', 'zproject.backends.GoogleBackend') diff --git a/zproject/urls.py b/zproject/urls.py index 784ac45cdd..fc823ad3e8 100644 --- a/zproject/urls.py +++ b/zproject/urls.py @@ -26,6 +26,7 @@ urlpatterns = patterns('', url(r'^accounts/login/jwt/$', 'zerver.views.remote_user_jwt', name='login-jwt'), url(r'^accounts/login/google/$', 'zerver.views.start_google_oauth2'), url(r'^accounts/login/google/done/$', 'zerver.views.finish_google_oauth2'), + url(r'^accounts/login/local/$', 'zerver.views.dev_direct_login'), # We have two entries for accounts/login to allow reverses on the Django # view we're wrapping to continue to function. url(r'^accounts/login/', 'zerver.views.login_page', {'template_name': 'zerver/login.html'}),