def handle(self, *args: Any, **options: str) -> None: realm = self.get_realm(options) assert realm is not None # Should be ensured by parser encoding = sys.getfilesystemencoding() stream_name = options['stream_name'] create_stream_if_needed(realm, force_text(stream_name, encoding))
def test_new_stream_link(self, mock_django_timezone: mock.MagicMock) -> None: cutoff = datetime.datetime(year=2017, month=11, day=1) mock_django_timezone.return_value = datetime.datetime(year=2017, month=11, day=5) cordelia = self.example_user('cordelia') create_stream_if_needed(cordelia.realm, 'New stream') new_stream = gather_new_streams(cordelia, cutoff)[1] expected_html = "<a href='http://zulip.testserver/#narrow/stream/New.20stream'>New stream</a>" self.assertIn(expected_html, new_stream['html'])
def handle(self, *args, **options): # type: (*Any, **str) -> None string_id = options['realm'] encoding = sys.getfilesystemencoding() stream_name = options['stream_name'] realm = get_realm(force_text(string_id, encoding)) if realm is None: print("Unknown string_id %s" % (string_id,)) exit(1) create_stream_if_needed(realm, force_text(stream_name, encoding))
def handle(self, *args, **options): # type: (*Any, **str) -> None string_id = options['realm'] encoding = sys.getfilesystemencoding() stream_name = options['stream_name'] realm = get_realm(force_text(string_id, encoding)) if realm is None: print("Unknown string_id %s" % (string_id, )) exit(1) create_stream_if_needed(realm, force_text(stream_name, encoding))
def test_register(self): realm = get_realm("zulip.com") streams = ["stream_%s" % i for i in range(40)] for stream in streams: create_stream_if_needed(realm, stream) set_default_streams(realm, streams) with queries_captured() as queries: self.register("test", "test") # Ensure the number of queries we make is not O(streams) self.assert_length(queries, 67) user_profile = get_user_profile_by_email('*****@*****.**') self.assertEqual(get_session_dict_user(self.client.session), user_profile.id)
def test_register(self): realm = get_realm("zulip.com") streams = ["stream_%s" % i for i in range(40)] for stream in streams: create_stream_if_needed(realm, stream) set_default_streams(realm, streams) with queries_captured() as queries: self.register("test", "test") # Ensure the number of queries we make is not O(streams) self.assert_length(queries, 74) user_profile = get_user_profile_by_email('*****@*****.**') self.assertEqual(get_session_dict_user(self.client.session), user_profile.id)
def test_slow_query_log(self, mock_logging_info: Mock) -> None: error_bot = get_system_bot(settings.ERROR_BOT) create_stream_if_needed(error_bot.realm, settings.SLOW_QUERY_LOGS_STREAM) self.log_data['time_started'] = time.time() - self.SLOW_QUERY_TIME write_log_line(self.log_data, path='/socket/open', method='SOCKET', remote_ip='123.456.789.012', email='unknown', client_name='?') last_message = self.get_last_message() self.assertEqual(last_message.sender.email, "*****@*****.**") self.assertIn("logs", str(last_message.recipient)) self.assertEqual(last_message.topic_name(), "testserver: slow queries") self.assertRegexpMatches(last_message.content, r"123\.456\.789\.012 SOCKET 200 10\.\ds .*")
def test_invite_user_signup_initial_history(self): """ Test that a new user invited to a stream receives some initial history but only from public streams. """ self.login("*****@*****.**") user_profile = get_user_profile_by_email("*****@*****.**") private_stream_name = "Secret" (stream, _) = create_stream_if_needed(user_profile.realm, private_stream_name, invite_only=True) do_add_subscription(user_profile, stream) public_msg_id = self.send_message("*****@*****.**", "Denmark", Recipient.STREAM, "Public topic", "Public message") secret_msg_id = self.send_message("*****@*****.**", private_stream_name, Recipient.STREAM, "Secret topic", "Secret message") invitee = "*****@*****.**" self.assert_json_success( self.invite(invitee, [private_stream_name, "Denmark"])) self.assertTrue(find_key_by_email(invitee)) self.submit_reg_form_for_user("alice-test", "password") invitee_profile = get_user_profile_by_email(invitee) invitee_msg_ids = [ um.message_id for um in UserMessage.objects.filter(user_profile=invitee_profile) ] self.assertTrue(public_msg_id in invitee_msg_ids) self.assertFalse(secret_msg_id in invitee_msg_ids)
def test_rename_stream(self): realm = get_realm('zulip.com') stream, _ = create_stream_if_needed(realm, 'old_name') new_name = u'stream with a brand new name' self.subscribe_to_stream(self.user_profile.email, stream.name) action = lambda: do_rename_stream(realm, stream.name, new_name) events = self.do_test(action) schema_checker = check_dict([ ('type', equals('stream')), ('op', equals('update')), ('property', equals('email_address')), ('value', check_string), ('name', equals('old_name')), ]) error = schema_checker('events[0]', events[0]) self.assert_on_error(error) schema_checker = check_dict([ ('type', equals('stream')), ('op', equals('update')), ('property', equals('name')), ('value', equals(new_name)), ('name', equals('old_name')), ]) error = schema_checker('events[1]', events[1]) self.assert_on_error(error)
def subscribe_to_stream(self, email, stream_name, realm=None): realm = get_realm(resolve_email_to_domain(email)) stream = get_stream(stream_name, realm) if stream is None: stream, _ = create_stream_if_needed(realm, stream_name) user_profile = get_user_profile_by_email(email) do_add_subscription(user_profile, stream, no_log=True)
def handle(self, **options): # type: (**Any) -> None if options["domain"] is None or options["streams"] is None or \ (options["users"] is None and options["all_users"] is None): self.print_help("python manage.py", "add_users_to_streams") exit(1) stream_names = set([stream.strip() for stream in options["streams"].split(",")]) realm = get_realm(options["domain"]) if options["all_users"]: user_profiles = UserProfile.objects.filter(realm=realm) else: emails = set([email.strip() for email in options["users"].split(",")]) user_profiles = [] for email in emails: user_profiles.append(get_user_profile_by_email(email)) for stream_name in set(stream_names): for user_profile in user_profiles: stream, _ = create_stream_if_needed(user_profile.realm, stream_name) did_subscribe = do_add_subscription(user_profile, stream) print("%s %s to %s" % ( "Subscribed" if did_subscribe else "Already subscribed", user_profile.email, stream_name))
def handle(self, **options): # type: (**Any) -> None if options["domain"] is None or options["streams"] is None or \ (options["users"] is None and options["all_users"] is None): self.print_help("python manage.py", "add_users_to_streams") exit(1) stream_names = set( [stream.strip() for stream in options["streams"].split(",")]) realm = get_realm(options["domain"]) if options["all_users"]: user_profiles = UserProfile.objects.filter(realm=realm) else: emails = set( [email.strip() for email in options["users"].split(",")]) user_profiles = [] for email in emails: user_profiles.append(get_user_profile_by_email(email)) for stream_name in set(stream_names): for user_profile in user_profiles: stream, _ = create_stream_if_needed(user_profile.realm, stream_name) _ignore, already_subscribed = bulk_add_subscriptions( [stream], [user_profile]) was_there_already = user_profile.id in { tup[0].id for tup in already_subscribed } print("%s %s to %s" % ("Already subscribed" if was_there_already else "Subscribed", user_profile.email, stream_name))
def handle(self, *args, **options): # type: (*Any, **Any) -> None realm = self.get_realm(options) assert realm is not None # Should be ensured by parser streams = [] if options["streams"]: stream_names = set( [stream.strip() for stream in options["streams"].split(",")]) for stream_name in set(stream_names): stream, _ = create_stream_if_needed(realm, stream_name) streams.append(stream) referred_by = self.get_user(options['referred_by'], realm) invite = MultiuseInvite.objects.create(realm=realm, referred_by=referred_by) if streams: invite.streams = streams invite.save() invite_link = create_confirmation_link(invite, realm.host, Confirmation.MULTIUSE_INVITE) print( "You can use %s to invite as many number of people to the organization." % (invite_link, ))
def test_invite_user_signup_initial_history(self): # type: () -> None """ Test that a new user invited to a stream receives some initial history but only from public streams. """ self.login("*****@*****.**") user_profile = get_user_profile_by_email("*****@*****.**") private_stream_name = "Secret" (stream, _) = create_stream_if_needed(user_profile.realm, private_stream_name, invite_only=True) do_add_subscription(user_profile, stream) public_msg_id = self.send_message("*****@*****.**", "Denmark", Recipient.STREAM, "Public topic", "Public message") secret_msg_id = self.send_message("*****@*****.**", private_stream_name, Recipient.STREAM, "Secret topic", "Secret message") invitee = "*****@*****.**" self.assert_json_success(self.invite(invitee, [private_stream_name, "Denmark"])) self.assertTrue(find_key_by_email(invitee)) self.submit_reg_form_for_user("alice-test", "password") invitee_profile = get_user_profile_by_email(invitee) invitee_msg_ids = [um.message_id for um in UserMessage.objects.filter(user_profile=invitee_profile)] self.assertTrue(public_msg_id in invitee_msg_ids) self.assertFalse(secret_msg_id in invitee_msg_ids)
def handle(self, **options): if options["domain"] is None or options["streams"] is None or \ (options["users"] is None and options["all_users"] is None): self.print_help("python manage.py", "add_users_to_streams") exit(1) stream_names = set( [stream.strip() for stream in options["streams"].split(",")]) realm = get_realm(options["domain"]) if options["all_users"]: user_profiles = UserProfile.objects.filter(realm=realm) else: emails = set( [email.strip() for email in options["users"].split(",")]) user_profiles = [] for email in emails: user_profiles.append(get_user_profile_by_email(email)) for stream_name in set(stream_names): for user_profile in user_profiles: stream, _ = create_stream_if_needed(user_profile.realm, stream_name) did_subscribe = do_add_subscription(user_profile, stream) print("%s %s to %s" % ("Subscribed" if did_subscribe else "Already subscribed", user_profile.email, stream_name))
def handle(self, *args, **options): # type: (*Any, **Any) -> None realm = self.get_realm(options) assert realm is not None # Should be ensured by parser streams = [] stream_names = set([stream.strip() for stream in options["streams"].split(",")]) for stream_name in set(stream_names): stream, _ = create_stream_if_needed(realm, stream_name) streams.append(stream) try: default_stream_group = DefaultStreamGroup.objects.get( name=options["name"], realm=realm, description=options["description"]) except DefaultStreamGroup.DoesNotExist: default_stream_group = DefaultStreamGroup.objects.create( name=options["name"], realm=realm, description=options["description"]) default_stream_group.streams = streams default_stream_group.save() default_stream_groups = DefaultStreamGroup.objects.all() for default_stream_group in default_stream_groups: print(default_stream_group.name) print(default_stream_group.description) for stream in default_stream_group.streams.all(): print(stream.name) print("")
def handle(self, *args, **options): # type: (*Any, **Any) -> None realm = self.get_realm(options) assert realm is not None # Should be ensured by parser streams = [] stream_names = set( [stream.strip() for stream in options["streams"].split(",")]) for stream_name in set(stream_names): stream, _ = create_stream_if_needed(realm, stream_name) streams.append(stream) try: default_stream_group = DefaultStreamGroup.objects.get( name=options["name"], realm=realm, description=options["description"]) except DefaultStreamGroup.DoesNotExist: default_stream_group = DefaultStreamGroup.objects.create( name=options["name"], realm=realm, description=options["description"]) default_stream_group.streams = streams default_stream_group.save() default_stream_groups = DefaultStreamGroup.objects.all() for default_stream_group in default_stream_groups: print(default_stream_group.name) print(default_stream_group.description) for stream in default_stream_group.streams.all(): print(stream.name) print("")
def handle(self, **options): # type: (**Any) -> None if ( options["string_id"] is None or options["streams"] is None or (options["users"] is None and options["all_users"] is None) ): self.print_help("./manage.py", "add_users_to_streams") exit(1) stream_names = set([stream.strip() for stream in options["streams"].split(",")]) realm = get_realm_by_string_id(options["string_id"]) if options["all_users"]: user_profiles = UserProfile.objects.filter(realm=realm) else: emails = set([email.strip() for email in options["users"].split(",")]) user_profiles = [] for email in emails: user_profiles.append(get_user_profile_by_email(email)) for stream_name in set(stream_names): for user_profile in user_profiles: stream, _ = create_stream_if_needed(user_profile.realm, stream_name) _ignore, already_subscribed = bulk_add_subscriptions([stream], [user_profile]) was_there_already = user_profile.id in {tup[0].id for tup in already_subscribed} print( "%s %s to %s" % ("Already subscribed" if was_there_already else "Subscribed", user_profile.email, stream_name) )
def subscribe(self, user_profile: UserProfile, stream_name: str) -> Stream: try: stream = get_stream(stream_name, user_profile.realm) from_stream_creation = False except Stream.DoesNotExist: stream, from_stream_creation = create_stream_if_needed(user_profile.realm, stream_name) bulk_add_subscriptions([stream], [user_profile], from_stream_creation=from_stream_creation) return stream
def subscribe(self, user_profile: UserProfile, stream_name: Text) -> Stream: try: stream = get_stream(stream_name, user_profile.realm) from_stream_creation = False except Stream.DoesNotExist: stream, from_stream_creation = create_stream_if_needed(user_profile.realm, stream_name) bulk_add_subscriptions([stream], [user_profile], from_stream_creation=from_stream_creation) return stream
def setup_initial_private_stream(user): # type: (UserProfile) -> None stream, _ = create_stream_if_needed( user.realm, "core team", invite_only=True, stream_description="A private stream for core team members.") bulk_add_subscriptions([stream], [user])
def list_to_streams(streams_raw, user_profile, autocreate=False, invite_only=False): # type: (List[str], UserProfile, Optional[bool], Optional[bool]) -> Tuple[List[Stream], List[Stream]] """Converts plaintext stream names to a list of Streams, validating input in the process For each stream name, we validate it to ensure it meets our requirements for a proper stream name: that is, that it is shorter than Stream.MAX_NAME_LENGTH characters and passes valid_stream_name. This function in autocreate mode should be atomic: either an exception will be raised during a precheck, or all the streams specified will have been created if applicable. @param streams_raw The list of stream names to process @param user_profile The user for whom we are retreiving the streams @param autocreate Whether we should create streams if they don't already exist @param invite_only Whether newly created streams should have the invite_only bit set """ existing_streams = [] created_streams = [] # Validate all streams, getting extant ones, then get-or-creating the rest. stream_set = set(stream_name.strip() for stream_name in streams_raw) rejects = [] for stream_name in stream_set: if len(stream_name) > Stream.MAX_NAME_LENGTH: raise JsonableError( _("Stream name (%s) too long.") % (stream_name, )) if not valid_stream_name(stream_name): raise JsonableError( _("Invalid stream name (%s).") % (stream_name, )) existing_stream_map = bulk_get_streams(user_profile.realm, stream_set) for stream_name in stream_set: stream = existing_stream_map.get(stream_name.lower()) if stream is None: rejects.append(stream_name) else: existing_streams.append(stream) if rejects: if not user_profile.can_create_streams(): raise JsonableError(_('User cannot create streams.')) elif not autocreate: raise JsonableError( _("Stream(s) (%s) do not exist") % ", ".join(rejects)) for stream_name in rejects: stream, created = create_stream_if_needed(user_profile.realm, stream_name, invite_only=invite_only) if created: created_streams.append(stream) else: existing_streams.append(stream) return existing_streams, created_streams
def subscribe_to_stream(self, email, stream_name, realm=None): # type: (text_type, text_type, Optional[Realm]) -> None if realm is None: realm = get_realm_by_email_domain(email) stream = get_stream(stream_name, realm) if stream is None: stream, _ = create_stream_if_needed(realm, stream_name) user_profile = get_user_profile_by_email(email) bulk_add_subscriptions([stream], [user_profile])
def list_to_streams(streams_raw, user_profile, autocreate=False, invite_only=False): # type: (Iterable[text_type], UserProfile, Optional[bool], Optional[bool]) -> Tuple[List[Stream], List[Stream]] """Converts plaintext stream names to a list of Streams, validating input in the process For each stream name, we validate it to ensure it meets our requirements for a proper stream name: that is, that it is shorter than Stream.MAX_NAME_LENGTH characters and passes valid_stream_name. This function in autocreate mode should be atomic: either an exception will be raised during a precheck, or all the streams specified will have been created if applicable. @param streams_raw The list of stream names to process @param user_profile The user for whom we are retreiving the streams @param autocreate Whether we should create streams if they don't already exist @param invite_only Whether newly created streams should have the invite_only bit set """ existing_streams = [] created_streams = [] # Validate all streams, getting extant ones, then get-or-creating the rest. stream_set = set(stream_name.strip() for stream_name in streams_raw) rejects = [] for stream_name in stream_set: if len(stream_name) > Stream.MAX_NAME_LENGTH: raise JsonableError(_("Stream name (%s) too long.") % (stream_name,)) if not valid_stream_name(stream_name): raise JsonableError(_("Invalid stream name (%s).") % (stream_name,)) existing_stream_map = bulk_get_streams(user_profile.realm, stream_set) for stream_name in stream_set: stream = existing_stream_map.get(stream_name.lower()) if stream is None: rejects.append(stream_name) else: existing_streams.append(stream) if rejects: if not user_profile.can_create_streams(): raise JsonableError(_('User cannot create streams.')) elif not autocreate: raise JsonableError(_("Stream(s) (%s) do not exist") % ", ".join(rejects)) for stream_name in rejects: stream, created = create_stream_if_needed(user_profile.realm, stream_name, invite_only=invite_only) if created: created_streams.append(stream) else: # We already checked for existing streams above; this # next line is present to handle races where a stream # was created while this function was executing. existing_streams.append(stream) return existing_streams, created_streams
def subscribe_to_stream(self, email, stream_name, realm=None): # type: (Text, Text, Optional[Realm]) -> Stream if realm is None: realm = get_realm_by_email_domain(email) try: stream = get_stream(stream_name, realm) from_creation = False except Stream.DoesNotExist: stream, from_creation = create_stream_if_needed(realm, stream_name) user_profile = get_user_profile_by_email(email) bulk_add_subscriptions([stream], [user_profile], from_creation=from_creation) return stream
def test_slow_queries_worker(self) -> None: error_bot = get_system_bot(settings.ERROR_BOT) fake_client = self.FakeClient() worker = SlowQueryWorker() create_stream_if_needed(error_bot.realm, 'errors') send_mock = patch( 'zerver.worker.queue_processors.internal_send_stream_message') with send_mock as sm, loopworker_sleep_mock as tm: with simulated_queue_client(lambda: fake_client): try: worker.setup() # `write_log_line` is where we publish slow queries to the queue. with patch('zerver.middleware.is_slow_query', return_value=True): write_log_line(log_data=dict(test='data'), email='*****@*****.**', remote_ip='127.0.0.1', client_name='website', path='/test/', method='GET') worker.start() except AbortLoop: pass self.assertEqual(tm.call_args[0][0], 60) # should sleep 60 seconds sm.assert_called_once() args = [c[0] for c in sm.call_args_list][0] self.assertEqual(args[0], error_bot.realm) self.assertEqual(args[1].email, error_bot.email) self.assertEqual(args[2].name, "errors") self.assertEqual(args[3], "testserver: slow queries") # Testing for specific query times can lead to test discrepancies. logging_info = re.sub(r'\(db: [0-9]+ms/\d+q\)', '', args[4]) self.assertEqual( logging_info, ' 127.0.0.1 GET 200 -1000ms ' ' /test/ ([email protected] via website) ([email protected])\n')
def handle(self, *args: Any, **options: Any) -> None: realm = self.get_realm(options) assert realm is not None # Should be ensured by parser streams = [] # type: List[Stream] if options["streams"]: stream_names = set([stream.strip() for stream in options["streams"].split(",")]) for stream_name in set(stream_names): stream, _ = create_stream_if_needed(realm, stream_name) streams.append(stream) referred_by = self.get_user(options['referred_by'], realm) invite_link = do_create_multiuse_invite_link(referred_by, streams) print("You can use %s to invite as many number of people to the organization." % (invite_link,))
def handle(self, **options: Any) -> None: realm = self.get_realm(options) assert realm is not None # Should be ensured by parser user_profiles = self.get_users(options, realm) stream_names = set([stream.strip() for stream in options["streams"].split(",")]) for stream_name in set(stream_names): for user_profile in user_profiles: stream, _ = create_stream_if_needed(realm, stream_name) _ignore, already_subscribed = bulk_add_subscriptions([stream], [user_profile]) was_there_already = user_profile.id in {tup[0].id for tup in already_subscribed} print("%s %s to %s" % ( "Already subscribed" if was_there_already else "Subscribed", user_profile.email, stream_name))
def test_invite_with_non_ascii_streams(self): """ Inviting someone to streams with non-ASCII characters succeeds. """ self.login("*****@*****.**") invitee = "*****@*****.**" stream_name = u"hümbüǵ" realm = get_realm("zulip.com") stream, _ = create_stream_if_needed(realm, stream_name) # Make sure we're subscribed before inviting someone. do_add_subscription(get_user_profile_by_email("*****@*****.**"), stream, no_log=True) self.assert_json_success(self.invite(invitee, [stream_name]))
def test_invite_with_non_ascii_streams(self): """ Inviting someone to streams with non-ASCII characters succeeds. """ self.login("*****@*****.**") invitee = "*****@*****.**" stream_name = u"hümbüǵ" realm = get_realm("zulip.com") stream, _ = create_stream_if_needed(realm, stream_name) # Make sure we're subscribed before inviting someone. do_add_subscription( get_user_profile_by_email("*****@*****.**"), stream, no_log=True) self.assert_json_success(self.invite(invitee, [stream_name]))
def handle(self, *args: Any, **options: Any) -> None: realm = self.get_realm(options) assert realm is not None # Should be ensured by parser streams = [] # type: List[Stream] if options["streams"]: stream_names = set( [stream.strip() for stream in options["streams"].split(",")]) for stream_name in set(stream_names): stream, _ = create_stream_if_needed(realm, stream_name) streams.append(stream) referred_by = self.get_user(options['referred_by'], realm) invite_link = do_create_multiuse_invite_link(referred_by, streams) print( "You can use %s to invite as many number of people to the organization." % (invite_link, ))
def handle(self, *args: Any, **options: Any) -> None: realm = self.get_realm(options) assert realm is not None # Should be ensured by parser streams = [] if options["streams"]: stream_names = set([stream.strip() for stream in options["streams"].split(",")]) for stream_name in set(stream_names): stream, _ = create_stream_if_needed(realm, stream_name) streams.append(stream) referred_by = self.get_user(options['referred_by'], realm) invite = MultiuseInvite.objects.create(realm=realm, referred_by=referred_by) if streams: invite.streams = streams invite.save() invite_link = create_confirmation_link(invite, realm.host, Confirmation.MULTIUSE_INVITE) print("You can use %s to invite as many number of people to the organization." % (invite_link,))
def setup_initial_private_stream(user): # type: (UserProfile) -> None stream, _ = create_stream_if_needed(user.realm, "core team", invite_only=True, stream_description="A private stream for core team members.") bulk_add_subscriptions([stream], [user])
def test_scrub_realm(self) -> None: zulip = get_realm("zulip") lear = get_realm("lear") iago = self.example_user("iago") othello = self.example_user("othello") cordelia = self.lear_user("cordelia") king = self.lear_user("king") create_stream_if_needed(lear, "Shakespeare") self.subscribe(cordelia, "Shakespeare") self.subscribe(king, "Shakespeare") Message.objects.all().delete() UserMessage.objects.all().delete() for i in range(5): self.send_stream_message(iago, "Scotland") self.send_stream_message(othello, "Scotland") self.send_stream_message(cordelia, "Shakespeare") self.send_stream_message(king, "Shakespeare") Attachment.objects.filter(realm=zulip).delete() Attachment.objects.create(realm=zulip, owner=iago, path_id="a/b/temp1.txt") Attachment.objects.create(realm=zulip, owner=othello, path_id="a/b/temp2.txt") Attachment.objects.filter(realm=lear).delete() Attachment.objects.create(realm=lear, owner=cordelia, path_id="c/d/temp1.txt") Attachment.objects.create(realm=lear, owner=king, path_id="c/d/temp2.txt") CustomProfileField.objects.create(realm=lear) self.assertEqual( Message.objects.filter(sender__in=[iago, othello]).count(), 10) self.assertEqual( Message.objects.filter(sender__in=[cordelia, king]).count(), 10) self.assertEqual( UserMessage.objects.filter( user_profile__in=[iago, othello]).count(), 20) self.assertEqual( UserMessage.objects.filter( user_profile__in=[cordelia, king]).count(), 20) self.assertNotEqual( CustomProfileField.objects.filter(realm=zulip).count(), 0) with mock.patch('logging.warning'): do_scrub_realm(zulip) self.assertEqual( Message.objects.filter(sender__in=[iago, othello]).count(), 0) self.assertEqual( Message.objects.filter(sender__in=[cordelia, king]).count(), 10) self.assertEqual( UserMessage.objects.filter( user_profile__in=[iago, othello]).count(), 0) self.assertEqual( UserMessage.objects.filter( user_profile__in=[cordelia, king]).count(), 20) self.assertEqual(Attachment.objects.filter(realm=zulip).count(), 0) self.assertEqual(Attachment.objects.filter(realm=lear).count(), 2) self.assertEqual( CustomProfileField.objects.filter(realm=zulip).count(), 0) self.assertNotEqual( CustomProfileField.objects.filter(realm=lear).count(), 0) zulip_users = UserProfile.objects.filter(realm=zulip) for user in zulip_users: self.assertTrue(re.search("Scrubbed [a-z0-9]{15}", user.full_name)) self.assertTrue( re.search("scrubbed-[a-z0-9]{15}@" + zulip.host, user.email)) self.assertTrue( re.search("scrubbed-[a-z0-9]{15}@" + zulip.host, user.delivery_email)) lear_users = UserProfile.objects.filter(realm=lear) for user in lear_users: self.assertIsNone( re.search("Scrubbed [a-z0-9]{15}", user.full_name)) self.assertIsNone( re.search("scrubbed-[a-z0-9]{15}@" + zulip.host, user.email)) self.assertIsNone( re.search("scrubbed-[a-z0-9]{15}@" + zulip.host, user.delivery_email))
def subscribe_to_stream(self, email, stream_name, realm=None): realm = Realm.objects.get(domain=resolve_email_to_domain(email)) stream, _ = create_stream_if_needed(realm, stream_name) user_profile = get_user_profile_by_email(email) do_add_subscription(user_profile, stream, no_log=True)
def handle(self, *args: Any, **options: str) -> None: realm = self.get_realm(options) assert realm is not None # Should be ensured by parser stream_name = options['stream_name'] create_stream_if_needed(realm, stream_name)
def handle(self, *args, **options): # type: (*Any, **str) -> None realm = self.get_realm(options) encoding = sys.getfilesystemencoding() stream_name = options['stream_name'] create_stream_if_needed(realm, force_text(stream_name, encoding))
def add_message_formatting_conversation(self) -> None: realm = get_realm('zulip') stream, _ = create_stream_if_needed(realm, 'zulip features') UserProfile.objects.filter(email__contains='stage').delete() starr = do_create_user('*****@*****.**', 'password', realm, 'Ada Starr', '') self.set_avatar(starr, 'static/images/features/starr.png') fisher = do_create_user('*****@*****.**', 'password', realm, 'Bel Fisher', '') self.set_avatar(fisher, 'static/images/features/fisher.png') twitter_bot = do_create_user('*****@*****.**', 'password', realm, 'Twitter Bot', '', bot_type=UserProfile.DEFAULT_BOT) self.set_avatar(twitter_bot, 'static/images/features/twitter.png') bulk_add_subscriptions([stream], list(UserProfile.objects.filter(realm=realm))) staged_messages = [ {'sender': starr, 'content': "Hey @**Bel Fisher**, check out Zulip's Markdown formatting! " "You can have:\n* bulleted lists\n * with sub-bullets too\n" "* **bold**, *italic*, and ~~strikethrough~~ text\n" "* LaTeX for mathematical formulas, both inline -- $$O(n^2)$$ -- and displayed:\n" "```math\n\\int_a^b f(t)\, dt=F(b)-F(a)\n```"}, {'sender': fisher, 'content': "My favorite is the syntax highlighting for code blocks\n" "```python\ndef fib(n: int) -> int:\n # returns the n-th Fibonacci number\n" " return fib(n-1) + fib(n-2)\n```"}, {'sender': starr, 'content': "I think you forgot your base case there, Bel :laughing:\n" "```quote\n```python\ndef fib(n: int) -> int:\n # returns the n-th Fibonacci number\n" " return fib(n-1) + fib(n-2)\n```\n```"}, {'sender': fisher, 'content': "I'm also a big fan of inline link, tweet, video, and image previews. " "Check out this picture of Çet Whalin[](/static/images/features/whale.png)!"}, {'sender': starr, 'content': "I just set up a custom linkifier, " "so `#1234` becomes [#1234](github.com/zulip/zulip/1234), " "a link to the corresponding GitHub issue."}, {'sender': twitter_bot, 'content': 'https://twitter.com/gvanrossum/status/786661035637772288'}, {'sender': fisher, 'content': "Oops, the Twitter bot I set up shouldn't be posting here. Let me go fix that."}, ] # type: List[Dict[str, Any]] messages = [internal_prep_stream_message( realm, message['sender'], stream.name, 'message formatting', message['content'] ) for message in staged_messages] message_ids = do_send_messages(messages) preview_message = Message.objects.get(id__in=message_ids, content__icontains='image previews') do_add_reaction_legacy(starr, preview_message, 'whale') twitter_message = Message.objects.get(id__in=message_ids, content__icontains='gvanrossum') # Setting up a twitter integration in dev is a decent amount of work. If you need # to update this tweet, either copy the format below, or send the link to the tweet # to chat.zulip.org and ask an admin of that server to get you the rendered_content. twitter_message.rendered_content = ( '<p><a>https://twitter.com/gvanrossum/status/786661035637772288</a></p>\n' '<div class="inline-preview-twitter"><div class="twitter-tweet">' '<a><img class="twitter-avatar" ' 'src="https://pbs.twimg.com/profile_images/424495004/GuidoAvatar_bigger.jpg"></a>' '<p>Great blog post about Zulip\'s use of mypy: ' '<a>http://blog.zulip.org/2016/10/13/static-types-in-python-oh-mypy/</a></p>' '<span>- Guido van Rossum (@gvanrossum)</span></div></div>') twitter_message.save(update_fields=['rendered_content']) # Put a short pause between the whale reaction and this, so that the # thumbs_up shows up second do_add_reaction_legacy(starr, preview_message, 'thumbs_up')
def add_message_formatting_conversation(self) -> None: realm = get_realm('zulip') stream, _ = create_stream_if_needed(realm, 'zulip features') UserProfile.objects.filter(email__contains='stage').delete() starr = do_create_user('*****@*****.**', 'password', realm, 'Ada Starr', '') self.set_avatar(starr, 'static/images/features/starr.png') fisher = do_create_user('*****@*****.**', 'password', realm, 'Bel Fisher', '') self.set_avatar(fisher, 'static/images/features/fisher.png') twitter_bot = do_create_user('*****@*****.**', 'password', realm, 'Twitter Bot', '', bot_type=UserProfile.DEFAULT_BOT) self.set_avatar(twitter_bot, 'static/images/features/twitter.png') bulk_add_subscriptions([stream], list(UserProfile.objects.filter(realm=realm))) staged_messages = [ { 'sender': starr, 'content': "Hey @**Bel Fisher**, check out Zulip's Markdown formatting! " "You can have:\n* bulleted lists\n * with sub-bullets too\n" "* **bold**, *italic*, and ~~strikethrough~~ text\n" "* LaTeX for mathematical formulas, both inline -- $$O(n^2)$$ -- and displayed:\n" "```math\n\\int_a^b f(t)\, dt=F(b)-F(a)\n```" }, { 'sender': fisher, 'content': "My favorite is the syntax highlighting for code blocks\n" "```python\ndef fib(n):\n # returns the n-th Fibonacci number\n" " return fib(n-1) + fib(n-2)\n```" }, { 'sender': starr, 'content': "I think you forgot your base case there, Bel :laughing:\n" "```quote\n```python\ndef fib(n):\n # returns the n-th Fibonacci number\n" " return fib(n-1) + fib(n-2)\n```\n```" }, { 'sender': fisher, 'content': "I'm also a big fan of inline link, tweet, video, and image previews. " "Check out this picture of Çet Whalin[](/static/images/features/whale.png)!" }, { 'sender': starr, 'content': "I just set up a custom linkifier, " "so `#1234` becomes [#1234](github.com/zulip/zulip/1234), " "a link to the corresponding GitHub issue." }, { 'sender': twitter_bot, 'content': 'https://twitter.com/gvanrossum/status/786661035637772288' }, { 'sender': fisher, 'content': "Oops, the Twitter bot I set up shouldn't be posting here. Let me go fix that." }, ] # type: List[Dict[str, Any]] messages = [ internal_prep_stream_message(realm, message['sender'], stream.name, 'message formatting', message['content']) for message in staged_messages ] message_ids = do_send_messages(messages) preview_message = Message.objects.get( id__in=message_ids, content__icontains='image previews') do_add_reaction_legacy(starr, preview_message, 'whale') twitter_message = Message.objects.get(id__in=message_ids, content__icontains='gvanrossum') # Setting up a twitter integration in dev is a decent amount of work. If you need # to update this tweet, either copy the format below, or send the link to the tweet # to chat.zulip.org and ask an admin of that server to get you the rendered_content. twitter_message.rendered_content = ( '<p><a>https://twitter.com/gvanrossum/status/786661035637772288</a></p>\n' '<div class="inline-preview-twitter"><div class="twitter-tweet">' '<a><img class="twitter-avatar" ' 'src="https://pbs.twimg.com/profile_images/424495004/GuidoAvatar_bigger.jpg"></a>' '<p>Great blog post about Zulip\'s use of mypy: ' '<a>http://blog.zulip.org/2016/10/13/static-types-in-python-oh-mypy/</a></p>' '<span>- Guido van Rossum (@gvanrossum)</span></div></div>') twitter_message.save(update_fields=['rendered_content']) # Put a short pause between the whale reaction and this, so that the # thumbs_up shows up second do_add_reaction_legacy(starr, preview_message, 'thumbs_up')
def test_export_realm_with_member_consent(self) -> None: realm = Realm.objects.get(string_id='zulip') # Create private streams and subscribe users for testing export create_stream_if_needed(realm, "Private A", invite_only=True) self.subscribe(self.example_user("iago"), "Private A") self.subscribe(self.example_user("othello"), "Private A") self.send_stream_message(self.example_email("iago"), "Private A", "Hello Stream A") create_stream_if_needed(realm, "Private B", invite_only=True) self.subscribe(self.example_user("prospero"), "Private B") stream_b_message_id = self.send_stream_message( self.example_email("prospero"), "Private B", "Hello Stream B") self.subscribe(self.example_user("hamlet"), "Private B") create_stream_if_needed(realm, "Private C", invite_only=True) self.subscribe(self.example_user("othello"), "Private C") self.subscribe(self.example_user("prospero"), "Private C") stream_c_message_id = self.send_stream_message( self.example_email("othello"), "Private C", "Hello Stream C") # Create huddles self.send_huddle_message( self.example_email("iago"), [self.example_email("cordelia"), self.example_email("AARON")]) huddle_a = Huddle.objects.last() self.send_huddle_message(self.example_email("ZOE"), [ self.example_email("hamlet"), self.example_email("AARON"), self.example_email("othello") ]) huddle_b = Huddle.objects.last() huddle_c_message_id = self.send_huddle_message( self.example_email("AARON"), [ self.example_email("cordelia"), self.example_email("ZOE"), self.example_email("othello") ]) # Create PMs pm_a_msg_id = self.send_personal_message(self.example_email("AARON"), self.example_email("othello")) pm_b_msg_id = self.send_personal_message( self.example_email("cordelia"), self.example_email("iago")) pm_c_msg_id = self.send_personal_message(self.example_email("hamlet"), self.example_email("othello")) pm_d_msg_id = self.send_personal_message(self.example_email("iago"), self.example_email("hamlet")) # Send message advertising export and make users react self.send_stream_message(self.example_email("othello"), "Verona", topic_name="Export", content="Thumbs up for export") message = Message.objects.last() consented_user_ids = [ self.example_user(user).id for user in ["iago", "hamlet"] ] do_add_reaction(self.example_user("iago"), message, "+1", "1f44d", Reaction.UNICODE_EMOJI) do_add_reaction(self.example_user("hamlet"), message, "+1", "1f44d", Reaction.UNICODE_EMOJI) realm_emoji = RealmEmoji.objects.get(realm=realm) realm_emoji.delete() full_data = self._export_realm(realm, consent_message_id=message.id) realm_emoji.save() data = full_data['realm'] self.assertEqual(len(data['zerver_userprofile_crossrealm']), 0) self.assertEqual(len(data['zerver_userprofile_mirrordummy']), 0) exported_user_emails = self.get_set(data['zerver_userprofile'], 'email') self.assertIn(self.example_email('cordelia'), exported_user_emails) self.assertIn(self.example_email('hamlet'), exported_user_emails) self.assertIn(self.example_email('iago'), exported_user_emails) self.assertIn(self.example_email('othello'), exported_user_emails) self.assertIn('*****@*****.**', exported_user_emails) self.assertIn('*****@*****.**', exported_user_emails) exported_streams = self.get_set(data['zerver_stream'], 'name') self.assertEqual( exported_streams, set([ u'Denmark', u'Rome', u'Scotland', u'Venice', u'Verona', u'Private A', u'Private B', u'Private C' ])) data = full_data['message'] exported_usermessages = UserMessage.objects.filter(user_profile__in=[ self.example_user("iago"), self.example_user("hamlet") ]) um = exported_usermessages[0] self.assertEqual(len(data["zerver_usermessage"]), len(exported_usermessages)) exported_um = self.find_by_id(data['zerver_usermessage'], um.id) self.assertEqual(exported_um['message'], um.message_id) self.assertEqual(exported_um['user_profile'], um.user_profile_id) exported_message = self.find_by_id(data['zerver_message'], um.message_id) self.assertEqual(exported_message['content'], um.message.content) public_stream_names = [ 'Denmark', 'Rome', 'Scotland', 'Venice', 'Verona' ] public_stream_ids = Stream.objects.filter( name__in=public_stream_names).values_list("id", flat=True) public_stream_recipients = Recipient.objects.filter( type_id__in=public_stream_ids, type=Recipient.STREAM) public_stream_message_ids = Message.objects.filter( recipient__in=public_stream_recipients).values_list("id", flat=True) # Messages from Private Stream C are not exported since no member gave consent private_stream_ids = Stream.objects.filter( name__in=["Private A", "Private B"]).values_list("id", flat=True) private_stream_recipients = Recipient.objects.filter( type_id__in=private_stream_ids, type=Recipient.STREAM) private_stream_message_ids = Message.objects.filter( recipient__in=private_stream_recipients).values_list("id", flat=True) pm_recipients = Recipient.objects.filter( type_id__in=consented_user_ids, type=Recipient.PERSONAL) pm_query = Q(recipient__in=pm_recipients) | Q( sender__in=consented_user_ids) exported_pm_ids = Message.objects.filter(pm_query).values_list( "id", flat=True).values_list("id", flat=True) # Third huddle is not exported since none of the members gave consent huddle_recipients = Recipient.objects.filter( type_id__in=[huddle_a.id, huddle_b.id], type=Recipient.HUDDLE) pm_query = Q(recipient__in=huddle_recipients) | Q( sender__in=consented_user_ids) exported_huddle_ids = Message.objects.filter(pm_query).values_list( "id", flat=True).values_list("id", flat=True) exported_msg_ids = set(public_stream_message_ids) | set(private_stream_message_ids) \ | set(exported_pm_ids) | set(exported_huddle_ids) self.assertEqual(self.get_set(data["zerver_message"], "id"), exported_msg_ids) # TODO: This behavior is wrong and should be fixed. The message should not be exported # since it was sent before the only consented user iago joined the stream. self.assertIn(stream_b_message_id, exported_msg_ids) self.assertNotIn(stream_c_message_id, exported_msg_ids) self.assertNotIn(huddle_c_message_id, exported_msg_ids) self.assertNotIn(pm_a_msg_id, exported_msg_ids) self.assertIn(pm_b_msg_id, exported_msg_ids) self.assertIn(pm_c_msg_id, exported_msg_ids) self.assertIn(pm_d_msg_id, exported_msg_ids)
def test_scrub_realm(self) -> None: zulip = get_realm("zulip") lear = get_realm("lear") iago = self.example_user("iago") othello = self.example_user("othello") cordelia = self.lear_user("cordelia") king = self.lear_user("king") create_stream_if_needed(lear, "Shakespeare") self.subscribe(cordelia, "Shakespeare") self.subscribe(king, "Shakespeare") Message.objects.all().delete() UserMessage.objects.all().delete() for i in range(5): self.send_stream_message(iago.email, "Scotland") self.send_stream_message(othello.email, "Scotland") self.send_stream_message(cordelia.email, "Shakespeare", sender_realm="lear") self.send_stream_message(king.email, "Shakespeare", sender_realm="lear") Attachment.objects.filter(realm=zulip).delete() Attachment.objects.create(realm=zulip, owner=iago, path_id="a/b/temp1.txt") Attachment.objects.create(realm=zulip, owner=othello, path_id="a/b/temp2.txt") Attachment.objects.filter(realm=lear).delete() Attachment.objects.create(realm=lear, owner=cordelia, path_id="c/d/temp1.txt") Attachment.objects.create(realm=lear, owner=king, path_id="c/d/temp2.txt") CustomProfileField.objects.create(realm=lear) self.assertEqual(Message.objects.filter(sender__in=[iago, othello]).count(), 10) self.assertEqual(Message.objects.filter(sender__in=[cordelia, king]).count(), 10) self.assertEqual(UserMessage.objects.filter(user_profile__in=[iago, othello]).count(), 20) self.assertEqual(UserMessage.objects.filter(user_profile__in=[cordelia, king]).count(), 20) self.assertNotEqual(CustomProfileField.objects.filter(realm=zulip).count(), 0) with mock.patch('logging.warning'): do_scrub_realm(zulip) self.assertEqual(Message.objects.filter(sender__in=[iago, othello]).count(), 0) self.assertEqual(Message.objects.filter(sender__in=[cordelia, king]).count(), 10) self.assertEqual(UserMessage.objects.filter(user_profile__in=[iago, othello]).count(), 0) self.assertEqual(UserMessage.objects.filter(user_profile__in=[cordelia, king]).count(), 20) self.assertEqual(Attachment.objects.filter(realm=zulip).count(), 0) self.assertEqual(Attachment.objects.filter(realm=lear).count(), 2) self.assertEqual(CustomProfileField.objects.filter(realm=zulip).count(), 0) self.assertNotEqual(CustomProfileField.objects.filter(realm=lear).count(), 0) zulip_users = UserProfile.objects.filter(realm=zulip) for user in zulip_users: self.assertTrue(re.search("Scrubbed [a-z0-9]{15}", user.full_name)) self.assertTrue(re.search("scrubbed-[a-z0-9]{15}@" + zulip.host, user.email)) self.assertTrue(re.search("scrubbed-[a-z0-9]{15}@" + zulip.host, user.delivery_email)) lear_users = UserProfile.objects.filter(realm=lear) for user in lear_users: self.assertIsNone(re.search("Scrubbed [a-z0-9]{15}", user.full_name)) self.assertIsNone(re.search("scrubbed-[a-z0-9]{15}@" + zulip.host, user.email)) self.assertIsNone(re.search("scrubbed-[a-z0-9]{15}@" + zulip.host, user.delivery_email))