def login_page(request, **kwargs): # type: (HttpRequest, **Any) -> HttpResponse if request.user.is_authenticated: return HttpResponseRedirect(request.user.realm.uri) if is_subdomain_root_or_alias(request) and settings.ROOT_DOMAIN_LANDING_PAGE: redirect_url = reverse('zerver.views.registration.find_account') return HttpResponseRedirect(redirect_url) realm = get_realm_from_request(request) if realm and realm.deactivated: return redirect_to_deactivation_notice() extra_context = kwargs.pop('extra_context', {}) if dev_auth_enabled(): if 'new_realm' in request.POST: realm = get_realm(request.POST['new_realm']) else: realm = get_realm_from_request(request) users = get_dev_users(realm) extra_context['current_realm'] = realm extra_context['all_realms'] = Realm.objects.all() extra_context['direct_admins'] = [u for u in users if u.is_realm_admin] extra_context['direct_users'] = [u for u in users if not u.is_realm_admin] if realm and 'new_realm' in request.POST: # If we're switching realms, redirect to that realm, but # only if it actually exists. return HttpResponseRedirect(realm.uri) try: template_response = django_login_page( request, authentication_form=OurAuthenticationForm, extra_context=extra_context, **kwargs) except ZulipLDAPConfigurationError as e: assert len(e.args) > 1 return redirect_to_misconfigured_ldap_notice(e.args[1]) try: template_response.context_data['email'] = request.GET['email'] except KeyError: pass try: already_registered = request.GET['already_registered'] template_response.context_data['already_registered'] = already_registered except KeyError: pass try: template_response.context_data['subdomain'] = request.GET['subdomain'] template_response.context_data['wrong_subdomain_error'] = WRONG_SUBDOMAIN_ERROR except KeyError: pass return template_response
def login_page(request: HttpRequest, **kwargs: Any) -> HttpResponse: if settings.TWO_FACTOR_AUTHENTICATION_ENABLED: if request.user and request.user.is_verified(): return HttpResponseRedirect(request.user.realm.uri) elif request.user.is_authenticated: return HttpResponseRedirect(request.user.realm.uri) if is_subdomain_root_or_alias(request) and settings.ROOT_DOMAIN_LANDING_PAGE: redirect_url = reverse('zerver.views.registration.realm_redirect') if request.method == "GET" and request.GET: redirect_url = "{}?{}".format(redirect_url, request.GET.urlencode()) return HttpResponseRedirect(redirect_url) realm = get_realm_from_request(request) if realm and realm.deactivated: return redirect_to_deactivation_notice() extra_context = kwargs.pop('extra_context', {}) if dev_auth_enabled(): if 'new_realm' in request.POST: realm = get_realm(request.POST['new_realm']) else: realm = get_realm_from_request(request) add_dev_login_context(realm, extra_context) if realm and 'new_realm' in request.POST: # If we're switching realms, redirect to that realm, but # only if it actually exists. return HttpResponseRedirect(realm.uri) if 'username' in request.POST: extra_context['email'] = request.POST['username'] if settings.TWO_FACTOR_AUTHENTICATION_ENABLED: return start_two_factor_auth(request, extra_context=extra_context, **kwargs) try: template_response = django_login_page( request, authentication_form=OurAuthenticationForm, extra_context=extra_context, **kwargs) except ZulipLDAPConfigurationError as e: assert len(e.args) > 1 return redirect_to_misconfigured_ldap_notice(e.args[1]) if isinstance(template_response, SimpleTemplateResponse): # Only those responses that are rendered using a template have # context_data attribute. This attribute doesn't exist otherwise. It is # added in SimpleTemplateResponse class, which is a derived class of # HttpResponse. See django.template.response.SimpleTemplateResponse, # https://github.com/django/django/blob/master/django/template/response.py#L19. update_login_page_context(request, template_response.context_data) return template_response
def show_deactivation_notice(request: HttpRequest) -> HttpResponse: realm = get_realm_from_request(request) if realm and realm.deactivated: return render(request, "zerver/deactivated.html", context={"deactivated_domain_name": realm.name}) return HttpResponseRedirect(reverse('zerver.views.auth.login_page'))
def plans_view(request: HttpRequest) -> HttpResponse: realm = get_realm_from_request(request) if realm is not None: if realm.plan_type == Realm.SELF_HOSTED: return HttpResponseRedirect('https://zulipchat.com/plans') if not request.user.is_authenticated(): return redirect_to_login(next="plans") return render(request, "zerver/plans.html")
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]: context = super().get_context_data(**kwargs) if self.extra_context is not None: context.update(self.extra_context) update_login_page_context(self.request, context) realm = get_realm_from_request(self.request) redirect_to = realm.uri if realm else '/' context['next'] = self.request.GET.get('next', redirect_to) return context
def accounts_home_from_multiuse_invite(request: HttpRequest, confirmation_key: str) -> HttpResponse: multiuse_object = None try: multiuse_object = get_object_from_key(confirmation_key, Confirmation.MULTIUSE_INVITE) # Required for oAuth2 request.session["multiuse_object_key"] = confirmation_key except ConfirmationKeyException as exception: realm = get_realm_from_request(request) if realm is None or realm.invite_required: return render_confirmation_key_error(request, exception) return accounts_home(request, multiuse_object=multiuse_object)
def maybe_send_to_registration(request: HttpRequest, email: Text, full_name: Text='', password_required: bool=True) -> HttpResponse: realm = get_realm_from_request(request) from_multiuse_invite = False multiuse_obj = None streams_to_subscribe = None multiuse_object_key = request.session.get("multiuse_object_key", None) if multiuse_object_key is not None: from_multiuse_invite = True multiuse_obj = Confirmation.objects.get(confirmation_key=multiuse_object_key).content_object realm = multiuse_obj.realm streams_to_subscribe = multiuse_obj.streams.all() form = HomepageForm({'email': email}, realm=realm, from_multiuse_invite=from_multiuse_invite) request.verified_email = None if form.is_valid(): # Construct a PreregistrationUser object and send the user over to # the confirmation view. prereg_user = None if settings.ONLY_SSO: try: prereg_user = PreregistrationUser.objects.filter( email__iexact=email, realm=realm).latest("invited_at") except PreregistrationUser.DoesNotExist: prereg_user = create_preregistration_user(email, request, password_required=password_required) else: prereg_user = create_preregistration_user(email, request, password_required=password_required) if multiuse_object_key is not None: del request.session["multiuse_object_key"] request.session.modified = True if streams_to_subscribe is not None: prereg_user.streams = streams_to_subscribe prereg_user.save() return redirect("".join(( create_confirmation_link(prereg_user, request.get_host(), Confirmation.USER_REGISTRATION), '?full_name=', # urllib does not handle Unicode, so coerece to encoded byte string # Explanation: http://stackoverflow.com/a/5605354/90777 urllib.parse.quote_plus(full_name.encode('utf8'))))) else: url = reverse('register') return render(request, 'zerver/accounts_home.html', context={'form': form, 'current_url': lambda: url, 'from_multiuse_invite': from_multiuse_invite}, )
def api_fetch_api_key(request: HttpRequest, username: str=REQ(), password: str=REQ()) -> HttpResponse: return_data = {} # type: Dict[str, bool] subdomain = get_subdomain(request) realm = get_realm(subdomain) if username == "google-oauth2-token": # This code path is auth for the legacy Android app user_profile = authenticate(google_oauth2_token=password, realm=realm, return_data=return_data) else: if not ldap_auth_enabled(realm=get_realm_from_request(request)): # In case we don't authenticate against LDAP, check for a valid # email. LDAP backend can authenticate against a non-email. validate_login_email(username) user_profile = authenticate(username=username, password=password, realm=realm, return_data=return_data) if return_data.get("inactive_user"): return json_error(_("Your account has been disabled."), data={"reason": "user disable"}, status=403) if return_data.get("inactive_realm"): return json_error(_("This organization has been deactivated."), data={"reason": "realm deactivated"}, status=403) if return_data.get("password_auth_disabled"): return json_error(_("Password auth is disabled in your team."), data={"reason": "password auth disabled"}, status=403) if user_profile is None: if return_data.get("valid_attestation"): # We can leak that the user is unregistered iff # they present a valid authentication string for the user. return json_error(_("This user is not registered; do so from a browser."), data={"reason": "unregistered"}, status=403) return json_error(_("Your username or password is incorrect."), data={"reason": "incorrect_creds"}, status=403) # Maybe sending 'user_logged_in' signal is the better approach: # user_logged_in.send(sender=user_profile.__class__, request=request, user=user_profile) # Not doing this only because over here we don't add the user information # in the session. If the signal receiver assumes that we do then that # would cause problems. email_on_new_login(sender=user_profile.__class__, request=request, user=user_profile) # Mark this request as having a logged-in user for our server logs. process_client(request, user_profile) request._email = user_profile.email api_key = get_api_key(user_profile) return json_success({"api_key": api_key, "email": user_profile.email})
def login_page(request: HttpRequest, **kwargs: Any) -> HttpResponse: # To support previewing the Zulip login pages, we have a special option # that disables the default behavior of redirecting logged-in users to the # logged-in app. is_preview = 'preview' in request.GET if settings.TWO_FACTOR_AUTHENTICATION_ENABLED: if request.user and request.user.is_verified(): return HttpResponseRedirect(request.user.realm.uri) elif request.user.is_authenticated and not is_preview: return HttpResponseRedirect(request.user.realm.uri) if is_subdomain_root_or_alias( request) and settings.ROOT_DOMAIN_LANDING_PAGE: redirect_url = reverse('zerver.views.registration.realm_redirect') if request.GET: redirect_url = "{}?{}".format(redirect_url, request.GET.urlencode()) return HttpResponseRedirect(redirect_url) realm = get_realm_from_request(request) if realm and realm.deactivated: return redirect_to_deactivation_notice() extra_context = kwargs.pop('extra_context', {}) if dev_auth_enabled() and kwargs.get( "template_name") == "zerver/dev_login.html": if 'new_realm' in request.POST: try: realm = get_realm(request.POST['new_realm']) except Realm.DoesNotExist: realm = None add_dev_login_context(realm, extra_context) if realm and 'new_realm' in request.POST: # If we're switching realms, redirect to that realm, but # only if it actually exists. return HttpResponseRedirect(realm.uri) if 'username' in request.POST: extra_context['email'] = request.POST['username'] extra_context.update(login_context(request)) if settings.TWO_FACTOR_AUTHENTICATION_ENABLED: return start_two_factor_auth(request, extra_context=extra_context, **kwargs) try: template_response = DjangoLoginView.as_view( authentication_form=OurAuthenticationForm, extra_context=extra_context, **kwargs)(request) except ZulipLDAPConfigurationError as e: assert len(e.args) > 1 return redirect_to_misconfigured_ldap_notice(e.args[1]) if isinstance(template_response, SimpleTemplateResponse): # Only those responses that are rendered using a template have # context_data attribute. This attribute doesn't exist otherwise. It is # added in SimpleTemplateResponse class, which is a derived class of # HttpResponse. See django.template.response.SimpleTemplateResponse, # https://github.com/django/django/blob/master/django/template/response.py#L19. update_login_page_context(request, template_response.context_data) return template_response
def api_fetch_api_key( request: HttpRequest, username: str = REQ(), password: str = REQ() ) -> HttpResponse: return_data = {} # type: Dict[str, bool] subdomain = get_subdomain(request) realm = get_realm(subdomain) if username == "google-oauth2-token": # This code path is auth for the legacy Android app user_profile = authenticate(google_oauth2_token=password, realm=realm, return_data=return_data) else: if not ldap_auth_enabled(realm=get_realm_from_request(request)): # In case we don't authenticate against LDAP, check for a valid # email. LDAP backend can authenticate against a non-email. validate_login_email(username) user_profile = authenticate(username=username, password=password, realm=realm, return_data=return_data) if return_data.get("inactive_user"): return json_error(_("Your account has been disabled."), data={"reason": "user disable"}, status=403) if return_data.get("inactive_realm"): return json_error(_("This organization has been deactivated."), data={"reason": "realm deactivated"}, status=403) if return_data.get("password_auth_disabled"): return json_error(_("Password auth is disabled in your team."), data={"reason": "password auth disabled"}, status=403) if user_profile is None: if return_data.get("valid_attestation"): # We can leak that the user is unregistered iff # they present a valid authentication string for the user. return json_error( _("This user is not registered; do so from a browser."), data={"reason": "unregistered"}, status=403) return json_error(_("Your username or password is incorrect."), data={"reason": "incorrect_creds"}, status=403) # Maybe sending 'user_logged_in' signal is the better approach: # user_logged_in.send(sender=user_profile.__class__, request=request, user=user_profile) # Not doing this only because over here we don't add the user information # in the session. If the signal receiver assumes that we do then that # would cause problems. email_on_new_login(sender=user_profile.__class__, request=request, user=user_profile) # Mark this request as having a logged-in user for our server logs. process_client(request, user_profile) request._email = user_profile.email api_key = get_api_key(user_profile) return json_success({ "api_key": api_key, "email": user_profile.delivery_email })
def maybe_send_to_registration(request: HttpRequest, email: Text, full_name: Text = '', password_required: bool = True) -> HttpResponse: realm = get_realm_from_request(request) from_multiuse_invite = False multiuse_obj = None streams_to_subscribe = None multiuse_object_key = request.session.get("multiuse_object_key", None) if multiuse_object_key is not None: from_multiuse_invite = True multiuse_obj = Confirmation.objects.get( confirmation_key=multiuse_object_key).content_object realm = multiuse_obj.realm streams_to_subscribe = multiuse_obj.streams.all() form = HomepageForm({'email': email}, realm=realm, from_multiuse_invite=from_multiuse_invite) request.verified_email = None if form.is_valid(): # Construct a PreregistrationUser object and send the user over to # the confirmation view. prereg_user = None if settings.ONLY_SSO: try: prereg_user = PreregistrationUser.objects.filter( email__iexact=email, realm=realm).latest("invited_at") except PreregistrationUser.DoesNotExist: prereg_user = create_preregistration_user( email, request, password_required=password_required) else: prereg_user = create_preregistration_user( email, request, password_required=password_required) if multiuse_object_key is not None: del request.session["multiuse_object_key"] request.session.modified = True if streams_to_subscribe is not None: prereg_user.streams = streams_to_subscribe prereg_user.save() return redirect("".join(( create_confirmation_link(prereg_user, request.get_host(), Confirmation.USER_REGISTRATION), '?full_name=', # urllib does not handle Unicode, so coerece to encoded byte string # Explanation: http://stackoverflow.com/a/5605354/90777 urllib.parse.quote_plus(full_name.encode('utf8'))))) else: url = reverse('register') return render( request, 'zerver/accounts_home.html', context={ 'form': form, 'current_url': lambda: url, 'from_multiuse_invite': from_multiuse_invite }, )
def api_fetch_api_key( request: HttpRequest, username: str = REQ(), password: str = REQ() ) -> HttpResponse: return_data: Dict[str, bool] = {} realm = get_realm_from_request(request) if realm is None: return json_error(_("Invalid subdomain")) if not ldap_auth_enabled(realm=realm): # In case we don't authenticate against LDAP, check for a valid # email. LDAP backend can authenticate against a non-email. validate_login_email(username) user_profile = authenticate(request=request, username=username, password=password, realm=realm, return_data=return_data) if return_data.get("inactive_user"): return json_error(_("Your account has been disabled."), data={"reason": "user disable"}, status=403) if return_data.get("inactive_realm"): return json_error( _("This organization has been deactivated."), data={"reason": "realm deactivated"}, status=403, ) if return_data.get("password_auth_disabled"): return json_error( _("Password auth is disabled in your team."), data={"reason": "password auth disabled"}, status=403, ) if return_data.get("password_reset_needed"): return json_error( _("You need to reset your password."), data={"reason": "password reset needed"}, status=403, ) if user_profile is None: return json_error( _("Your username or password is incorrect."), data={"reason": "incorrect_creds"}, status=403, ) # Maybe sending 'user_logged_in' signal is the better approach: # user_logged_in.send(sender=user_profile.__class__, request=request, user=user_profile) # Not doing this only because over here we don't add the user information # in the session. If the signal receiver assumes that we do then that # would cause problems. email_on_new_login(sender=user_profile.__class__, request=request, user=user_profile) # Mark this request as having a logged-in user for our server logs. process_client(request, user_profile) request._requestor_for_logs = user_profile.format_requestor_for_logs() api_key = get_api_key(user_profile) return json_success({ "api_key": api_key, "email": user_profile.delivery_email })
def login_page( request: HttpRequest, next: str = REQ(default="/"), **kwargs: Any, ) -> HttpResponse: if settings.SOCIAL_AUTH_SUBDOMAIN == get_subdomain(request): return social_auth_subdomain_login_page(request) # To support previewing the Zulip login pages, we have a special option # that disables the default behavior of redirecting logged-in users to the # logged-in app. is_preview = "preview" in request.GET if settings.TWO_FACTOR_AUTHENTICATION_ENABLED: if request.user and request.user.is_verified(): return HttpResponseRedirect(request.user.realm.uri) elif request.user.is_authenticated and not is_preview: return HttpResponseRedirect(request.user.realm.uri) if is_subdomain_root_or_alias( request) and settings.ROOT_DOMAIN_LANDING_PAGE: redirect_url = reverse("realm_redirect") if request.GET: redirect_url = append_url_query_string(redirect_url, request.GET.urlencode()) return HttpResponseRedirect(redirect_url) realm = get_realm_from_request(request) if realm and realm.deactivated: return redirect_to_deactivation_notice() extra_context = kwargs.pop("extra_context", {}) extra_context["next"] = next if dev_auth_enabled() and kwargs.get( "template_name") == "zerver/development/dev_login.html": from zerver.views.development.dev_login import add_dev_login_context if "new_realm" in request.POST: try: realm = get_realm(request.POST["new_realm"]) except Realm.DoesNotExist: realm = None add_dev_login_context(realm, extra_context) if realm and "new_realm" in request.POST: # If we're switching realms, redirect to that realm, but # only if it actually exists. return HttpResponseRedirect(realm.uri) if "username" in request.POST: extra_context["email"] = request.POST["username"] extra_context.update(login_context(request)) if settings.TWO_FACTOR_AUTHENTICATION_ENABLED: return start_two_factor_auth(request, extra_context=extra_context, **kwargs) try: template_response = DjangoLoginView.as_view( authentication_form=OurAuthenticationForm, extra_context=extra_context, **kwargs)(request) except ZulipLDAPConfigurationError as e: assert len(e.args) > 1 return redirect_to_misconfigured_ldap_notice(request, e.args[1]) if isinstance(template_response, SimpleTemplateResponse): # Only those responses that are rendered using a template have # context_data attribute. This attribute doesn't exist otherwise. It is # added in SimpleTemplateResponse class, which is a derived class of # HttpResponse. See django.template.response.SimpleTemplateResponse, # https://github.com/django/django/blob/2.0/django/template/response.py#L19 update_login_page_context(request, template_response.context_data) assert isinstance(template_response, HttpResponse) return template_response
def login_page(request, **kwargs): # type: (HttpRequest, **Any) -> HttpResponse if request.user.is_authenticated: return HttpResponseRedirect(request.user.realm.uri) if is_subdomain_root_or_alias( request) and settings.ROOT_DOMAIN_LANDING_PAGE: redirect_url = reverse('zerver.views.registration.find_account') return HttpResponseRedirect(redirect_url) realm = get_realm_from_request(request) if realm and realm.deactivated: return redirect_to_deactivation_notice() extra_context = kwargs.pop('extra_context', {}) if dev_auth_enabled(): if 'new_realm' in request.POST: realm = get_realm(request.POST['new_realm']) else: realm = get_realm_from_request(request) users = get_dev_users(realm) extra_context['current_realm'] = realm extra_context['all_realms'] = Realm.objects.all() extra_context['direct_admins'] = [u for u in users if u.is_realm_admin] extra_context['direct_users'] = [ u for u in users if not u.is_realm_admin ] if realm and 'new_realm' in request.POST: # If we're switching realms, redirect to that realm, but # only if it actually exists. return HttpResponseRedirect(realm.uri) try: template_response = django_login_page( request, authentication_form=OurAuthenticationForm, extra_context=extra_context, **kwargs) except ZulipLDAPConfigurationError as e: assert len(e.args) > 1 return redirect_to_misconfigured_ldap_notice(e.args[1]) try: template_response.context_data['email'] = request.GET['email'] except KeyError: pass try: already_registered = request.GET['already_registered'] template_response.context_data[ 'already_registered'] = already_registered except KeyError: pass try: template_response.context_data['subdomain'] = request.GET['subdomain'] template_response.context_data[ 'wrong_subdomain_error'] = WRONG_SUBDOMAIN_ERROR except KeyError: pass return template_response