Exemplo n.º 1
0
def api_dev_fetch_api_key(request: HttpRequest, username: str = REQ()) -> HttpResponse:
    """This function allows logging in without a password on the Zulip
    mobile apps when connecting to a Zulip development environment.  It
    requires DevAuthBackend to be included in settings.AUTHENTICATION_BACKENDS.
    """
    check_dev_auth_backend()

    # Django invokes authenticate methods by matching arguments, and this
    # authentication flow will not invoke LDAP authentication because of
    # this condition of Django so no need to check if LDAP backend is
    # enabled.
    validate_login_email(username)
    realm = get_realm_from_request(request)
    if realm is None:
        raise InvalidSubdomainError()
    return_data: Dict[str, bool] = {}
    user_profile = authenticate(dev_auth_username=username, realm=realm, return_data=return_data)
    if return_data.get("inactive_realm"):
        raise RealmDeactivatedError()
    if return_data.get("inactive_user"):
        raise UserDeactivatedError()
    if return_data.get("invalid_subdomain"):
        raise InvalidSubdomainError()
    if user_profile is None:
        # Since we're not actually checking passwords, this condition
        # is when one's attempting to send an email address that
        # doesn't have an account, i.e. it's definitely invalid username.
        raise AuthenticationFailedError()
    assert user_profile is not None

    do_login(request, user_profile)
    api_key = get_api_key(user_profile)
    return json_success(request, data={"api_key": api_key, "email": user_profile.delivery_email})
Exemplo n.º 2
0
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:
        raise InvalidSubdomainError()

    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"):
        raise UserDeactivatedError()
    if return_data.get("inactive_realm"):
        raise RealmDeactivatedError()
    if return_data.get("password_auth_disabled"):
        raise PasswordAuthDisabledError()
    if return_data.get("password_reset_needed"):
        raise PasswordResetRequiredError()
    if user_profile is None:
        raise AuthenticationFailedError()

    assert user_profile.is_authenticated

    # 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.
    assert isinstance(user_profile, UserProfile)
    process_client(request, user_profile)
    RequestNotes.get_notes(
        request).requestor_for_logs = user_profile.format_requestor_for_logs()

    api_key = get_api_key(user_profile)
    return json_success(request,
                        data={
                            "api_key": api_key,
                            "email": user_profile.delivery_email
                        })
Exemplo n.º 3
0
def confirm_email_change(request: HttpRequest,
                         confirmation_key: str) -> HttpResponse:
    try:
        email_change_object = get_object_from_key(confirmation_key,
                                                  [Confirmation.EMAIL_CHANGE])
    except ConfirmationKeyException as exception:
        return render_confirmation_key_error(request, exception)

    new_email = email_change_object.new_email
    old_email = email_change_object.old_email
    user_profile = email_change_object.user_profile

    if user_profile.realm.deactivated:
        return redirect_to_deactivation_notice()

    if not user_profile.is_active:
        # TODO: Make this into a user-facing error, not JSON
        raise UserDeactivatedError()

    if user_profile.realm.email_changes_disabled and not user_profile.is_realm_admin:
        raise JsonableError(
            _("Email address changes are disabled in this organization."))

    do_change_user_delivery_email(user_profile, new_email)

    context = {"realm_name": user_profile.realm.name, "new_email": new_email}
    language = user_profile.default_language
    send_email(
        "zerver/emails/notify_change_in_email",
        to_emails=[old_email],
        from_name=FromAddress.security_email_from_name(
            user_profile=user_profile),
        from_address=FromAddress.SUPPORT,
        language=language,
        context=context,
        realm=user_profile.realm,
    )

    ctx = {
        "new_email_html_tag":
        SafeString(
            f'<a href="mailto:{escape(new_email)}">{escape(new_email)}</a>'),
        "old_email_html_tag":
        SafeString(
            f'<a href="mailto:{escape(old_email)}">{escape(old_email)}</a>'),
    }
    return render(request,
                  "confirmation/confirm_email_change.html",
                  context=ctx)
Exemplo n.º 4
0
def validate_account_and_subdomain(request: HttpRequest,
                                   user_profile: UserProfile) -> None:
    if user_profile.realm.deactivated:
        raise RealmDeactivatedError()
    if not user_profile.is_active:
        raise UserDeactivatedError()

    # Either the subdomain matches, or we're accessing Tornado from
    # and to localhost (aka spoofing a request as the user).
    if not user_matches_subdomain(
            get_subdomain(request), user_profile) and not (
                settings.RUNNING_INSIDE_TORNADO and request.META["SERVER_NAME"]
                == "127.0.0.1" and request.META["REMOTE_ADDR"] == "127.0.0.1"):
        logging.warning(
            "User %s (%s) attempted to access API on wrong subdomain (%s)",
            user_profile.delivery_email,
            user_profile.realm.subdomain,
            get_subdomain(request),
        )
        raise JsonableError(_("Account is not associated with this subdomain"))