コード例 #1
0
def do_get_invites_controlled_by_user(
        user_profile: UserProfile) -> List[Dict[str, Any]]:
    """
    Returns a list of dicts representing invitations that can be controlled by user_profile.
    This isn't necessarily the same as all the invitations generated by the user, as administrators
    can control also invitations that they did not themselves create.
    """
    if user_profile.is_realm_admin:
        prereg_users = filter_to_valid_prereg_users(
            PreregistrationUser.objects.filter(
                referred_by__realm=user_profile.realm))
    else:
        prereg_users = filter_to_valid_prereg_users(
            PreregistrationUser.objects.filter(referred_by=user_profile))

    invites = []

    for invitee in prereg_users:
        assert invitee.referred_by is not None
        invites.append(
            dict(
                email=invitee.email,
                invited_by_user_id=invitee.referred_by.id,
                invited=datetime_to_timestamp(invitee.invited_at),
                expiry_date=get_invitation_expiry_date(
                    invitee.confirmation.get()),
                id=invitee.id,
                invited_as=invitee.invited_as,
                is_multiuse=False,
            ))

    if not user_profile.is_realm_admin:
        # We do not return multiuse invites to non-admin users.
        return invites

    multiuse_confirmation_objs = Confirmation.objects.filter(
        realm=user_profile.realm, type=Confirmation.MULTIUSE_INVITE).filter(
            Q(expiry_date__gte=timezone_now()) | Q(expiry_date=None))
    for confirmation_obj in multiuse_confirmation_objs:
        invite = confirmation_obj.content_object
        assert invite is not None
        invites.append(
            dict(
                invited_by_user_id=invite.referred_by.id,
                invited=datetime_to_timestamp(confirmation_obj.date_sent),
                expiry_date=get_invitation_expiry_date(confirmation_obj),
                id=invite.id,
                link_url=confirmation_url(
                    confirmation_obj.confirmation_key,
                    user_profile.realm,
                    Confirmation.MULTIUSE_INVITE,
                ),
                invited_as=invite.invited_as,
                is_multiuse=True,
            ))
    return invites
コード例 #2
0
ファイル: queue_processors.py プロジェクト: not-so-rabh/zulip
    def consume(self, data: Mapping[str, Any]) -> None:
        invitee = filter_to_valid_prereg_users(
            PreregistrationUser.objects.filter(id=data["prereg_id"])
        ).first()
        if invitee is None:
            # The invitation could have been revoked
            return

        referrer = get_user_profile_by_id(data["referrer_id"])
        logger.info(
            "Sending invitation for realm %s to %s", referrer.realm.string_id, invitee.email
        )
        activate_url = do_send_confirmation_email(invitee, referrer)

        # queue invitation reminder
        if settings.INVITATION_LINK_VALIDITY_DAYS >= 4:
            context = common_context(referrer)
            context.update(
                activate_url=activate_url,
                referrer_name=referrer.full_name,
                referrer_email=referrer.delivery_email,
                referrer_realm_name=referrer.realm.name,
            )
            send_future_email(
                "zerver/emails/invitation_reminder",
                referrer.realm,
                to_emails=[invitee.email],
                from_address=FromAddress.tokenized_no_reply_placeholder,
                language=referrer.realm.default_language,
                context=context,
                delay=datetime.timedelta(days=settings.INVITATION_LINK_VALIDITY_DAYS - 2),
            )
コード例 #3
0
    def consume(self, data: Mapping[str, Any]) -> None:
        if "email" in data:
            # When upgrading from a version up through 1.7.1, there may be
            # existing items in the queue with `email` instead of `prereg_id`.
            invitee = filter_to_valid_prereg_users(
                PreregistrationUser.objects.filter(
                    email__iexact=data["email"].strip())).latest("invited_at")
        else:
            invitee = filter_to_valid_prereg_users(
                PreregistrationUser.objects.filter(
                    id=data["prereg_id"])).first()
            if invitee is None:
                # The invitation could have been revoked
                return

        referrer = get_user_profile_by_id(data["referrer_id"])
        logger.info("Sending invitation for realm %s to %s",
                    referrer.realm.string_id, invitee.email)
        activate_url = do_send_confirmation_email(invitee, referrer)

        # queue invitation reminder
        if settings.INVITATION_LINK_VALIDITY_DAYS >= 4:
            context = common_context(referrer)
            context.update({
                'activate_url': activate_url,
                'referrer_name': referrer.full_name,
                'referrer_email': referrer.delivery_email,
                'referrer_realm_name': referrer.realm.name,
            })
            send_future_email(
                "zerver/emails/invitation_reminder",
                referrer.realm,
                to_emails=[invitee.email],
                from_address=FromAddress.tokenized_no_reply_placeholder,
                language=referrer.realm.default_language,
                context=context,
                delay=datetime.timedelta(
                    days=settings.INVITATION_LINK_VALIDITY_DAYS - 2))
コード例 #4
0
ファイル: queue_processors.py プロジェクト: priyank-p/zulip
    def consume(self, data: Mapping[str, Any]) -> None:
        if "invite_expires_in_days" in data:
            invite_expires_in_minutes = data["invite_expires_in_days"] * 24 * 60
        elif "invite_expires_in_minutes" in data:
            invite_expires_in_minutes = data["invite_expires_in_minutes"]
        invitee = filter_to_valid_prereg_users(
            PreregistrationUser.objects.filter(id=data["prereg_id"]),
            invite_expires_in_minutes).first()
        if invitee is None:
            # The invitation could have been revoked
            return

        referrer = get_user_profile_by_id(data["referrer_id"])
        logger.info("Sending invitation for realm %s to %s",
                    referrer.realm.string_id, invitee.email)
        if "email_language" in data:
            email_language = data["email_language"]
        else:
            email_language = referrer.realm.default_language

        activate_url = do_send_confirmation_email(invitee, referrer,
                                                  email_language,
                                                  invite_expires_in_minutes)
        if invite_expires_in_minutes is None:
            # We do not queue reminder email for never expiring
            # invitations. This is probably a low importance bug; it
            # would likely be more natural to send a reminder after 7
            # days.
            return

        # queue invitation reminder
        if invite_expires_in_minutes >= 4 * 24 * 60:
            context = common_context(referrer)
            context.update(
                activate_url=activate_url,
                referrer_name=referrer.full_name,
                referrer_email=referrer.delivery_email,
                referrer_realm_name=referrer.realm.name,
            )
            send_future_email(
                "zerver/emails/invitation_reminder",
                referrer.realm,
                to_emails=[invitee.email],
                from_address=FromAddress.tokenized_no_reply_placeholder,
                language=email_language,
                context=context,
                delay=datetime.timedelta(minutes=invite_expires_in_minutes -
                                         (2 * 24 * 60)),
            )
コード例 #5
0
ファイル: invites.py プロジェクト: priyank-p/zulip
def get_valid_invite_confirmations_generated_by_user(
    user_profile: UserProfile, ) -> List[Confirmation]:
    prereg_user_ids = filter_to_valid_prereg_users(
        PreregistrationUser.objects.filter(
            referred_by=user_profile)).values_list("id", flat=True)
    confirmations = list(
        Confirmation.objects.filter(type=Confirmation.INVITATION,
                                    object_id__in=prereg_user_ids))

    multiuse_invite_ids = MultiuseInvite.objects.filter(
        referred_by=user_profile).values_list("id", flat=True)
    confirmations += list(
        Confirmation.objects.filter(
            type=Confirmation.MULTIUSE_INVITE,
            object_id__in=multiuse_invite_ids,
        ).filter(Q(expiry_date__gte=timezone_now()) | Q(expiry_date=None)))

    return confirmations
コード例 #6
0
def maybe_send_to_registration(
    request: HttpRequest,
    email: str,
    full_name: str = "",
    mobile_flow_otp: Optional[str] = None,
    desktop_flow_otp: Optional[str] = None,
    is_signup: bool = False,
    password_required: bool = True,
    multiuse_object_key: str = "",
    full_name_validated: bool = False,
) -> HttpResponse:
    """Given a successful authentication for an email address (i.e. we've
    confirmed the user controls the email address) that does not
    currently have a Zulip account in the target realm, send them to
    the registration flow or the "continue to registration" flow,
    depending on is_signup, whether the email address can join the
    organization (checked in HomepageForm), and similar details.
    """

    # In the desktop and mobile registration flows, the sign up
    # happens in the browser so the user can use their
    # already-logged-in social accounts.  Then at the end, with the
    # user account created, we pass the appropriate data to the app
    # via e.g. a `zulip://` redirect.  We store the OTP keys for the
    # mobile/desktop flow in the session with 1-hour expiry, because
    # we want this configuration of having a successful authentication
    # result in being logged into the app to persist if the user makes
    # mistakes while trying to authenticate (E.g. clicks the wrong
    # Google account, hits back, etc.) during a given browser session,
    # rather than just logging into the webapp in the target browser.
    #
    # We can't use our usual pre-account-creation state storage
    # approach of putting something in PreregistrationUser, because
    # that would apply to future registration attempts on other
    # devices, e.g. just creating an account on the web on their laptop.
    assert not (mobile_flow_otp and desktop_flow_otp)
    if mobile_flow_otp:
        set_expirable_session_var(
            request.session, "registration_mobile_flow_otp", mobile_flow_otp, expiry_seconds=3600
        )
    elif desktop_flow_otp:
        set_expirable_session_var(
            request.session, "registration_desktop_flow_otp", desktop_flow_otp, expiry_seconds=3600
        )

    if multiuse_object_key:
        from_multiuse_invite = True
        multiuse_obj = Confirmation.objects.get(confirmation_key=multiuse_object_key).content_object
        realm = multiuse_obj.realm
        invited_as = multiuse_obj.invited_as
    else:
        from_multiuse_invite = False
        multiuse_obj = None
        try:
            realm = get_realm(get_subdomain(request))
        except Realm.DoesNotExist:
            realm = None
        invited_as = PreregistrationUser.INVITE_AS["MEMBER"]

    form = HomepageForm({"email": email}, realm=realm, from_multiuse_invite=from_multiuse_invite)
    if form.is_valid():
        # If the email address is allowed to sign up for an account in
        # this organization, construct a PreregistrationUser and
        # Confirmation objects, and then send the user to account
        # creation or confirm-continue-registration depending on
        # is_signup.
        try:
            prereg_user = filter_to_valid_prereg_users(
                PreregistrationUser.objects.filter(email__iexact=email, realm=realm)
            ).latest("invited_at")

            # password_required and full_name data passed here as argument should take precedence
            # over the defaults with which the existing PreregistrationUser that we've just fetched
            # was created.
            prereg_user.password_required = password_required
            update_fields = ["password_required"]
            if full_name:
                prereg_user.full_name = full_name
                prereg_user.full_name_validated = full_name_validated
                update_fields.extend(["full_name", "full_name_validated"])
            prereg_user.save(update_fields=update_fields)
        except PreregistrationUser.DoesNotExist:
            prereg_user = create_preregistration_user(
                email,
                request,
                password_required=password_required,
                full_name=full_name,
                full_name_validated=full_name_validated,
            )

        if multiuse_obj is not None:
            request.session.modified = True
            streams_to_subscribe = list(multiuse_obj.streams.all())
            prereg_user.streams.set(streams_to_subscribe)
            prereg_user.invited_as = invited_as
            prereg_user.save()

        confirmation_link = create_confirmation_link(prereg_user, Confirmation.USER_REGISTRATION)
        if is_signup:
            return redirect(confirmation_link)

        context = {"email": email, "continue_link": confirmation_link, "full_name": full_name}
        return render(request, "zerver/confirm_continue_registration.html", context=context)

    # This email address it not allowed to join this organization, so
    # just send the user back to the registration page.
    url = reverse("register")
    context = login_context(request)
    extra_context: Mapping[str, Any] = {
        "form": form,
        "current_url": lambda: url,
        "from_multiuse_invite": from_multiuse_invite,
        "multiuse_object_key": multiuse_object_key,
        "mobile_flow_otp": mobile_flow_otp,
        "desktop_flow_otp": desktop_flow_otp,
    }
    context.update(extra_context)
    return render(request, "zerver/accounts_home.html", context=context)