示例#1
0
    def handle(self, *args, **options):
        # type: (*Any, **Any) -> None
        realm = self.get_realm(options)
        user_profile = self.get_user(options['email'], realm)

        print("Deactivating %s (%s) - %s" % (user_profile.full_name,
                                             user_profile.email,
                                             user_profile.realm.string_id))
        print("%s has the following active sessions:" % (user_profile.email,))
        for session in user_sessions(user_profile):
            print(session.expire_date, session.get_decoded())
        print("")
        print("%s has %s active bots that will also be deactivated." % (
            user_profile.email,
            UserProfile.objects.filter(
                is_bot=True, is_active=True, bot_owner=user_profile
            ).count()
        ))

        if not options["for_real"]:
            print("This was a dry run. Pass -f to actually deactivate.")
            exit(1)

        do_deactivate_user(user_profile)
        print("Sessions deleted, user deactivated.")
示例#2
0
 def test_clear_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_user(user)
     self.assertEqual(ScheduledEmail.objects.count(), 0)
示例#3
0
    def test_access_user_by_id(self) -> None:
        iago = self.example_user("iago")

        # Must be a valid user ID in the realm
        with self.assertRaises(JsonableError):
            access_user_by_id(iago, 1234)
        with self.assertRaises(JsonableError):
            access_user_by_id(iago, self.mit_user("sipbtest").id)

        # Can only access bot users if allow_deactivated is passed
        bot = self.example_user("welcome_bot")
        access_user_by_id(iago, bot.id, allow_bots=True)
        with self.assertRaises(JsonableError):
            access_user_by_id(iago, bot.id)

        # Can only access deactivated users if allow_deactivated is passed
        hamlet = self.example_user("hamlet")
        do_deactivate_user(hamlet)
        with self.assertRaises(JsonableError):
            access_user_by_id(iago, hamlet.id)
        access_user_by_id(iago, hamlet.id, allow_deactivated=True)

        # Non-admin user can't admin another user
        with self.assertRaises(JsonableError):
            access_user_by_id(self.example_user("cordelia"),
                              self.example_user("aaron").id)
示例#4
0
    def test_access_user_by_id(self) -> None:
        iago = self.example_user("iago")

        # Must be a valid user ID in the realm
        with self.assertRaises(JsonableError):
            access_user_by_id(iago, 1234)
        with self.assertRaises(JsonableError):
            access_user_by_id(iago, self.mit_user("sipbtest").id)

        # Can only access bot users if allow_deactivated is passed
        bot = self.example_user("welcome_bot")
        access_user_by_id(iago, bot.id, allow_bots=True)
        with self.assertRaises(JsonableError):
            access_user_by_id(iago, bot.id)

        # Can only access deactivated users if allow_deactivated is passed
        hamlet = self.example_user("hamlet")
        do_deactivate_user(hamlet)
        with self.assertRaises(JsonableError):
            access_user_by_id(iago, hamlet.id)
        access_user_by_id(iago, hamlet.id, allow_deactivated=True)

        # Non-admin user can't admin another user
        with self.assertRaises(JsonableError):
            access_user_by_id(self.example_user("cordelia"), self.example_user("aaron").id)
示例#5
0
 def test_user_activation(self) -> None:
     realm = get_realm('zulip')
     now = timezone_now()
     user = do_create_user('email', 'password', realm, 'full_name',
                           'short_name')
     do_deactivate_user(user)
     do_activate_user(user)
     do_deactivate_user(user)
     do_reactivate_user(user)
     self.assertEqual(
         RealmAuditLog.objects.filter(event_time__gte=now).count(), 5)
     event_types = list(
         RealmAuditLog.objects.filter(
             realm=realm,
             acting_user=None,
             modified_user=user,
             modified_stream=None,
             event_time__gte=now,
             event_time__lte=now +
             timedelta(minutes=60)).order_by('event_time').values_list(
                 'event_type', flat=True))
     self.assertEqual(event_types, [
         RealmAuditLog.USER_CREATED, RealmAuditLog.USER_DEACTIVATED,
         RealmAuditLog.USER_ACTIVATED, RealmAuditLog.USER_DEACTIVATED,
         RealmAuditLog.USER_REACTIVATED
     ])
示例#6
0
 def test_inactive_user(self):
     # type: () -> None
     do_deactivate_user(self.user_profile)
     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 account has been disabled", 403)
示例#7
0
def deactivate_user_own_backend(request, user_profile):
    # type: (HttpRequest, UserProfile) -> HttpResponse

    if user_profile.is_realm_admin and check_last_admin(user_profile):
        return json_error(_('Cannot deactivate the only organization administrator'))
    do_deactivate_user(user_profile, acting_user=user_profile)
    return json_success()
示例#8
0
def _deactivate_user_profile_backend(request, user_profile, target):
    # type: (HttpRequest, UserProfile, UserProfile) -> HttpResponse
    if not user_profile.can_admin_user(target):
        return json_error(_('Insufficient permission'))

    do_deactivate_user(target, acting_user=user_profile)
    return json_success()
示例#9
0
 def get_or_build_user(self, username: str,
                       ldap_user: _LDAPUser) -> Tuple[UserProfile, bool]:
     """This is used only in non-authentication contexts such as:
          ./manage.py sync_ldap_user_data
        In authentication contexts, this is overriden in ZulipLDAPAuthBackend.
     """
     (user, built) = super().get_or_build_user(username, ldap_user)
     self.sync_avatar_from_ldap(user, ldap_user)
     self.sync_full_name_from_ldap(user, ldap_user)
     self.sync_custom_profile_fields_from_ldap(user, ldap_user)
     if 'userAccountControl' in settings.AUTH_LDAP_USER_ATTR_MAP:
         user_disabled_in_ldap = self.is_account_control_disabled_user(
             ldap_user)
         if user_disabled_in_ldap and user.is_active:
             logging.info(
                 "Deactivating user %s because they are disabled in LDAP." %
                 (user.email, ))
             do_deactivate_user(user)
             return (user, built)
         if not user_disabled_in_ldap and not user.is_active:
             logging.info(
                 "Reactivating user %s because they are not disabled in LDAP."
                 % (user.email, ))
             do_reactivate_user(user)
     return (user, built)
示例#10
0
 def test_clear_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_user(user)
     self.assertEqual(ScheduledEmail.objects.count(), 0)
示例#11
0
 def test_active_users_log_by_is_bot(self):
     # type: () -> None
     property = 'active_users_log:is_bot:day'
     user = do_create_user('email', 'password', self.default_realm,
                           'full_name', 'short_name')
     self.assertEqual(
         1,
         RealmCount.objects.filter(property=property,
                                   subgroup=False).aggregate(
                                       Sum('value'))['value__sum'])
     do_deactivate_user(user)
     self.assertEqual(
         0,
         RealmCount.objects.filter(property=property,
                                   subgroup=False).aggregate(
                                       Sum('value'))['value__sum'])
     do_activate_user(user)
     self.assertEqual(
         1,
         RealmCount.objects.filter(property=property,
                                   subgroup=False).aggregate(
                                       Sum('value'))['value__sum'])
     do_deactivate_user(user)
     self.assertEqual(
         0,
         RealmCount.objects.filter(property=property,
                                   subgroup=False).aggregate(
                                       Sum('value'))['value__sum'])
     do_reactivate_user(user)
     self.assertEqual(
         1,
         RealmCount.objects.filter(property=property,
                                   subgroup=False).aggregate(
                                       Sum('value'))['value__sum'])
示例#12
0
 def test_basics(self):
     # type: () -> None
     user = self.example_user('hamlet')
     do_deactivate_user(user)
     self.assertFalse(user.is_active)
     do_reactivate_user(user)
     self.assertTrue(user.is_active)
示例#13
0
    def handle(self, *args: Any, **options: Any) -> None:
        realm = self.get_realm(options)
        user_profile = self.get_user(options['email'], realm)

        print(
            f"Deactivating {user_profile.full_name} ({user_profile.delivery_email}) - {user_profile.realm.string_id}"
        )
        print(
            f"{user_profile.delivery_email} has the following active sessions:"
        )
        for session in user_sessions(user_profile):
            print(session.expire_date, session.get_decoded())
        print("")
        print("{} has {} active bots that will also be deactivated.".format(
            user_profile.delivery_email,
            UserProfile.objects.filter(
                is_bot=True,
                is_active=True,
                bot_owner=user_profile,
            ).count(),
        ))

        if not options["for_real"]:
            raise CommandError(
                "This was a dry run. Pass -f to actually deactivate.")

        do_deactivate_user(user_profile)
        print("Sessions deleted, user deactivated.")
示例#14
0
文件: users.py 项目: dawran6/zulip
def deactivate_user_own_backend(request, user_profile):
    # type: (HttpRequest, UserProfile) -> HttpResponse

    if user_profile.is_realm_admin and check_last_admin(user_profile):
        return json_error(_('Cannot deactivate the only organization administrator'))
    do_deactivate_user(user_profile)
    return json_success()
示例#15
0
文件: users.py 项目: dawran6/zulip
def _deactivate_user_profile_backend(request, user_profile, target):
    # type: (HttpRequest, UserProfile, UserProfile) -> HttpResponse
    if not user_profile.can_admin_user(target):
        return json_error(_('Insufficient permission'))

    do_deactivate_user(target)
    return json_success()
示例#16
0
    def test_change_email_deactivated_user_realm(self) -> None:
        data = {"email": "*****@*****.**"}
        user_profile = self.example_user("hamlet")
        self.login_user(user_profile)
        url = "/json/settings"
        self.assert_length(mail.outbox, 0)
        result = self.client_patch(url, data)
        self.assert_length(mail.outbox, 1)
        self.assert_json_success(result)
        email_message = mail.outbox[0]
        self.assertEqual(
            email_message.subject,
            "Verify your new email address",
        )
        body = email_message.body
        self.assertIn("We received a request to change the email", body)

        activation_url = [s for s in body.split("\n") if s][2]

        do_deactivate_user(user_profile, acting_user=None)
        response = self.client_get(activation_url)
        self.assertEqual(response.status_code, 401)

        do_deactivate_realm(user_profile.realm, acting_user=None)

        response = self.client_get(activation_url)
        self.assertEqual(response.status_code, 302)
        self.assertTrue(response["Location"].endswith("/accounts/deactivated/"))
示例#17
0
    def test_send_deactivated_user(self):
        """
        rest_dispatch rejects requests from deactivated users, both /json and api

        """
        email = "*****@*****.**"
        user_profile = get_user_profile_by_email(email)
        self.login(email)
        do_deactivate_user(user_profile)

        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
        do_reactivate_user(user_profile)
        self.login(email)
        user_profile.is_active = False
        user_profile.save()

        result = self.client_post("/json/messages", {"type": "private",
                                                     "content": "Test message",
                                                     "client": "test suite",
                                                     "to": "*****@*****.**"})
        self.assert_json_error_contains(result, "Account not active", 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, "Account not active", status_code=401)
示例#18
0
文件: backends.py 项目: vedhant/zulip
def sync_user_from_ldap(user_profile: UserProfile) -> bool:
    backend = ZulipLDAPUserPopulator()
    updated_user = backend.populate_user(backend.django_to_ldap_username(user_profile.email))
    if not updated_user:
        if settings.LDAP_DEACTIVATE_NON_MATCHING_USERS:
            do_deactivate_user(user_profile)
        return False
    return True
示例#19
0
文件: users.py 项目: BakerWang/zulip
def deactivate_user_own_backend(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
    if UserProfile.objects.filter(realm=user_profile.realm, is_active=True).count() == 1:
        raise CannotDeactivateLastUserError(is_last_admin=False)
    if user_profile.is_realm_admin and check_last_admin(user_profile):
        raise CannotDeactivateLastUserError(is_last_admin=True)

    do_deactivate_user(user_profile, acting_user=user_profile)
    return json_success()
示例#20
0
文件: users.py 项目: Jianchun1/zulip
def deactivate_user_own_backend(request, user_profile):
    # type: (HttpRequest, UserProfile) -> HttpResponse
    admins = set(user_profile.realm.get_admin_users())

    if user_profile.is_realm_admin and len(admins) == 1:
        return json_error(_('Cannot deactivate the only admin'))
    do_deactivate_user(user_profile)
    return json_success()
示例#21
0
文件: users.py 项目: shekhirin/zulip
def deactivate_user_own_backend(request, user_profile):
    # type: (HttpRequest, UserProfile) -> HttpResponse
    admins = set(user_profile.realm.get_admin_users())

    if user_profile.is_realm_admin and len(admins) == 1:
        return json_error(_('Cannot deactivate the only admin'))
    do_deactivate_user(user_profile)
    return json_success()
示例#22
0
def deactivate_user_own_backend(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
    if UserProfile.objects.filter(realm=user_profile.realm, is_active=True).count() == 1:
        raise CannotDeactivateLastUserError(is_last_owner=False)
    if user_profile.is_realm_owner and check_last_owner(user_profile):
        raise CannotDeactivateLastUserError(is_last_owner=True)

    do_deactivate_user(user_profile, acting_user=user_profile)
    return json_success()
示例#23
0
    def test_login_deactivated_user(self):
        """
        logging in fails with an inactive user

        """
        email = "*****@*****.**"
        user_profile = get_user_profile_by_email(email)
        do_deactivate_user(user_profile)

        result = self.login_with_return("*****@*****.**")
        self.assert_in_response("Please enter a correct email and password", result)
示例#24
0
    def test_login_deactivated_user(self):
        # type: () -> None
        """
        logging in fails with an inactive user

        """
        user_profile = self.example_user('hamlet')
        do_deactivate_user(user_profile)

        result = self.login_with_return(self.example_email("hamlet"))
        self.assert_in_response(
            "Sorry for the trouble, but your account has been deactivated",
            result)
示例#25
0
    def test_login_deactivated_user(self):
        # type: () -> None
        """
        logging in fails with an inactive user

        """
        user_profile = self.example_user('hamlet')
        do_deactivate_user(user_profile)

        result = self.login_with_return(self.example_email("hamlet"))
        self.assert_in_response(
            "Sorry for the trouble, but your account has been deactivated",
            result)
示例#26
0
    def test_get_seat_count(self) -> None:
        initial_count = get_seat_count(self.realm)
        user1 = UserProfile.objects.create(realm=self.realm, email='*****@*****.**', pointer=-1)
        user2 = UserProfile.objects.create(realm=self.realm, email='*****@*****.**', pointer=-1)
        self.assertEqual(get_seat_count(self.realm), initial_count + 2)

        # Test that bots aren't counted
        user1.is_bot = True
        user1.save(update_fields=['is_bot'])
        self.assertEqual(get_seat_count(self.realm), initial_count + 1)

        # Test that inactive users aren't counted
        do_deactivate_user(user2)
        self.assertEqual(get_seat_count(self.realm), initial_count)
示例#27
0
    def _test_remove_muted_user_valid_data(self,
                                           deactivate_user: bool = False
                                           ) -> None:
        hamlet = self.example_user("hamlet")
        self.login_user(hamlet)
        cordelia = self.example_user("cordelia")
        mute_time = datetime(2021, 1, 1, tzinfo=timezone.utc)

        if deactivate_user:
            do_deactivate_user(cordelia, acting_user=None)

        with mock.patch("zerver.views.muting.timezone_now",
                        return_value=mute_time):
            url = f"/api/v1/users/me/muted_users/{cordelia.id}"
            result = self.api_post(hamlet, url)
            self.assert_json_success(result)

        with mock.patch("zerver.lib.actions.timezone_now",
                        return_value=mute_time):
            # To test that `RealmAuditLog` entry has correct `event_time`.
            url = f"/api/v1/users/me/muted_users/{cordelia.id}"
            result = self.api_delete(hamlet, url)

        self.assert_json_success(result)
        self.assertNotIn(
            {
                "id": cordelia.id,
                "timestamp": datetime_to_timestamp(mute_time),
            },
            get_user_mutes(hamlet),
        )
        self.assertIsNone(get_mute_object(hamlet, cordelia))

        audit_log_entries = list(
            RealmAuditLog.objects.filter(acting_user=hamlet,
                                         modified_user=hamlet).values_list(
                                             "event_type", "event_time",
                                             "extra_data").order_by("id"))
        self.assert_length(audit_log_entries, 2)
        audit_log_entry = audit_log_entries[1]
        self.assertEqual(
            audit_log_entry,
            (
                RealmAuditLog.USER_UNMUTED,
                mute_time,
                orjson.dumps({
                    "unmuted_user_id": cordelia.id
                }).decode(),
            ),
        )
示例#28
0
文件: backends.py 项目: sumepr/zulip
def sync_user_from_ldap(user_profile: UserProfile, logger: logging.Logger) -> bool:
    backend = ZulipLDAPUserPopulator()
    updated_user = backend.populate_user(backend.django_to_ldap_username(user_profile.email))
    if updated_user:
        logger.info("Updated %s." % (user_profile.email,))
        return True

    if settings.LDAP_DEACTIVATE_NON_MATCHING_USERS:
        do_deactivate_user(user_profile)
        logger.info("Deactivated non-matching user: %s" % (user_profile.email,))
        return True
    elif user_profile.is_active:
        logger.warning("Did not find %s in LDAP." % (user_profile.email,))
    return False
示例#29
0
    def test_single_user_get(self) -> None:
        reset_emails_in_zulip_realm()

        # First, we setup the test with some data
        user = self.example_user("othello")
        self.login_user(user)
        result = self.client_post("/json/users/me/presence",
                                  {"status": "active"})
        result = self.client_post("/json/users/me/presence",
                                  {"status": "active"},
                                  HTTP_USER_AGENT="ZulipDesktop/1.0")
        result = self.api_post(
            user,
            "/api/v1/users/me/presence",
            {"status": "idle"},
            HTTP_USER_AGENT="ZulipAndroid/1.0",
        )
        self.assert_json_success(result)

        # Check some error conditions
        result = self.client_get("/json/users/[email protected]/presence")
        self.assert_json_error(result, "No such user")

        result = self.client_get("/json/users/[email protected]/presence")
        self.assert_json_error(result,
                               "No presence data for [email protected]")

        do_deactivate_user(self.example_user("cordelia"))
        result = self.client_get("/json/users/[email protected]/presence")
        self.assert_json_error(result, "No such user")

        result = self.client_get("/json/users/[email protected]/presence")
        self.assert_json_error(result,
                               "Presence is not supported for bot users.")

        sipbtest = self.mit_user("sipbtest")
        self.login_user(sipbtest)
        result = self.client_get("/json/users/[email protected]/presence",
                                 subdomain="zephyr")
        self.assert_json_error(result, "No such user")

        # Then, we check everything works
        self.login("hamlet")
        result = self.client_get("/json/users/[email protected]/presence")
        result_dict = result.json()
        self.assertEqual(set(result_dict["presence"].keys()),
                         {"ZulipAndroid", "website", "aggregated"})
        self.assertEqual(set(result_dict["presence"]["website"].keys()),
                         {"status", "timestamp"})
示例#30
0
    def test_webhook_deactivated_user(self):
        """
        Deactivated users can't use webhooks

        """
        email = "*****@*****.**"
        user_profile = get_user_profile_by_email(email)
        do_deactivate_user(user_profile)

        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, "Account not active", status_code=400)
示例#31
0
    def test_webhook_deactivated_user(self):
        # type: () -> None
        """
        Deactivated users can't use webhooks

        """
        user_profile = self.example_user('hamlet')
        do_deactivate_user(user_profile)

        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, "Account not active", status_code=400)
示例#32
0
 def test_user_activation(self) -> None:
     realm = get_realm('zulip')
     now = timezone_now()
     user = do_create_user('email', 'password', realm, 'full_name', 'short_name')
     do_deactivate_user(user)
     do_activate_user(user)
     do_deactivate_user(user)
     do_reactivate_user(user)
     self.assertEqual(RealmAuditLog.objects.filter(event_time__gte=now).count(), 5)
     event_types = list(RealmAuditLog.objects.filter(
         realm=realm, acting_user=None, modified_user=user, modified_stream=None,
         event_time__gte=now, event_time__lte=now+timedelta(minutes=60))
         .order_by('event_time').values_list('event_type', flat=True))
     self.assertEqual(event_types, [RealmAuditLog.USER_CREATED, RealmAuditLog.USER_DEACTIVATED, RealmAuditLog.USER_ACTIVATED,
                                    RealmAuditLog.USER_DEACTIVATED, RealmAuditLog.USER_REACTIVATED])
示例#33
0
    def test_get_seat_count(self) -> None:
        realm = get_realm("zulip")
        initial_count = get_seat_count(realm)
        user1 = UserProfile.objects.create(realm=realm, email='*****@*****.**', pointer=-1)
        user2 = UserProfile.objects.create(realm=realm, email='*****@*****.**', pointer=-1)
        self.assertEqual(get_seat_count(realm), initial_count + 2)

        # Test that bots aren't counted
        user1.is_bot = True
        user1.save(update_fields=['is_bot'])
        self.assertEqual(get_seat_count(realm), initial_count + 1)

        # Test that inactive users aren't counted
        do_deactivate_user(user2)
        self.assertEqual(get_seat_count(realm), initial_count)
示例#34
0
    def test_webhook_deactivated_user(self):
        # type: () -> None
        """
        Deactivated users can't use webhooks

        """
        user_profile = self.example_user('hamlet')
        do_deactivate_user(user_profile)

        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, "Account not active", status_code=400)
示例#35
0
 def get_or_build_user(self, username: str,
                       ldap_user: _LDAPUser) -> Tuple[UserProfile, bool]:  # nocoverage
     (user, built) = super().get_or_build_user(username, ldap_user)
     self.sync_avatar_from_ldap(user, ldap_user)
     if 'userAccountControl' in settings.AUTH_LDAP_USER_ATTR_MAP:
         user_disabled_in_ldap = self.is_account_control_disabled_user(ldap_user)
         if user_disabled_in_ldap and user.is_active:
             logging.info("Deactivating user %s because they are disabled in LDAP." %
                          (user.email,))
             do_deactivate_user(user)
             return (user, built)
         if not user_disabled_in_ldap and not user.is_active:
             logging.info("Reactivating user %s because they are not disabled in LDAP." %
                          (user.email,))
             do_reactivate_user(user)
     return (user, built)
示例#36
0
    def test_requires_billing_update_for_is_active_changes(self) -> None:
        count = RealmAuditLog.objects.count()
        user1 = do_create_user('*****@*****.**', 'password', self.realm, 'full name', 'short name')
        do_deactivate_user(user1)
        do_reactivate_user(user1)
        # Not a proper use of do_activate_user, but it's fine to call it like this for this test
        do_activate_user(user1)
        self.assertEqual(count + 4,
                         RealmAuditLog.objects.filter(requires_billing_update=False).count())

        self.realm.has_seat_based_plan = True
        self.realm.save(update_fields=['has_seat_based_plan'])
        user2 = do_create_user('*****@*****.**', 'password', self.realm, 'full name', 'short name')
        do_deactivate_user(user2)
        do_reactivate_user(user2)
        do_activate_user(user2)
        self.assertEqual(4, RealmAuditLog.objects.filter(requires_billing_update=True).count())
示例#37
0
    def test_patch_bot_owner_deactivated(self) -> None:
        self.login(self.example_email('hamlet'))
        self.create_bot()
        self.assert_num_bots_equal(1)

        target_user_profile = self.example_user("othello")
        do_deactivate_user(target_user_profile)
        target_user_profile = self.example_user('othello')
        self.assertFalse(target_user_profile.is_active)
        bot_info = {
            'bot_owner': self.example_email('othello'),
        }

        result = self.client_patch("/json/bots/[email protected]", bot_info)
        self.assert_json_error(result, "Failed to change owner, user is deactivated")
        profile = get_user('*****@*****.**', get_realm('zulip'))
        self.assertEqual(profile.bot_owner, self.example_user("hamlet"))
示例#38
0
 def get_or_build_user(self, username: str,
                       ldap_user: _LDAPUser) -> Tuple[UserProfile, bool]:
     (user, built) = super().get_or_build_user(username, ldap_user)
     self.sync_avatar_from_ldap(user, ldap_user)
     self.sync_full_name_from_ldap(user, ldap_user)
     if 'userAccountControl' in settings.AUTH_LDAP_USER_ATTR_MAP:
         user_disabled_in_ldap = self.is_account_control_disabled_user(ldap_user)
         if user_disabled_in_ldap and user.is_active:
             logging.info("Deactivating user %s because they are disabled in LDAP." %
                          (user.email,))
             do_deactivate_user(user)
             return (user, built)
         if not user_disabled_in_ldap and not user.is_active:
             logging.info("Reactivating user %s because they are not disabled in LDAP." %
                          (user.email,))
             do_reactivate_user(user)
     return (user, built)
示例#39
0
    def test_single_user_get(self):
        # type: () -> None

        # First, we setup the test with some data
        email = self.example_email("othello")
        self.login(self.example_email("othello"))
        result = self.client_post("/json/users/me/presence",
                                  {'status': 'active'})
        result = self.client_post("/json/users/me/presence",
                                  {'status': 'active'},
                                  HTTP_USER_AGENT="ZulipDesktop/1.0")
        result = self.client_post("/api/v1/users/me/presence",
                                  {'status': 'idle'},
                                  HTTP_USER_AGENT="ZulipAndroid/1.0",
                                  **self.api_auth(email))
        self.assert_json_success(result)

        # Check some error conditions
        result = self.client_get("/json/users/[email protected]/presence")
        self.assert_json_error(result, "No such user")

        result = self.client_get("/json/users/[email protected]/presence")
        self.assert_json_error(result,
                               "No presence data for [email protected]")

        do_deactivate_user(self.example_user('cordelia'))
        result = self.client_get("/json/users/[email protected]/presence")
        self.assert_json_error(result, "No such user")

        result = self.client_get("/json/users/[email protected]/presence")
        self.assert_json_error(result,
                               "Presence is not supported for bot users.")

        self.login(self.mit_email("sipbtest"))
        result = self.client_get("/json/users/[email protected]/presence",
                                 subdomain="zephyr")
        self.assert_json_error(result, "No such user")

        # Then, we check everything works
        self.login(self.example_email("hamlet"))
        result = self.client_get("/json/users/[email protected]/presence")
        result_dict = result.json()
        self.assertEqual(set(result_dict['presence'].keys()),
                         {"ZulipAndroid", "website", "aggregated"})
        self.assertEqual(set(result_dict['presence']['website'].keys()),
                         {"status", "timestamp"})
示例#40
0
文件: test_stripe.py 项目: kou/zulip
    def test_requires_billing_update_for_is_active_changes(self) -> None:
        count = RealmAuditLog.objects.count()
        realm = get_realm("zulip")
        user1 = do_create_user('*****@*****.**', 'password', realm, 'full name', 'short name')
        do_deactivate_user(user1)
        do_reactivate_user(user1)
        # Not a proper use of do_activate_user, but it's fine to call it like this for this test
        do_activate_user(user1)
        self.assertEqual(count + 4,
                         RealmAuditLog.objects.filter(requires_billing_update=False).count())

        realm.has_seat_based_plan = True
        realm.save(update_fields=['has_seat_based_plan'])
        user2 = do_create_user('*****@*****.**', 'password', realm, 'full name', 'short name')
        do_deactivate_user(user2)
        do_reactivate_user(user2)
        do_activate_user(user2)
        self.assertEqual(4, RealmAuditLog.objects.filter(requires_billing_update=True).count())
示例#41
0
 def test_active_users_log_by_is_bot(self):
     # type: () -> None
     property = 'active_users_log:is_bot:day'
     user = do_create_user('email', 'password', self.default_realm, 'full_name', 'short_name')
     self.assertEqual(1, RealmCount.objects.filter(property=property, subgroup=False)
                      .aggregate(Sum('value'))['value__sum'])
     do_deactivate_user(user)
     self.assertEqual(0, RealmCount.objects.filter(property=property, subgroup=False)
                      .aggregate(Sum('value'))['value__sum'])
     do_activate_user(user)
     self.assertEqual(1, RealmCount.objects.filter(property=property, subgroup=False)
                      .aggregate(Sum('value'))['value__sum'])
     do_deactivate_user(user)
     self.assertEqual(0, RealmCount.objects.filter(property=property, subgroup=False)
                      .aggregate(Sum('value'))['value__sum'])
     do_reactivate_user(user)
     self.assertEqual(1, RealmCount.objects.filter(property=property, subgroup=False)
                      .aggregate(Sum('value'))['value__sum'])
示例#42
0
    def test_billing_quantity_changes_end_to_end(
            self, mock_customer_with_subscription: Mock, mock_create_subscription: Mock,
            mock_create_customer: Mock) -> None:
        self.login(self.example_email("hamlet"))
        processor = BillingProcessor.objects.create(
            log_row=RealmAuditLog.objects.order_by('id').first(), state=BillingProcessor.DONE)

        def check_billing_processor_update(event_type: str, quantity: int) -> None:
            def check_subscription_save(subscription: stripe.Subscription, idempotency_key: str) -> None:
                self.assertEqual(subscription.quantity, quantity)
                log_row = RealmAuditLog.objects.filter(
                    event_type=event_type, requires_billing_update=True).order_by('-id').first()
                self.assertEqual(idempotency_key, 'process_billing_log_entry:%s' % (log_row.id,))
                self.assertEqual(subscription.proration_date, datetime_to_timestamp(log_row.event_time))
            with patch.object(stripe.Subscription, 'save', autospec=True,
                              side_effect=check_subscription_save):
                run_billing_processor_one_step(processor)

        # Test STRIPE_PLAN_QUANTITY_RESET
        new_seat_count = 123
        # change the seat count while the user is going through the upgrade flow
        with patch('corporate.lib.stripe.get_seat_count', return_value=new_seat_count):
            self.client_post("/upgrade/", {'stripeToken': self.token,
                                           'signed_seat_count': self.signed_seat_count,
                                           'salt': self.salt,
                                           'plan': Plan.CLOUD_ANNUAL})
        check_billing_processor_update(RealmAuditLog.STRIPE_PLAN_QUANTITY_RESET, new_seat_count)

        # Test USER_CREATED
        user = do_create_user('*****@*****.**', 'password', get_realm('zulip'), 'full name', 'short name')
        check_billing_processor_update(RealmAuditLog.USER_CREATED, self.quantity + 1)

        # Test USER_DEACTIVATED
        do_deactivate_user(user)
        check_billing_processor_update(RealmAuditLog.USER_DEACTIVATED, self.quantity - 1)

        # Test USER_REACTIVATED
        do_reactivate_user(user)
        check_billing_processor_update(RealmAuditLog.USER_REACTIVATED, self.quantity + 1)

        # Test USER_ACTIVATED
        # Not a proper use of do_activate_user, but it's fine to call it like this for this test
        do_activate_user(user)
        check_billing_processor_update(RealmAuditLog.USER_ACTIVATED, self.quantity + 1)
示例#43
0
 def test_user_activation(self) -> None:
     realm = get_realm("zulip")
     now = timezone_now()
     user = do_create_user("email",
                           "password",
                           realm,
                           "full_name",
                           acting_user=None)
     do_deactivate_user(user, acting_user=user)
     do_activate_user(user, acting_user=user)
     do_deactivate_user(user, acting_user=user)
     do_reactivate_user(user, acting_user=user)
     self.assertEqual(
         RealmAuditLog.objects.filter(event_time__gte=now).count(), 5)
     event_types = list(
         RealmAuditLog.objects.filter(
             realm=realm,
             acting_user=user,
             modified_user=user,
             modified_stream=None,
             event_time__gte=now,
             event_time__lte=now + timedelta(minutes=60),
         ).order_by("event_time").values_list("event_type", flat=True))
     self.assertEqual(
         event_types,
         [
             RealmAuditLog.USER_CREATED,
             RealmAuditLog.USER_DEACTIVATED,
             RealmAuditLog.USER_ACTIVATED,
             RealmAuditLog.USER_DEACTIVATED,
             RealmAuditLog.USER_REACTIVATED,
         ],
     )
     for event in RealmAuditLog.objects.filter(
             realm=realm,
             acting_user=user,
             modified_user=user,
             modified_stream=None,
             event_time__gte=now,
             event_time__lte=now + timedelta(minutes=60),
     ):
         extra_data = orjson.loads(event.extra_data)
         self.check_role_count_schema(extra_data[RealmAuditLog.ROLE_COUNT])
         self.assertNotIn(RealmAuditLog.OLD_VALUE, extra_data)
示例#44
0
文件: test_stripe.py 项目: kou/zulip
    def test_billing_quantity_changes_end_to_end(
            self, mock_customer_with_subscription: Mock, mock_create_subscription: Mock,
            mock_create_customer: Mock) -> None:
        self.login(self.example_email("hamlet"))
        processor = BillingProcessor.objects.create(
            log_row=RealmAuditLog.objects.order_by('id').first(), state=BillingProcessor.DONE)

        def check_billing_processor_update(event_type: str, quantity: int) -> None:
            def check_subscription_save(subscription: stripe.Subscription, idempotency_key: str) -> None:
                self.assertEqual(subscription.quantity, quantity)
                log_row = RealmAuditLog.objects.filter(
                    event_type=event_type, requires_billing_update=True).order_by('-id').first()
                self.assertEqual(idempotency_key, 'process_billing_log_entry:%s' % (log_row.id,))
                self.assertEqual(subscription.proration_date, datetime_to_timestamp(log_row.event_time))
            with patch.object(stripe.Subscription, 'save', autospec=True,
                              side_effect=check_subscription_save):
                run_billing_processor_one_step(processor)

        # Test STRIPE_PLAN_QUANTITY_RESET
        new_seat_count = 123
        # change the seat count while the user is going through the upgrade flow
        with patch('corporate.lib.stripe.get_seat_count', return_value=new_seat_count):
            self.client_post("/upgrade/", {'stripeToken': self.token,
                                           'signed_seat_count': self.signed_seat_count,
                                           'salt': self.salt,
                                           'plan': Plan.CLOUD_ANNUAL})
        check_billing_processor_update(RealmAuditLog.STRIPE_PLAN_QUANTITY_RESET, new_seat_count)

        # Test USER_CREATED
        user = do_create_user('*****@*****.**', 'password', get_realm('zulip'), 'full name', 'short name')
        check_billing_processor_update(RealmAuditLog.USER_CREATED, self.quantity + 1)

        # Test USER_DEACTIVATED
        do_deactivate_user(user)
        check_billing_processor_update(RealmAuditLog.USER_DEACTIVATED, self.quantity - 1)

        # Test USER_REACTIVATED
        do_reactivate_user(user)
        check_billing_processor_update(RealmAuditLog.USER_REACTIVATED, self.quantity + 1)

        # Test USER_ACTIVATED
        # Not a proper use of do_activate_user, but it's fine to call it like this for this test
        do_activate_user(user)
        check_billing_processor_update(RealmAuditLog.USER_ACTIVATED, self.quantity + 1)
示例#45
0
 def get_or_build_user(
         self, username: str,
         ldap_user: _LDAPUser) -> Tuple[UserProfile, bool]:  # nocoverage
     (user, built) = super().get_or_build_user(username, ldap_user)
     self.sync_avatar_from_ldap(user, ldap_user)
     user_disabled_in_ldap = self.is_account_control_disabled_user(
         ldap_user)
     if user_disabled_in_ldap and user.is_active:
         logging.info(
             "Deactivating user %s because they are disabled in LDAP." %
             (user.email, ))
         do_deactivate_user(user)
         return (user, built)
     if not user_disabled_in_ldap and not user.is_active:
         logging.info(
             "Reactivating user %s because they are not disabled in LDAP." %
             (user.email, ))
         do_reactivate_user(user)
     return (user, built)
示例#46
0
    def test_login_deactivated_mirror_dummy(self):
        # type: () -> None
        """
        logging in fails with an inactive user

        """
        user_profile = self.example_user('hamlet')
        user_profile.is_mirror_dummy = True
        user_profile.save()

        password = initial_password(user_profile.email)
        request = mock.MagicMock()
        request.get_host.return_value = 'zulip.testserver'

        # Test a mirror-dummy active user.
        form = OurAuthenticationForm(request,
                                     data={'username': user_profile.email,
                                           'password': password})
        with self.settings(AUTHENTICATION_BACKENDS=('zproject.backends.EmailAuthBackend',)):
            self.assertTrue(form.is_valid())

        # Test a mirror-dummy deactivated user.
        do_deactivate_user(user_profile)
        user_profile.save()

        form = OurAuthenticationForm(request,
                                     data={'username': user_profile.email,
                                           'password': password})
        with self.settings(AUTHENTICATION_BACKENDS=('zproject.backends.EmailAuthBackend',)):
            self.assertFalse(form.is_valid())
            self.assertIn("Please enter a correct email", str(form.errors))

        # Test a non-mirror-dummy deactivated user.
        user_profile.is_mirror_dummy = False
        user_profile.save()

        form = OurAuthenticationForm(request,
                                     data={'username': user_profile.email,
                                           'password': password})
        with self.settings(AUTHENTICATION_BACKENDS=('zproject.backends.EmailAuthBackend',)):
            self.assertFalse(form.is_valid())
            self.assertIn("your account has been deactivated", str(form.errors))
示例#47
0
    def test_login_deactivated_mirror_dummy(self):
        # type: () -> None
        """
        logging in fails with an inactive user

        """
        user_profile = self.example_user('hamlet')
        user_profile.is_mirror_dummy = True
        user_profile.save()

        password = initial_password(user_profile.email)
        request = mock.MagicMock()
        request.get_host.return_value = 'zulip.testserver'

        # Test a mirror-dummy active user.
        form = OurAuthenticationForm(request,
                                     data={'username': user_profile.email,
                                           'password': password})
        with self.settings(AUTHENTICATION_BACKENDS=('zproject.backends.EmailAuthBackend',)):
            self.assertTrue(form.is_valid())

        # Test a mirror-dummy deactivated user.
        do_deactivate_user(user_profile)
        user_profile.save()

        form = OurAuthenticationForm(request,
                                     data={'username': user_profile.email,
                                           'password': password})
        with self.settings(AUTHENTICATION_BACKENDS=('zproject.backends.EmailAuthBackend',)):
            self.assertFalse(form.is_valid())
            self.assertIn("Please enter a correct email", str(form.errors))

        # Test a non-mirror-dummy deactivated user.
        user_profile.is_mirror_dummy = False
        user_profile.save()

        form = OurAuthenticationForm(request,
                                     data={'username': user_profile.email,
                                           'password': password})
        with self.settings(AUTHENTICATION_BACKENDS=('zproject.backends.EmailAuthBackend',)):
            self.assertFalse(form.is_valid())
            self.assertIn("your account has been deactivated", str(form.errors))
示例#48
0
    def test_single_user_get(self):
        # type: () -> None

        # First, we setup the test with some data
        email = self.example_email("othello")
        self.login(self.example_email("othello"))
        result = self.client_post("/json/users/me/presence", {'status': 'active'})
        result = self.client_post("/json/users/me/presence", {'status': 'active'},
                                  HTTP_USER_AGENT="ZulipDesktop/1.0")
        result = self.client_post("/api/v1/users/me/presence", {'status': 'idle'},
                                  HTTP_USER_AGENT="ZulipAndroid/1.0",
                                  **self.api_auth(email))
        self.assert_json_success(result)

        # Check some error conditions
        result = self.client_get("/json/users/[email protected]/presence")
        self.assert_json_error(result, "No such user")

        result = self.client_get("/json/users/[email protected]/presence")
        self.assert_json_error(result, "No presence data for [email protected]")

        do_deactivate_user(self.example_user('cordelia'))
        result = self.client_get("/json/users/[email protected]/presence")
        self.assert_json_error(result, "No such user")

        result = self.client_get("/json/users/[email protected]/presence")
        self.assert_json_error(result, "Presence is not supported for bot users.")

        self.login(self.mit_email("sipbtest"))
        result = self.client_get("/json/users/[email protected]/presence",
                                 subdomain="zephyr")
        self.assert_json_error(result, "No such user")

        # Then, we check everything works
        self.login(self.example_email("hamlet"))
        result = self.client_get("/json/users/[email protected]/presence")
        result_dict = result.json()
        self.assertEqual(
            set(result_dict['presence'].keys()),
            {"ZulipAndroid", "website", "aggregated"})
        self.assertEqual(set(result_dict['presence']['website'].keys()), {"status", "timestamp"})
示例#49
0
    def handle(self, *args, **options):
        user_profile = get_user_profile_by_email(options['email'])

        print "Deactivating %s (%s) - %s" % (user_profile.full_name,
                                             user_profile.email,
                                             user_profile.realm.domain)
        print "%s has the following active sessions:" % (user_profile.email, )
        for session in user_sessions(user_profile):
            print session.expire_date, session.get_decoded()
        print ""
        print "%s has %s active bots that will also be deactivated." % (
            user_profile.email,
            UserProfile.objects.filter(
                is_bot=True, is_active=True, bot_owner=user_profile).count())

        if not options["for_real"]:
            print "This was a dry run. Pass -f to actually deactivate."
            exit(1)

        do_deactivate_user(user_profile)
        print "Sessions deleted, user deactivated."
示例#50
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)
示例#51
0
文件: backends.py 项目: deltay/zulip
 def get_or_build_user(self, username: str,
                       ldap_user: _LDAPUser) -> Tuple[UserProfile, bool]:
     """This is used only in non-authentication contexts such as:
          ./manage.py sync_ldap_user_data
        In authentication contexts, this is overriden in ZulipLDAPAuthBackend.
     """
     (user, built) = super().get_or_build_user(username, ldap_user)
     self.sync_avatar_from_ldap(user, ldap_user)
     self.sync_full_name_from_ldap(user, ldap_user)
     self.sync_custom_profile_fields_from_ldap(user, ldap_user)
     if 'userAccountControl' in settings.AUTH_LDAP_USER_ATTR_MAP:
         user_disabled_in_ldap = self.is_account_control_disabled_user(ldap_user)
         if user_disabled_in_ldap and user.is_active:
             logging.info("Deactivating user %s because they are disabled in LDAP." %
                          (user.email,))
             do_deactivate_user(user)
             return (user, built)
         if not user_disabled_in_ldap and not user.is_active:
             logging.info("Reactivating user %s because they are not disabled in LDAP." %
                          (user.email,))
             do_reactivate_user(user)
     return (user, built)
示例#52
0
 def test_do_deactivate_user(self):
     bot_deactivate_checker = check_dict([
         ('type', equals('realm_bot')),
         ('op', equals('remove')),
         ('bot', check_dict([
             ('email', check_string),
             ('full_name', check_string),
         ])),
     ])
     bot = self.create_bot('*****@*****.**')
     action = lambda: do_deactivate_user(bot)
     events = self.do_test(action)
     error = bot_deactivate_checker('events[1]', events[1])
     self.assert_on_error(error)
示例#53
0
    def handle(self, *args: Any, **options: Any) -> None:
        realm = self.get_realm(options)
        user_profile = self.get_user(options['email'], realm)

        print("Deactivating %s (%s) - %s" %
              (user_profile.full_name, user_profile.email,
               user_profile.realm.string_id))
        print("%s has the following active sessions:" % (user_profile.email, ))
        for session in user_sessions(user_profile):
            print(session.expire_date, session.get_decoded())
        print("")
        print(
            "%s has %s active bots that will also be deactivated." %
            (user_profile.email,
             UserProfile.objects.filter(
                 is_bot=True, is_active=True, bot_owner=user_profile).count()))

        if not options["for_real"]:
            print("This was a dry run. Pass -f to actually deactivate.")
            exit(1)

        do_deactivate_user(user_profile)
        print("Sessions deleted, user deactivated.")
示例#54
0
    def handle(self, *args, **options):
        user_profile = get_user_profile_by_email(options['email'])

        print "Deactivating %s (%s) - %s" % (user_profile.full_name,
                                             user_profile.email,
                                             user_profile.realm.domain)
        print "%s has the following active sessions:" % (user_profile.email,)
        for session in user_sessions(user_profile):
            print session.expire_date, session.get_decoded()
        print ""
        print "%s has %s active bots that will also be deactivated." % (
                user_profile.email,
                UserProfile.objects.filter(
                    is_bot=True, is_active=True, bot_owner=user_profile
                ).count()
            )

        if not options["for_real"]:
            print "This was a dry run. Pass -f to actually deactivate."
            exit(1)

        do_deactivate_user(user_profile)
        print "Sessions deleted, user deactivated."
示例#55
0
 def test_do_deactivate_user(self):
     bot_deactivate_checker = check_dict([
         ('type', equals('realm_bot')),
         ('op', equals('remove')),
         ('bot', check_dict([
             ('email', check_string),
             ('full_name', check_string),
         ])),
     ])
     bot = self.create_bot('*****@*****.**')
     action = lambda: do_deactivate_user(bot)
     events = self.do_test(action)
     error = bot_deactivate_checker('events[1]', events[1])
     self.assert_on_error(error)
示例#56
0
 def test_basics(self) -> None:
     user = self.example_user('hamlet')
     do_deactivate_user(user)
     self.assertFalse(user.is_active)
     do_reactivate_user(user)
     self.assertTrue(user.is_active)
示例#57
0
文件: users.py 项目: BakerWang/zulip
def _deactivate_user_profile_backend(request: HttpRequest, user_profile: UserProfile,
                                     target: UserProfile) -> HttpResponse:
    do_deactivate_user(target, acting_user=user_profile)
    return json_success()
示例#58
0
def restore_saved_messages():
    # type: () -> None
    old_messages = [] # type: List[Dict[str, Any]]
    duplicate_suppression_hash = {} # type: Dict[str, bool]

    stream_dict = {} # type: Dict[Tuple[text_type, text_type], Tuple[text_type, text_type]]
    user_set = set() # type: Set[Tuple[text_type, text_type, text_type, bool]]
    email_set = set([u.email for u in UserProfile.objects.all()]) # type: Set[text_type]
    realm_set = set() # type: Set[text_type]
    # Initial client_set is nonempty temporarily because we don't have
    # clients in logs at all right now -- later we can start with nothing.
    client_set = set(["populate_db", "website", "zephyr_mirror"])
    huddle_user_set = set() # type: Set[Tuple[text_type, ...]]
    # First, determine all the objects our messages will need.
    print(datetime.datetime.now(), "Creating realms/streams/etc...")
    def process_line(line):
        # type: (str) -> None
        old_message_json = line.strip()

        # Due to populate_db's shakespeare mode, we have a lot of
        # duplicate messages in our log that only differ in their
        # logged ID numbers (same timestamp, content, etc.).  With
        # sqlite, bulk creating those messages won't work properly: in
        # particular, the first 100 messages will actually only result
        # in 20 rows ending up in the target table, which screws up
        # the below accounting where for handling changing
        # subscriptions, we assume that the Nth row populate_db
        # created goes with the Nth non-subscription row of the input
        # So suppress the duplicates when using sqlite.
        if "sqlite" in settings.DATABASES["default"]["ENGINE"]:
            tmp_message = ujson.loads(old_message_json)
            tmp_message['id'] = '1'
            duplicate_suppression_key = ujson.dumps(tmp_message)
            if duplicate_suppression_key in duplicate_suppression_hash:
                return
            duplicate_suppression_hash[duplicate_suppression_key] = True

        old_message = ujson.loads(old_message_json)
        message_type = old_message["type"]

        # Lower case emails and domains; it will screw up
        # deduplication if we don't
        def fix_email(email):
            # type: (text_type) -> text_type
            return email.strip().lower()

        if message_type in ["stream", "huddle", "personal"]:
            old_message["sender_email"] = fix_email(old_message["sender_email"])
            # Fix the length on too-long messages before we start processing them
            if len(old_message["content"]) > MAX_MESSAGE_LENGTH:
                old_message["content"] = "[ This message was deleted because it was too long ]"
        if message_type in ["subscription_added", "subscription_removed"]:
            old_message["domain"] = old_message["domain"].lower()
            old_message["user"] = fix_email(old_message["user"])
        elif message_type == "subscription_property":
            old_message["user"] = fix_email(old_message["user"])
        elif message_type == "user_email_changed":
            old_message["old_email"] = fix_email(old_message["old_email"])
            old_message["new_email"] = fix_email(old_message["new_email"])
        elif message_type.startswith("user_"):
            old_message["user"] = fix_email(old_message["user"])
        elif message_type.startswith("enable_"):
            old_message["user"] = fix_email(old_message["user"])

        if message_type == 'personal':
            old_message["recipient"][0]["email"] = fix_email(old_message["recipient"][0]["email"])
        elif message_type == "huddle":
            for i in range(len(old_message["recipient"])):
                old_message["recipient"][i]["email"] = fix_email(old_message["recipient"][i]["email"])

        old_messages.append(old_message)

        if message_type in ["subscription_added", "subscription_removed"]:
            stream_name = old_message["name"].strip() # type: text_type
            canon_stream_name = stream_name.lower()
            if canon_stream_name not in stream_dict:
                stream_dict[(old_message["domain"], canon_stream_name)] = \
                    (old_message["domain"], stream_name)
        elif message_type == "user_created":
            user_set.add((old_message["user"], old_message["full_name"], old_message["short_name"], False))
        elif message_type == "realm_created":
            realm_set.add(old_message["domain"])

        if message_type not in ["stream", "huddle", "personal"]:
            return

        sender_email = old_message["sender_email"]

        domain = split_email_to_domain(sender_email)
        realm_set.add(domain)

        if old_message["sender_email"] not in email_set:
            user_set.add((old_message["sender_email"],
                          old_message["sender_full_name"],
                          old_message["sender_short_name"],
                          False))

        if 'sending_client' in old_message:
            client_set.add(old_message['sending_client'])

        if message_type == 'stream':
            stream_name = old_message["recipient"].strip()
            canon_stream_name = stream_name.lower()
            if canon_stream_name not in stream_dict:
                stream_dict[(domain, canon_stream_name)] = (domain, stream_name)
        elif message_type == 'personal':
            u = old_message["recipient"][0]
            if u["email"] not in email_set:
                user_set.add((u["email"], u["full_name"], u["short_name"], False))
                email_set.add(u["email"])
        elif message_type == 'huddle':
            for u in old_message["recipient"]:
                user_set.add((u["email"], u["full_name"], u["short_name"], False))
                if u["email"] not in email_set:
                    user_set.add((u["email"], u["full_name"], u["short_name"], False))
                    email_set.add(u["email"])
            huddle_user_set.add(tuple(sorted(set(u["email"] for u in old_message["recipient"]))))
        else:
            raise ValueError('Bad message type')

    event_glob = os.path.join(settings.EVENT_LOG_DIR, 'events.*')
    for filename in sorted(glob.glob(event_glob)):
        with open(filename, "r") as message_log:
            for line in message_log.readlines():
                process_line(line)

    stream_recipients = {} # type: Dict[Tuple[int, text_type], Recipient]
    user_recipients = {} # type: Dict[text_type, Recipient]
    huddle_recipients = {} # type: Dict[text_type, Recipient]

    # Then, create the objects our messages need.
    print(datetime.datetime.now(), "Creating realms...")
    bulk_create_realms(realm_set)

    realms = {} # type: Dict[text_type, Realm]
    for realm in Realm.objects.all():
        realms[realm.domain] = realm

    print(datetime.datetime.now(), "Creating clients...")
    bulk_create_clients(client_set)

    clients = {} # type: Dict[text_type, Client]
    for client in Client.objects.all():
        clients[client.name] = client

    print(datetime.datetime.now(), "Creating streams...")
    bulk_create_streams(realms, list(stream_dict.values()))

    streams = {} # type: Dict[int, Stream]
    for stream in Stream.objects.all():
        streams[stream.id] = stream
    for recipient in Recipient.objects.filter(type=Recipient.STREAM):
        stream_recipients[(streams[recipient.type_id].realm_id,
                           streams[recipient.type_id].name.lower())] = recipient

    print(datetime.datetime.now(), "Creating users...")
    bulk_create_users(realms, user_set, tos_version=settings.TOS_VERSION)

    users = {} # type: Dict[text_type, UserProfile]
    users_by_id = {} # type: Dict[int, UserProfile]
    for user_profile in UserProfile.objects.select_related().all():
        users[user_profile.email] = user_profile
        users_by_id[user_profile.id] = user_profile
    for recipient in Recipient.objects.filter(type=Recipient.PERSONAL):
        user_recipients[users_by_id[recipient.type_id].email] = recipient

    print(datetime.datetime.now(), "Creating huddles...")
    bulk_create_huddles(users, huddle_user_set)

    huddles_by_id = {} # type: Dict[int, Huddle]
    for huddle in Huddle.objects.all():
        huddles_by_id[huddle.id] = huddle
    for recipient in Recipient.objects.filter(type=Recipient.HUDDLE):
        huddle_recipients[huddles_by_id[recipient.type_id].huddle_hash] = recipient

    # TODO: Add a special entry type in the log that is a subscription
    # change and import those as we go to make subscription changes
    # take effect!
    print(datetime.datetime.now(), "Importing subscriptions...")
    subscribers = {} # type: Dict[int, Set[int]]
    for s in Subscription.objects.select_related().all():
        if s.active:
            subscribers.setdefault(s.recipient.id, set()).add(s.user_profile.id)

    # Then create all the messages, without talking to the DB!
    print(datetime.datetime.now(), "Importing messages, part 1...")
    first_message_id = None
    if Message.objects.exists():
        first_message_id = Message.objects.all().order_by("-id")[0].id + 1

    messages_to_create = [] # type: List[Message]
    for idx, old_message in enumerate(old_messages):
        message_type = old_message["type"]
        if message_type not in ["stream", "huddle", "personal"]:
            continue

        message = Message()

        sender_email = old_message["sender_email"]
        domain = split_email_to_domain(sender_email)
        realm = realms[domain]

        message.sender = users[sender_email]
        type_hash = {"stream": Recipient.STREAM,
                     "huddle": Recipient.HUDDLE,
                     "personal": Recipient.PERSONAL}

        if 'sending_client' in old_message:
            message.sending_client = clients[old_message['sending_client']]
        elif sender_email in ["*****@*****.**", "*****@*****.**", "*****@*****.**",
                              "*****@*****.**", "*****@*****.**"]:
            message.sending_client = clients['populate_db']
        elif realm.domain == "zulip.com":
            message.sending_client = clients["website"]
        elif realm.domain == "mit.edu":
            message.sending_client = clients['zephyr_mirror']
        else:
            message.sending_client = clients['populate_db']

        message.type = type_hash[message_type]
        message.content = old_message["content"]
        message.subject = old_message["subject"]
        message.pub_date = timestamp_to_datetime(old_message["timestamp"])

        if message.type == Recipient.PERSONAL:
            message.recipient = user_recipients[old_message["recipient"][0]["email"]]
        elif message.type == Recipient.STREAM:
            message.recipient = stream_recipients[(realm.id,
                                                   old_message["recipient"].lower())]
        elif message.type == Recipient.HUDDLE:
            huddle_hash = get_huddle_hash([users[u["email"]].id
                                           for u in old_message["recipient"]])
            message.recipient = huddle_recipients[huddle_hash]
        else:
            raise ValueError('Bad message type')
        messages_to_create.append(message)

    print(datetime.datetime.now(), "Importing messages, part 2...")
    Message.objects.bulk_create(messages_to_create)
    messages_to_create = []

    # Finally, create all the UserMessage objects
    print(datetime.datetime.now(), "Importing usermessages, part 1...")
    personal_recipients = {} # type: Dict[int, bool]
    for r in Recipient.objects.filter(type = Recipient.PERSONAL):
        personal_recipients[r.id] = True

    all_messages = Message.objects.all() # type: Sequence[Message]
    user_messages_to_create = [] # type: List[UserMessage]

    messages_by_id = {} # type: Dict[int, Message]
    for message in all_messages:
        messages_by_id[message.id] = message

    if len(messages_by_id) == 0:
        print(datetime.datetime.now(), "No old messages to replay")
        return

    if first_message_id is None:
        first_message_id = min(messages_by_id.keys())

    tot_user_messages = 0
    pending_subs = {} # type: Dict[Tuple[int, int], bool]
    current_message_id = first_message_id
    pending_colors = {} # type: Dict[Tuple[text_type, text_type], text_type]
    for old_message in old_messages:
        message_type = old_message["type"]
        if message_type == 'subscription_added':
            stream_key = (realms[old_message["domain"]].id, old_message["name"].strip().lower())
            subscribers.setdefault(stream_recipients[stream_key].id,
                                   set()).add(users[old_message["user"]].id)
            pending_subs[(stream_recipients[stream_key].id,
                          users[old_message["user"]].id)] = True
            continue
        elif message_type == "subscription_removed":
            stream_key = (realms[old_message["domain"]].id, old_message["name"].strip().lower())
            user_id = users[old_message["user"]].id
            subscribers.setdefault(stream_recipients[stream_key].id, set())
            try:
                subscribers[stream_recipients[stream_key].id].remove(user_id)
            except KeyError:
                print("Error unsubscribing %s from %s: not subscribed" % (
                    old_message["user"], old_message["name"]))
            pending_subs[(stream_recipients[stream_key].id,
                          users[old_message["user"]].id)] = False
            continue
        elif message_type == "user_activated" or message_type == "user_created":
            # These are rare, so just handle them the slow way
            user_profile = users[old_message["user"]]
            join_date = timestamp_to_datetime(old_message['timestamp'])
            do_activate_user(user_profile, log=False, join_date=join_date)
            # Update the cache of users to show this user as activated
            users_by_id[user_profile.id] = user_profile
            users[old_message["user"]] = user_profile
            continue
        elif message_type == "user_deactivated":
            user_profile = users[old_message["user"]]
            do_deactivate_user(user_profile, log=False)
            continue
        elif message_type == "user_change_password":
            # Just handle these the slow way
            user_profile = users[old_message["user"]]
            do_change_password(user_profile, old_message["pwhash"], log=False,
                               hashed_password=True)
            continue
        elif message_type == "user_change_full_name":
            # Just handle these the slow way
            user_profile = users[old_message["user"]]
            user_profile.full_name = old_message["full_name"]
            user_profile.save(update_fields=["full_name"])
            continue
        elif message_type == "enable_desktop_notifications_changed":
            # Just handle these the slow way
            user_profile = users[old_message["user"]]
            user_profile.enable_desktop_notifications = (old_message["enable_desktop_notifications"] != "false")
            user_profile.save(update_fields=["enable_desktop_notifications"])
            continue
        elif message_type == "enable_sounds_changed":
            user_profile = users[old_message["user"]]
            user_profile.enable_sounds = (old_message["enable_sounds"] != "false")
            user_profile.save(update_fields=["enable_sounds"])
        elif message_type == "enable_offline_email_notifications_changed":
            user_profile = users[old_message["user"]]
            user_profile.enable_offline_email_notifications = (
                old_message["enable_offline_email_notifications"] != "false")
            user_profile.save(update_fields=["enable_offline_email_notifications"])
            continue
        elif message_type == "enable_offline_push_notifications_changed":
            user_profile = users[old_message["user"]]
            user_profile.enable_offline_push_notifications = (
                old_message["enable_offline_push_notifications"] != "false")
            user_profile.save(update_fields=["enable_offline_push_notifications"])
            continue
        elif message_type == "default_streams":
            set_default_streams(get_realm(old_message["domain"]),
                                old_message["streams"])
            continue
        elif message_type == "subscription_property":
            property_name = old_message.get("property")
            if property_name == "stream_color" or property_name == "color":
                color = old_message.get("color", old_message.get("value"))
                pending_colors[(old_message["user"],
                                old_message["stream_name"].lower())] = color
            elif property_name in ["in_home_view", "notifications"]:
                # TODO: Handle this
                continue
            else:
                raise RuntimeError("Unknown property %s" % (property_name,))
            continue
        elif message_type == "realm_created":
            # No action required
            continue
        elif message_type in ["user_email_changed", "update_onboarding", "update_message"]:
            # TODO: Handle these
            continue
        if message_type not in ["stream", "huddle", "personal"]:
            raise RuntimeError("Unexpected message type %s" % (message_type,))

        message = messages_by_id[current_message_id]
        current_message_id += 1

        if message.recipient_id not in subscribers:
            # Nobody received this message -- probably due to our
            # subscriptions being out-of-date.
            continue

        recipient_user_ids = set() # type: Set[int]
        for user_profile_id in subscribers[message.recipient_id]:
            recipient_user_ids.add(user_profile_id)
        if message.recipient_id in personal_recipients:
            # Include the sender in huddle recipients
            recipient_user_ids.add(message.sender_id)

        for user_profile_id in recipient_user_ids:
            if users_by_id[user_profile_id].is_active:
                um = UserMessage(user_profile_id=user_profile_id,
                                 message=message)
                user_messages_to_create.append(um)

        if len(user_messages_to_create) > 100000:
            tot_user_messages += len(user_messages_to_create)
            UserMessage.objects.bulk_create(user_messages_to_create)
            user_messages_to_create = []

    print(datetime.datetime.now(), "Importing usermessages, part 2...")
    tot_user_messages += len(user_messages_to_create)
    UserMessage.objects.bulk_create(user_messages_to_create)

    print(datetime.datetime.now(), "Finalizing subscriptions...")
    current_subs = {} # type: Dict[Tuple[int, int], bool]
    current_subs_obj = {} # type: Dict[Tuple[int, int], Subscription]
    for s in Subscription.objects.select_related().all():
        current_subs[(s.recipient_id, s.user_profile_id)] = s.active
        current_subs_obj[(s.recipient_id, s.user_profile_id)] = s

    subscriptions_to_add = [] # type: List[Subscription]
    subscriptions_to_change = [] # type: List[Tuple[Tuple[int, int], bool]]
    for pending_sub in pending_subs.keys():
        (recipient_id, user_profile_id) = pending_sub
        current_state = current_subs.get(pending_sub)
        if pending_subs[pending_sub] == current_state:
            # Already correct in the database
            continue
        elif current_state is not None:
            subscriptions_to_change.append((pending_sub, pending_subs[pending_sub]))
            continue

        s = Subscription(recipient_id=recipient_id,
                         user_profile_id=user_profile_id,
                         active=pending_subs[pending_sub])
        subscriptions_to_add.append(s)
    Subscription.objects.bulk_create(subscriptions_to_add)
    for (sub_tuple, active) in subscriptions_to_change:
        current_subs_obj[sub_tuple].active = active
        current_subs_obj[sub_tuple].save(update_fields=["active"])

    subs = {} # type: Dict[Tuple[int, int], Subscription]
    for sub in Subscription.objects.all():
        subs[(sub.user_profile_id, sub.recipient_id)] = sub

    # TODO: do restore of subscription colors -- we're currently not
    # logging changes so there's little point in having the code :(

    print(datetime.datetime.now(), "Finished importing %s messages (%s usermessages)" % \
        (len(all_messages), tot_user_messages))

    site = Site.objects.get_current()
    site.domain = 'zulip.com'
    site.save()

    print(datetime.datetime.now(), "Filling in user pointers...")

    # Set restored pointers to the very latest messages
    for user_profile in UserProfile.objects.all():
        try:
            top = UserMessage.objects.filter(
                user_profile_id=user_profile.id).order_by("-message")[0]
            user_profile.pointer = top.message_id
        except IndexError:
            user_profile.pointer = -1
        user_profile.save(update_fields=["pointer"])

    print(datetime.datetime.now(), "Done replaying old messages")
示例#59
0
文件: users.py 项目: 8trust/zulip
def _deactivate_user_profile_backend(request, user_profile, target):
    if not user_profile.can_admin_user(target):
        return json_error('Insufficient permission')

    do_deactivate_user(target)
    return json_success({})