def make_stream(self, stream_name: str, realm: Optional[Realm]=None, invite_only: Optional[bool]=False, history_public_to_subscribers: Optional[bool]=None) -> Stream: if realm is None: realm = get_realm('zulip') history_public_to_subscribers = get_default_value_for_history_public_to_subscribers( realm, invite_only, history_public_to_subscribers) try: stream = Stream.objects.create( realm=realm, name=stream_name, invite_only=invite_only, history_public_to_subscribers=history_public_to_subscribers, ) except IntegrityError: # nocoverage -- this is for bugs in the tests raise Exception(''' %s already exists Please call make_stream with a stream name that is not already in use.''' % (stream_name,)) recipient = Recipient.objects.create(type_id=stream.id, type=Recipient.STREAM) stream.recipient = recipient stream.save(update_fields=["recipient"]) return stream
def do_change_stream_permission( stream: Stream, *, invite_only: Optional[bool] = None, history_public_to_subscribers: Optional[bool] = None, is_web_public: Optional[bool] = None, acting_user: UserProfile, ) -> None: old_invite_only_value = stream.invite_only old_history_public_to_subscribers_value = stream.history_public_to_subscribers old_is_web_public_value = stream.is_web_public # A note on these assertions: It's possible we'd be better off # making all callers of this function pass the full set of # parameters, rather than having default values. Doing so would # allow us to remove the messy logic below, where we sometimes # ignore the passed parameters. # # But absent such a refactoring, it's important to assert that # we're not requesting an unsupported configurations. if is_web_public: assert history_public_to_subscribers is not False assert invite_only is not True stream.is_web_public = True stream.invite_only = False stream.history_public_to_subscribers = True else: assert invite_only is not None # is_web_public is falsey history_public_to_subscribers = get_default_value_for_history_public_to_subscribers( stream.realm, invite_only, history_public_to_subscribers, ) stream.invite_only = invite_only stream.history_public_to_subscribers = history_public_to_subscribers stream.is_web_public = False with transaction.atomic(): stream.save(update_fields=["invite_only", "history_public_to_subscribers", "is_web_public"]) event_time = timezone_now() if old_invite_only_value != stream.invite_only: # Reset the Attachment.is_realm_public cache for all # messages in the stream whose permissions were changed. Attachment.objects.filter(messages__recipient_id=stream.recipient_id).update( is_realm_public=None ) # We need to do the same for ArchivedAttachment to avoid # bugs if deleted attachments are later restored. ArchivedAttachment.objects.filter(messages__recipient_id=stream.recipient_id).update( is_realm_public=None ) RealmAuditLog.objects.create( realm=stream.realm, acting_user=acting_user, modified_stream=stream, event_type=RealmAuditLog.STREAM_PROPERTY_CHANGED, event_time=event_time, extra_data=orjson.dumps( { RealmAuditLog.OLD_VALUE: old_invite_only_value, RealmAuditLog.NEW_VALUE: stream.invite_only, "property": "invite_only", } ).decode(), ) if old_history_public_to_subscribers_value != stream.history_public_to_subscribers: RealmAuditLog.objects.create( realm=stream.realm, acting_user=acting_user, modified_stream=stream, event_type=RealmAuditLog.STREAM_PROPERTY_CHANGED, event_time=event_time, extra_data=orjson.dumps( { RealmAuditLog.OLD_VALUE: old_history_public_to_subscribers_value, RealmAuditLog.NEW_VALUE: stream.history_public_to_subscribers, "property": "history_public_to_subscribers", } ).decode(), ) if old_is_web_public_value != stream.is_web_public: # Reset the Attachment.is_realm_public cache for all # messages in the stream whose permissions were changed. Attachment.objects.filter(messages__recipient_id=stream.recipient_id).update( is_web_public=None ) # We need to do the same for ArchivedAttachment to avoid # bugs if deleted attachments are later restored. ArchivedAttachment.objects.filter(messages__recipient_id=stream.recipient_id).update( is_web_public=None ) RealmAuditLog.objects.create( realm=stream.realm, acting_user=acting_user, modified_stream=stream, event_type=RealmAuditLog.STREAM_PROPERTY_CHANGED, event_time=event_time, extra_data=orjson.dumps( { RealmAuditLog.OLD_VALUE: old_is_web_public_value, RealmAuditLog.NEW_VALUE: stream.is_web_public, "property": "is_web_public", } ).decode(), ) event = dict( op="update", type="stream", property="invite_only", value=stream.invite_only, history_public_to_subscribers=stream.history_public_to_subscribers, is_web_public=stream.is_web_public, stream_id=stream.id, name=stream.name, ) send_event(stream.realm, event, can_access_stream_user_ids(stream)) old_policy_name = get_stream_permission_policy_name( invite_only=old_invite_only_value, history_public_to_subscribers=old_history_public_to_subscribers_value, is_web_public=old_is_web_public_value, ) new_policy_name = get_stream_permission_policy_name( invite_only=stream.invite_only, history_public_to_subscribers=stream.history_public_to_subscribers, is_web_public=stream.is_web_public, ) send_change_stream_permission_notification( stream, old_policy_name=old_policy_name, new_policy_name=new_policy_name, acting_user=acting_user, )