Пример #1
0
 def test_deactivated_realm(self):
     # type: () -> None
     do_deactivate_realm(self.user_profile.realm)
     result = self.client_post("/api/v1/fetch_api_key",
                               dict(username=self.email,
                                    password=initial_password(self.email)))
     self.assert_json_error_contains(result, "Your realm has been deactivated", 403)
Пример #2
0
 def test_do_deactivate_realm_clears_scheduled_jobs(self) -> None:
     user = self.example_user('hamlet')
     send_future_email('zerver/emails/followup_day1', user.realm,
                       to_user_id=user.id, delay=datetime.timedelta(hours=1))
     self.assertEqual(ScheduledEmail.objects.count(), 1)
     do_deactivate_realm(user.realm)
     self.assertEqual(ScheduledEmail.objects.count(), 0)
Пример #3
0
    def test_send_deactivated_realm(self):
        """
        rest_dispatch rejects requests in a deactivated realm, both /json and api

        """
        realm = get_realm("zulip.com")
        do_deactivate_realm(get_realm("zulip.com"))

        result = self.client_post("/json/messages", {"type": "private",
                                                     "content": "Test message",
                                                     "client": "test suite",
                                                     "to": "*****@*****.**"})
        self.assert_json_error_contains(result, "Not logged in", status_code=401)

        # Even if a logged-in session was leaked, it still wouldn't work
        realm.deactivated = False
        realm.save()
        self.login("*****@*****.**")
        realm.deactivated = True
        realm.save()

        result = self.client_post("/json/messages", {"type": "private",
                                                     "content": "Test message",
                                                     "client": "test suite",
                                                     "to": "*****@*****.**"})
        self.assert_json_error_contains(result, "has been deactivated", status_code=400)

        result = self.client_post("/api/v1/messages", {"type": "private",
                                                       "content": "Test message",
                                                       "client": "test suite",
                                                       "to": "*****@*****.**"},
                                  **self.api_auth("*****@*****.**"))
        self.assert_json_error_contains(result, "has been deactivated", status_code=401)
Пример #4
0
    def test_login_deactivated_realm(self):
        """
        logging in fails in a deactivated realm

        """
        do_deactivate_realm(get_realm("zulip.com"))
        result = self.login_with_return("*****@*****.**")
        self.assert_in_response("has been deactivated", result)
Пример #5
0
 def handle(self, *args, **options):
     realm = get_realm(options["domain"])
     if realm is None:
         print("Could not find realm %s" % (options["domain"],))
         sys.exit(1)
     print("Deactivating", options["domain"])
     do_deactivate_realm(realm)
     print("Done!")
Пример #6
0
 def handle(self, *args, **options):
     # type: (*Any, **str) -> None
     realm = get_realm(options["string_id"])
     if realm is None:
         print("Could not find realm %s" % (options["string_id"],))
         sys.exit(1)
     print("Deactivating", options["string_id"])
     do_deactivate_realm(realm)
     print("Done!")
Пример #7
0
 def test_realm_reactivation_link(self) -> None:
     realm = get_realm('zulip')
     do_deactivate_realm(realm)
     self.assertTrue(realm.deactivated)
     confirmation_url = create_confirmation_link(realm, realm.host, Confirmation.REALM_REACTIVATION)
     response = self.client_get(confirmation_url)
     self.assert_in_success_response(['Your organization has been successfully reactivated'], response)
     realm = get_realm('zulip')
     self.assertFalse(realm.deactivated)
Пример #8
0
 def handle(self, *args, **options):
     # type: (*Any, **str) -> None
     realm = self.get_realm(options)
     if realm.deactivated:
         print("The realm", options["realm_id"], "is already deactivated.")
         exit(0)
     print("Deactivating", options["realm_id"])
     do_deactivate_realm(realm)
     print("Done!")
Пример #9
0
    def handle(self, *args: Any, **options: str) -> None:
        realm = self.get_realm(options)
        assert realm is not None  # Should be ensured by parser

        if realm.deactivated:
            print("The realm", options["realm_id"], "is already deactivated.")
            exit(0)
        print("Deactivating", options["realm_id"])
        do_deactivate_realm(realm)
        print("Done!")
Пример #10
0
    def test_do_deactivate_realm_on_deactived_realm(self) -> None:
        """Ensure early exit is working in realm deactivation"""
        realm = get_realm('zulip')
        self.assertFalse(realm.deactivated)

        do_deactivate_realm(realm)
        self.assertTrue(realm.deactivated)

        do_deactivate_realm(realm)
        self.assertTrue(realm.deactivated)
Пример #11
0
    def handle(self, *args, **options):
        # type: (*Any, **str) -> None
        realm = self.get_realm(options)
        assert realm is not None  # Should be ensured by parser

        if realm.deactivated:
            print("The realm", options["realm_id"], "is already deactivated.")
            exit(0)
        print("Deactivating", options["realm_id"])
        do_deactivate_realm(realm)
        print("Done!")
Пример #12
0
 def test_do_deactivate_realm_clears_user_realm_cache(self) -> None:
     """The main complicated thing about deactivating realm names is
     updating the cache, and we start by populating the cache for
     Hamlet, and we end by checking the cache to ensure that his
     realm appears to be deactivated.  You can make this test fail
     by disabling cache.flush_realm()."""
     self.example_user('hamlet')
     realm = get_realm('zulip')
     do_deactivate_realm(realm)
     user = self.example_user('hamlet')
     self.assertTrue(user.realm.deactivated)
Пример #13
0
 def test_realm_reactivation_link(self) -> None:
     realm = get_realm('zulip')
     do_deactivate_realm(realm)
     self.assertTrue(realm.deactivated)
     confirmation_url = create_confirmation_link(
         realm, Confirmation.REALM_REACTIVATION)
     response = self.client_get(confirmation_url)
     self.assert_in_success_response(
         ['Your organization has been successfully reactivated'], response)
     realm = get_realm('zulip')
     self.assertFalse(realm.deactivated)
Пример #14
0
 def test_do_deactivate_realm_clears_scheduled_jobs(self) -> None:
     user = self.example_user("hamlet")
     send_future_email(
         "zerver/emails/followup_day1",
         user.realm,
         to_user_ids=[user.id],
         delay=datetime.timedelta(hours=1),
     )
     self.assertEqual(ScheduledEmail.objects.count(), 1)
     do_deactivate_realm(user.realm, acting_user=None)
     self.assertEqual(ScheduledEmail.objects.count(), 0)
Пример #15
0
 def test_do_deactivate_realm_clears_user_realm_cache(self) -> None:
     """The main complicated thing about deactivating realm names is
     updating the cache, and we start by populating the cache for
     Hamlet, and we end by checking the cache to ensure that his
     realm appears to be deactivated.  You can make this test fail
     by disabling cache.flush_realm()."""
     self.example_user('hamlet')
     realm = get_realm('zulip')
     do_deactivate_realm(realm)
     user = self.example_user('hamlet')
     self.assertTrue(user.realm.deactivated)
Пример #16
0
 def test_do_deactivate_realm_clears_user_realm_cache(self) -> None:
     """The main complicated thing about deactivating realm names is
     updating the cache, and we start by populating the cache for
     Hamlet, and we end by checking the cache to ensure that his
     realm appears to be deactivated.  You can make this test fail
     by disabling cache.flush_realm()."""
     hamlet_id = self.example_user("hamlet").id
     get_user_profile_by_id(hamlet_id)
     realm = get_realm("zulip")
     do_deactivate_realm(realm, acting_user=None)
     user = get_user_profile_by_id(hamlet_id)
     self.assertTrue(user.realm.deactivated)
Пример #17
0
    def test_realm_activation(self) -> None:
        realm = get_realm('zulip')
        do_deactivate_realm(realm)
        log_entry = RealmAuditLog.objects.get(
            realm=realm, event_type=RealmAuditLog.REALM_DEACTIVATED)
        extra_data = ujson.loads(log_entry.extra_data)
        self.check_role_count_schema(extra_data[RealmAuditLog.ROLE_COUNT])

        do_reactivate_realm(realm)
        log_entry = RealmAuditLog.objects.get(
            realm=realm, event_type=RealmAuditLog.REALM_REACTIVATED)
        extra_data = ujson.loads(log_entry.extra_data)
        self.check_role_count_schema(extra_data[RealmAuditLog.ROLE_COUNT])
Пример #18
0
    def test_webhook_deactivated_realm(self):
        """
        Using a webhook while in a deactivated realm fails

        """
        do_deactivate_realm(get_realm("zulip.com"))
        email = "*****@*****.**"
        api_key = self.get_api_key(email)
        url = "/api/v1/external/jira?api_key=%s&stream=jira_custom" % (api_key,)
        data = self.fixture_data('jira', "created")
        result = self.client_post(url, data,
                                  content_type="application/json")
        self.assert_json_error_contains(result, "has been deactivated", status_code=400)
Пример #19
0
    def test_webhook_deactivated_realm(self):
        # type: () -> None
        """
        Using a webhook while in a deactivated realm fails

        """
        do_deactivate_realm(get_realm("zulip"))
        user_profile = self.example_user("hamlet")
        url = "/api/v1/external/jira?api_key=%s&stream=jira_custom" % (
            user_profile.api_key,)
        data = self.fixture_data('jira', "created_v2")
        result = self.client_post(url, data,
                                  content_type="application/json")
        self.assert_json_error_contains(result, "has been deactivated", status_code=400)
Пример #20
0
    def test_do_set_deactivated_redirect_on_deactivated_realm(self) -> None:
        """Ensure that the redirect url is working when deactivating realm"""
        realm = get_realm("zulip")

        redirect_url = "new_server.zulip.com"
        do_deactivate_realm(realm, acting_user=None)
        self.assertTrue(realm.deactivated)
        do_add_deactivated_redirect(realm, redirect_url)
        self.assertEqual(realm.deactivated_redirect, redirect_url)

        new_redirect_url = "test.zulip.com"
        do_add_deactivated_redirect(realm, new_redirect_url)
        self.assertEqual(realm.deactivated_redirect, new_redirect_url)
        self.assertNotEqual(realm.deactivated_redirect, redirect_url)
Пример #21
0
    def test_webhook_deactivated_realm(self):
        # type: () -> None
        """
        Using a webhook while in a deactivated realm fails

        """
        do_deactivate_realm(get_realm("zulip"))
        user_profile = self.example_user("hamlet")
        url = "/api/v1/external/jira?api_key=%s&stream=jira_custom" % (
            user_profile.api_key,)
        data = self.fixture_data('jira', "created_v2")
        result = self.client_post(url, data,
                                  content_type="application/json")
        self.assert_json_error_contains(result, "has been deactivated", status_code=400)
Пример #22
0
    def test_realm_activation(self) -> None:
        realm = get_realm("zulip")
        user = self.example_user("desdemona")
        do_deactivate_realm(realm, acting_user=user)
        log_entry = RealmAuditLog.objects.get(
            realm=realm, event_type=RealmAuditLog.REALM_DEACTIVATED, acting_user=user
        )
        extra_data = orjson.loads(log_entry.extra_data)
        self.check_role_count_schema(extra_data[RealmAuditLog.ROLE_COUNT])

        do_reactivate_realm(realm)
        log_entry = RealmAuditLog.objects.get(
            realm=realm, event_type=RealmAuditLog.REALM_REACTIVATED
        )
        extra_data = orjson.loads(log_entry.extra_data)
        self.check_role_count_schema(extra_data[RealmAuditLog.ROLE_COUNT])
Пример #23
0
    def handle(self, *args: Any, **options: str) -> None:
        realm = self.get_realm(options)

        assert realm is not None  # Should be ensured by parser

        if options['redirect_url']:
            print("Setting the redirect URL to", options['redirect_url'])
            do_add_deactivated_redirect(realm, options['redirect_url'])

        if realm.deactivated:
            print("The realm", options['realm_id'], "is already deactivated.")
            exit(0)

        print("Deactivating", options["realm_id"])
        do_deactivate_realm(realm)
        print("Done!")
Пример #24
0
    def verify_backend(self, backend, good_args=None,
                       good_kwargs=None, bad_kwargs=None,
                       email_to_username=None):
        # type: (Any, List[Any], Dict[str, Any], Dict[str, Any], Callable[[text_type], text_type]) -> None
        if good_args is None:
            good_args = []
        if good_kwargs is None:
            good_kwargs = {}
        email = u"*****@*****.**"
        user_profile = get_user_profile_by_email(email)

        username = email
        if email_to_username is not None:
            username = email_to_username(email)

        # If bad_kwargs was specified, verify auth fails in that case
        if bad_kwargs is not None:
            self.assertIsNone(backend.authenticate(username, **bad_kwargs))

        # Verify auth works
        result = backend.authenticate(username, *good_args, **good_kwargs)
        self.assertEqual(user_profile, result)

        # Verify auth fails with a deactivated user
        do_deactivate_user(user_profile)
        self.assertIsNone(backend.authenticate(username, *good_args, **good_kwargs))

        # Reactivate the user and verify auth works again
        do_reactivate_user(user_profile)
        result = backend.authenticate(username, *good_args, **good_kwargs)
        self.assertEqual(user_profile, result)

        # Verify auth fails with a deactivated realm
        do_deactivate_realm(user_profile.realm)
        self.assertIsNone(backend.authenticate(username, *good_args, **good_kwargs))

        # Verify auth works again after reactivating the realm
        do_reactivate_realm(user_profile.realm)
        result = backend.authenticate(username, *good_args, **good_kwargs)
        self.assertEqual(user_profile, result)
Пример #25
0
def deactivate_realm(request: HttpRequest, user: UserProfile) -> HttpResponse:
    realm = user.realm
    do_deactivate_realm(realm, acting_user=user)
    return json_success()
Пример #26
0
 def handle(self, *args, **options):
     print "Deactivating", options["domain"]
     do_deactivate_realm(get_realm(options["domain"]))
     print "Done!"
Пример #27
0
 def handle(self, *args, **options):
     print "Deactivating", options["domain"]
     do_deactivate_realm(get_realm(options["domain"]))
     print "Done!"
Пример #28
0
def deactivate_realm(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
    realm = user_profile.realm
    do_deactivate_realm(realm)
    return json_success()
Пример #29
0
    def handle(self, *args: Any, **options: Any) -> None:
        realm = self.get_realm(options)
        assert realm is not None  # Should be ensured by parser

        output_dir = options["output_dir"]
        public_only = options["public_only"]
        consent_message_id = options["consent_message_id"]

        print(f"\033[94mExporting realm\033[0m: {realm.string_id}")

        num_threads = int(options["threads"])
        if num_threads < 1:
            raise CommandError("You must have at least one thread.")

        if public_only and consent_message_id is not None:
            raise CommandError(
                "Please pass either --public-only or --consent-message-id")

        if options["deactivate_realm"] and realm.deactivated:
            raise CommandError(
                f"The realm {realm.string_id} is already deactivated.  Aborting..."
            )

        if consent_message_id is not None:
            try:
                message = Message.objects.get(id=consent_message_id)
            except Message.DoesNotExist:
                raise CommandError(
                    "Message with given ID does not exist. Aborting...")

            if message.last_edit_time is not None:
                raise CommandError("Message was edited. Aborting...")

            # Since the message might have been sent by
            # Notification Bot, we can't trivially check the realm of
            # the message through message.sender.realm.  So instead we
            # check the realm of the people who reacted to the message
            # (who must all be in the message's realm).
            reactions = Reaction.objects.filter(
                message=message,
                # outbox = 1f4e4
                emoji_code="1f4e4",
                reaction_type="unicode_emoji",
            )
            for reaction in reactions:
                if reaction.user_profile.realm != realm:
                    raise CommandError(
                        "Users from a different realm reacted to message. Aborting..."
                    )

            print(f"\n\033[94mMessage content:\033[0m\n{message.content}\n")

            user_count = (
                UserProfile.objects.filter(
                    realm_id=realm.id,
                    is_active=True,
                    is_bot=False,
                ).exclude(
                    # We exclude guests, because they're not a priority for
                    # looking at whether most users are being exported.
                    role=UserProfile.ROLE_GUEST, ).count())
            print(
                f"\033[94mNumber of users that reacted outbox:\033[0m {len(reactions)} / {user_count} total non-guest users\n"
            )

            proceed = input("Continue? [y/N] ")
            if proceed.lower() not in ("y", "yes"):
                raise CommandError("Aborting!")

        if output_dir is None:
            output_dir = tempfile.mkdtemp(prefix="zulip-export-")
        else:
            output_dir = os.path.realpath(os.path.expanduser(output_dir))
            if os.path.exists(output_dir):
                if os.listdir(output_dir):
                    raise CommandError(
                        f"Refusing to overwrite nonempty directory: {output_dir}. Aborting...",
                    )
            else:
                os.makedirs(output_dir)

        tarball_path = output_dir.rstrip("/") + ".tar.gz"
        try:
            with open(tarball_path, "x"):
                pass
        except FileExistsError:
            raise CommandError(
                f"Refusing to overwrite existing tarball: {tarball_path}. Aborting..."
            )

        if options["deactivate_realm"]:
            print(f"\033[94mDeactivating realm\033[0m: {realm.string_id}")
            do_deactivate_realm(realm, acting_user=None)

        def percent_callback(bytes_transferred: Any) -> None:
            print(end=".", flush=True)

        # Allows us to trigger exports separately from command line argument parsing
        export_realm_wrapper(
            realm=realm,
            output_dir=output_dir,
            threads=num_threads,
            upload=options["upload"],
            public_only=public_only,
            percent_callback=percent_callback,
            consent_message_id=consent_message_id,
        )
Пример #30
0
    def handle(self, *args: Any, **options: Any) -> None:
        realm = self.get_realm(options)
        assert realm is not None  # Should be ensured by parser

        output_dir = options["output_dir"]
        public_only = options["public_only"]
        consent_message_id = options["consent_message_id"]

        print(f"\033[94mExporting realm\033[0m: {realm.string_id}")

        num_threads = int(options['threads'])
        if num_threads < 1:
            raise CommandError('You must have at least one thread.')

        if public_only and consent_message_id is not None:
            raise CommandError('Please pass either --public-only or --consent-message-id')

        if options["deactivate_realm"] and realm.deactivated:
            raise CommandError(f"The realm {realm.string_id} is already deactivated.  Aborting...")

        if consent_message_id is not None:
            try:
                message = Message.objects.get(id=consent_message_id)
            except Message.DoesNotExist:
                raise CommandError("Message with given ID does not exist. Aborting...")

            if message.last_edit_time is not None:
                raise CommandError("Message was edited. Aborting...")

            # Since the message might have been sent by
            # Notification Bot, we can't trivially check the realm of
            # the message through message.sender.realm.  So instead we
            # check the realm of the people who reacted to the message
            # (who must all be in the message's realm).
            reactions = Reaction.objects.filter(message=message,
                                                # outbox = 1f4e4
                                                emoji_code="1f4e4",
                                                reaction_type="unicode_emoji")
            for reaction in reactions:
                if reaction.user_profile.realm != realm:
                    raise CommandError("Users from a different realm reacted to message. Aborting...")

            print(f"\n\033[94mMessage content:\033[0m\n{message.content}\n")

            user_count = UserProfile.objects.filter(realm_id=realm.id).count()
            print(f"\033[94mNumber of users that reacted outbox:\033[0m {len(reactions)} / {user_count} total users\n")

            proceed = input("Continue? [y/N] ")
            if proceed.lower() not in ('y', 'yes'):
                raise CommandError("Aborting!")

        if output_dir is None:
            output_dir = tempfile.mkdtemp(prefix="zulip-export-")
        else:
            output_dir = os.path.realpath(os.path.expanduser(output_dir))
            if os.path.exists(output_dir):
                if os.listdir(output_dir):
                    raise CommandError(
                        f"Refusing to overwrite nonempty directory: {output_dir}. Aborting...",
                    )
            else:
                os.makedirs(output_dir)

        tarball_path = output_dir.rstrip("/") + ".tar.gz"
        try:
            os.close(os.open(tarball_path, os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0o666))
        except FileExistsError:
            raise CommandError(f"Refusing to overwrite existing tarball: {tarball_path}. Aborting...")

        if options["deactivate_realm"]:
            print(f"\033[94mDeactivating realm\033[0m: {realm.string_id}")
            do_deactivate_realm(realm)

        def percent_callback(bytes_transferred: Any) -> None:
            sys.stdout.write('.')
            sys.stdout.flush()

        # Allows us to trigger exports separately from command line argument parsing
        export_realm_wrapper(realm=realm, output_dir=output_dir,
                             threads=num_threads, upload=options['upload'],
                             public_only=public_only,
                             delete_after_upload=options["delete_after_upload"],
                             percent_callback=percent_callback,
                             consent_message_id=consent_message_id)
Пример #31
0
def deactivate_realm(request: HttpRequest,
                     user_profile: UserProfile) -> HttpResponse:
    realm = user_profile.realm
    do_deactivate_realm(realm)
    return json_success()
Пример #32
0
def support(
    request: HttpRequest,
    realm_id: Optional[int] = REQ(default=None, converter=to_non_negative_int),
    plan_type: Optional[int] = REQ(default=None,
                                   converter=to_non_negative_int),
    discount: Optional[Decimal] = REQ(default=None, converter=to_decimal),
    new_subdomain: Optional[str] = REQ(default=None),
    status: Optional[str] = REQ(
        default=None, str_validator=check_string_in(VALID_STATUS_VALUES)),
    billing_method: Optional[str] = REQ(
        default=None, str_validator=check_string_in(VALID_BILLING_METHODS)),
    sponsorship_pending: Optional[bool] = REQ(default=None,
                                              json_validator=check_bool),
    approve_sponsorship: Optional[bool] = REQ(default=None,
                                              json_validator=check_bool),
    downgrade_method: Optional[str] = REQ(
        default=None, str_validator=check_string_in(VALID_DOWNGRADE_METHODS)),
    scrub_realm: Optional[bool] = REQ(default=None, json_validator=check_bool),
    query: Optional[str] = REQ("q", default=None),
    org_type: Optional[int] = REQ(default=None, converter=to_non_negative_int),
) -> HttpResponse:
    context: Dict[str, Any] = {}

    if "success_message" in request.session:
        context["success_message"] = request.session["success_message"]
        del request.session["success_message"]

    if settings.BILLING_ENABLED and request.method == "POST":
        # We check that request.POST only has two keys in it: The
        # realm_id and a field to change.
        keys = set(request.POST.keys())
        if "csrfmiddlewaretoken" in keys:
            keys.remove("csrfmiddlewaretoken")
        if len(keys) != 2:
            raise JsonableError(_("Invalid parameters"))

        realm = Realm.objects.get(id=realm_id)

        acting_user = request.user
        assert isinstance(acting_user, UserProfile)
        if plan_type is not None:
            current_plan_type = realm.plan_type
            do_change_plan_type(realm, plan_type, acting_user=acting_user)
            msg = f"Plan type of {realm.string_id} changed from {get_plan_name(current_plan_type)} to {get_plan_name(plan_type)} "
            context["success_message"] = msg
        elif org_type is not None:
            current_realm_type = realm.org_type
            do_change_realm_org_type(realm, org_type, acting_user=acting_user)
            msg = f"Org type of {realm.string_id} changed from {get_org_type_display_name(current_realm_type)} to {get_org_type_display_name(org_type)} "
            context["success_message"] = msg
        elif discount is not None:
            current_discount = get_discount_for_realm(realm) or 0
            attach_discount_to_realm(realm, discount, acting_user=acting_user)
            context[
                "success_message"] = f"Discount of {realm.string_id} changed to {discount}% from {current_discount}%."
        elif new_subdomain is not None:
            old_subdomain = realm.string_id
            try:
                check_subdomain_available(new_subdomain)
            except ValidationError as error:
                context["error_message"] = error.message
            else:
                do_change_realm_subdomain(realm,
                                          new_subdomain,
                                          acting_user=acting_user)
                request.session[
                    "success_message"] = f"Subdomain changed from {old_subdomain} to {new_subdomain}"
                return HttpResponseRedirect(
                    reverse("support") + "?" + urlencode({"q": new_subdomain}))
        elif status is not None:
            if status == "active":
                do_send_realm_reactivation_email(realm,
                                                 acting_user=acting_user)
                context[
                    "success_message"] = f"Realm reactivation email sent to admins of {realm.string_id}."
            elif status == "deactivated":
                do_deactivate_realm(realm, acting_user=acting_user)
                context["success_message"] = f"{realm.string_id} deactivated."
        elif billing_method is not None:
            if billing_method == "send_invoice":
                update_billing_method_of_current_plan(
                    realm, charge_automatically=False, acting_user=acting_user)
                context[
                    "success_message"] = f"Billing method of {realm.string_id} updated to pay by invoice."
            elif billing_method == "charge_automatically":
                update_billing_method_of_current_plan(
                    realm, charge_automatically=True, acting_user=acting_user)
                context[
                    "success_message"] = f"Billing method of {realm.string_id} updated to charge automatically."
        elif sponsorship_pending is not None:
            if sponsorship_pending:
                update_sponsorship_status(realm, True, acting_user=acting_user)
                context[
                    "success_message"] = f"{realm.string_id} marked as pending sponsorship."
            else:
                update_sponsorship_status(realm,
                                          False,
                                          acting_user=acting_user)
                context[
                    "success_message"] = f"{realm.string_id} is no longer pending sponsorship."
        elif approve_sponsorship:
            do_approve_sponsorship(realm, acting_user=acting_user)
            context[
                "success_message"] = f"Sponsorship approved for {realm.string_id}"
        elif downgrade_method is not None:
            if downgrade_method == "downgrade_at_billing_cycle_end":
                downgrade_at_the_end_of_billing_cycle(realm)
                context[
                    "success_message"] = f"{realm.string_id} marked for downgrade at the end of billing cycle"
            elif downgrade_method == "downgrade_now_without_additional_licenses":
                downgrade_now_without_creating_additional_invoices(realm)
                context[
                    "success_message"] = f"{realm.string_id} downgraded without creating additional invoices"
            elif downgrade_method == "downgrade_now_void_open_invoices":
                downgrade_now_without_creating_additional_invoices(realm)
                voided_invoices_count = void_all_open_invoices(realm)
                context[
                    "success_message"] = f"{realm.string_id} downgraded and voided {voided_invoices_count} open invoices"
        elif scrub_realm:
            do_scrub_realm(realm, acting_user=acting_user)
            context["success_message"] = f"{realm.string_id} scrubbed."

    if query:
        key_words = get_invitee_emails_set(query)

        users = set(UserProfile.objects.filter(delivery_email__in=key_words))
        realms = set(Realm.objects.filter(string_id__in=key_words))

        for key_word in key_words:
            try:
                URLValidator()(key_word)
                parse_result = urllib.parse.urlparse(key_word)
                hostname = parse_result.hostname
                assert hostname is not None
                if parse_result.port:
                    hostname = f"{hostname}:{parse_result.port}"
                subdomain = get_subdomain_from_hostname(hostname)
                try:
                    realms.add(get_realm(subdomain))
                except Realm.DoesNotExist:
                    pass
            except ValidationError:
                users.update(
                    UserProfile.objects.filter(full_name__iexact=key_word))

        for realm in realms:
            realm.customer = get_customer_by_realm(realm)

            current_plan = get_current_plan_by_realm(realm)
            if current_plan is not None:
                new_plan, last_ledger_entry = make_end_of_cycle_updates_if_needed(
                    current_plan, timezone_now())
                if last_ledger_entry is not None:
                    if new_plan is not None:
                        realm.current_plan = new_plan
                    else:
                        realm.current_plan = current_plan
                    realm.current_plan.licenses = last_ledger_entry.licenses
                    realm.current_plan.licenses_used = get_latest_seat_count(
                        realm)

        # full_names can have , in them
        users.update(UserProfile.objects.filter(full_name__iexact=query))

        context["users"] = users
        context["realms"] = realms

        confirmations: List[Dict[str, Any]] = []

        preregistration_users = PreregistrationUser.objects.filter(
            email__in=key_words)
        confirmations += get_confirmations(
            [
                Confirmation.USER_REGISTRATION, Confirmation.INVITATION,
                Confirmation.REALM_CREATION
            ],
            preregistration_users,
            hostname=request.get_host(),
        )

        multiuse_invites = MultiuseInvite.objects.filter(realm__in=realms)
        confirmations += get_confirmations([Confirmation.MULTIUSE_INVITE],
                                           multiuse_invites)

        confirmations += get_confirmations([Confirmation.REALM_REACTIVATION],
                                           [realm.id for realm in realms])

        context["confirmations"] = confirmations

    def get_realm_owner_emails_as_string(realm: Realm) -> str:
        return ", ".join(realm.get_human_owner_users().order_by(
            "delivery_email").values_list("delivery_email", flat=True))

    def get_realm_admin_emails_as_string(realm: Realm) -> str:
        return ", ".join(
            realm.get_human_admin_users(include_realm_owners=False).order_by(
                "delivery_email").values_list("delivery_email", flat=True))

    context[
        "get_realm_owner_emails_as_string"] = get_realm_owner_emails_as_string
    context[
        "get_realm_admin_emails_as_string"] = get_realm_admin_emails_as_string
    context["get_discount_for_realm"] = get_discount_for_realm
    context["get_org_type_display_name"] = get_org_type_display_name
    context["realm_icon_url"] = realm_icon_url
    context["Confirmation"] = Confirmation
    context["sorted_realm_types"] = sorted(Realm.ORG_TYPES.values(),
                                           key=lambda d: d["display_order"])

    return render(request, "analytics/support.html", context=context)