def build_zerver_realm(realm_id: int, realm_subdomain: str, time: float, other_product: str) -> List[ZerverFieldsT]: realm = Realm(id=realm_id, date_created=time, name=realm_subdomain, string_id=realm_subdomain, description="Organization imported from %s!" % (other_product, )) auth_methods = [[flag[0], flag[1]] for flag in realm.authentication_methods] realm_dict = model_to_dict(realm, exclude='authentication_methods') realm_dict['authentication_methods'] = auth_methods return [realm_dict]
def do_import_realm(import_dir: Path, subdomain: str) -> Realm: logging.info("Importing realm dump %s" % (import_dir, )) if not os.path.exists(import_dir): raise Exception("Missing import directory!") realm_data_filename = os.path.join(import_dir, "realm.json") if not os.path.exists(realm_data_filename): raise Exception("Missing realm.json file!") logging.info("Importing realm data from %s" % (realm_data_filename, )) with open(realm_data_filename) as f: data = ujson.load(f) update_model_ids(Stream, data, 'zerver_stream', 'stream') re_map_foreign_keys(data, 'zerver_realm', 'notifications_stream', related_table="stream") fix_datetime_fields(data, 'zerver_realm') # Fix realm subdomain information data['zerver_realm'][0]['string_id'] = subdomain data['zerver_realm'][0]['name'] = subdomain fix_realm_authentication_bitfield(data, 'zerver_realm', 'authentication_methods') update_model_ids(Realm, data, 'zerver_realm', 'realm') realm = Realm(**data['zerver_realm'][0]) if realm.notifications_stream_id is not None: notifications_stream_id = int( realm.notifications_stream_id) # type: Optional[int] else: notifications_stream_id = None realm.notifications_stream_id = None realm.save() bulk_import_client(data, Client, 'zerver_client') # Email tokens will automatically be randomly generated when the # Stream objects are created by Django. fix_datetime_fields(data, 'zerver_stream') re_map_foreign_keys(data, 'zerver_stream', 'realm', related_table="realm") bulk_import_model(data, Stream, 'zerver_stream') realm.notifications_stream_id = notifications_stream_id realm.save() re_map_foreign_keys(data, 'zerver_defaultstream', 'stream', related_table="stream") re_map_foreign_keys(data, 'zerver_realmemoji', 'author', related_table="user_profile") for (table, model, related_table) in realm_tables: re_map_foreign_keys(data, table, 'realm', related_table="realm") update_model_ids(model, data, table, related_table) bulk_import_model(data, model, table) # Remap the user IDs for notification_bot and friends to their # appropriate IDs on this server for item in data['zerver_userprofile_crossrealm']: logging.info("Adding to ID map: %s %s" % (item['id'], get_system_bot(item['email']).id)) new_user_id = get_system_bot(item['email']).id update_id_map(table='user_profile', old_id=item['id'], new_id=new_user_id) # Merge in zerver_userprofile_mirrordummy data['zerver_userprofile'] = data['zerver_userprofile'] + data[ 'zerver_userprofile_mirrordummy'] del data['zerver_userprofile_mirrordummy'] data['zerver_userprofile'].sort(key=lambda r: r['id']) # To remap foreign key for UserProfile.last_active_message_id update_message_foreign_keys(import_dir) fix_datetime_fields(data, 'zerver_userprofile') update_model_ids(UserProfile, data, 'zerver_userprofile', 'user_profile') re_map_foreign_keys(data, 'zerver_userprofile', 'realm', related_table="realm") re_map_foreign_keys(data, 'zerver_userprofile', 'bot_owner', related_table="user_profile") re_map_foreign_keys(data, 'zerver_userprofile', 'default_sending_stream', related_table="stream") re_map_foreign_keys(data, 'zerver_userprofile', 'default_events_register_stream', related_table="stream") re_map_foreign_keys(data, 'zerver_userprofile', 'last_active_message_id', related_table="message", id_field=True) for user_profile_dict in data['zerver_userprofile']: user_profile_dict['password'] = None user_profile_dict['api_key'] = random_api_key() # Since Zulip doesn't use these permissions, drop them del user_profile_dict['user_permissions'] del user_profile_dict['groups'] user_profiles = [ UserProfile(**item) for item in data['zerver_userprofile'] ] for user_profile in user_profiles: user_profile.set_unusable_password() UserProfile.objects.bulk_create(user_profiles) if 'zerver_huddle' in data: bulk_import_model(data, Huddle, 'zerver_huddle') re_map_foreign_keys(data, 'zerver_recipient', 'type_id', related_table="stream", recipient_field=True, id_field=True) re_map_foreign_keys(data, 'zerver_recipient', 'type_id', related_table="user_profile", recipient_field=True, id_field=True) update_model_ids(Recipient, data, 'zerver_recipient', 'recipient') bulk_import_model(data, Recipient, 'zerver_recipient') re_map_foreign_keys(data, 'zerver_subscription', 'user_profile', related_table="user_profile") re_map_foreign_keys(data, 'zerver_subscription', 'recipient', related_table="recipient") update_model_ids(Subscription, data, 'zerver_subscription', 'subscription') bulk_import_model(data, Subscription, 'zerver_subscription') fix_datetime_fields(data, 'zerver_userpresence') re_map_foreign_keys(data, 'zerver_userpresence', 'user_profile', related_table="user_profile") re_map_foreign_keys(data, 'zerver_userpresence', 'client', related_table='client') update_model_ids(UserPresence, data, 'zerver_userpresence', 'user_presence') bulk_import_model(data, UserPresence, 'zerver_userpresence') fix_datetime_fields(data, 'zerver_useractivity') re_map_foreign_keys(data, 'zerver_useractivity', 'user_profile', related_table="user_profile") re_map_foreign_keys(data, 'zerver_useractivity', 'client', related_table='client') update_model_ids(UserActivity, data, 'zerver_useractivity', 'useractivity') bulk_import_model(data, UserActivity, 'zerver_useractivity') fix_datetime_fields(data, 'zerver_useractivityinterval') re_map_foreign_keys(data, 'zerver_useractivityinterval', 'user_profile', related_table="user_profile") update_model_ids(UserActivityInterval, data, 'zerver_useractivityinterval', 'useractivityinterval') bulk_import_model(data, UserActivityInterval, 'zerver_useractivityinterval') if 'zerver_customprofilefield' in data: # As the export of Custom Profile fields is not supported, Zulip exported # data would not contain this field. # However this is supported in slack importer script re_map_foreign_keys(data, 'zerver_customprofilefield', 'realm', related_table="realm") update_model_ids(CustomProfileField, data, 'zerver_customprofilefield', related_table="customprofilefield") bulk_import_model(data, CustomProfileField, 'zerver_customprofilefield') re_map_foreign_keys(data, 'zerver_customprofilefield_value', 'user_profile', related_table="user_profile") re_map_foreign_keys(data, 'zerver_customprofilefield_value', 'field', related_table="customprofilefield") update_model_ids(CustomProfileFieldValue, data, 'zerver_customprofilefield_value', related_table="customprofilefield_value") bulk_import_model(data, CustomProfileFieldValue, 'zerver_customprofilefield_value') # Import uploaded files and avatars import_uploads(os.path.join(import_dir, "avatars"), processing_avatars=True) import_uploads(os.path.join(import_dir, "uploads")) # We need to have this check as the emoji files are only present in the data # importer from slack # For Zulip export, this doesn't exist if os.path.exists(os.path.join(import_dir, "emoji")): import_uploads(os.path.join(import_dir, "emoji"), processing_emojis=True) # Import zerver_message and zerver_usermessage import_message_data(import_dir) # Do attachments AFTER message data is loaded. # TODO: de-dup how we read these json files. fn = os.path.join(import_dir, "attachment.json") if not os.path.exists(fn): raise Exception("Missing attachment.json file!") logging.info("Importing attachment data from %s" % (fn, )) with open(fn) as f: data = ujson.load(f) import_attachments(data) return realm
def do_import_realm(import_dir: Path, subdomain: str) -> Realm: logging.info("Importing realm dump %s" % (import_dir,)) if not os.path.exists(import_dir): raise Exception("Missing import directory!") realm_data_filename = os.path.join(import_dir, "realm.json") if not os.path.exists(realm_data_filename): raise Exception("Missing realm.json file!") logging.info("Importing realm data from %s" % (realm_data_filename,)) with open(realm_data_filename) as f: data = ujson.load(f) bulk_import_client(data, Client, 'zerver_client') # We don't import the Stream model yet, since it depends on Realm, # which isn't imported yet. But we need the Stream model IDs for # notifications_stream. update_model_ids(Stream, data, 'stream') re_map_foreign_keys(data, 'zerver_realm', 'notifications_stream', related_table="stream") re_map_foreign_keys(data, 'zerver_realm', 'signup_notifications_stream', related_table="stream") fix_datetime_fields(data, 'zerver_realm') # Fix realm subdomain information data['zerver_realm'][0]['string_id'] = subdomain data['zerver_realm'][0]['name'] = subdomain fix_realm_authentication_bitfield(data, 'zerver_realm', 'authentication_methods') update_model_ids(Realm, data, 'realm') realm = Realm(**data['zerver_realm'][0]) if settings.BILLING_ENABLED: realm.plan_type = Realm.LIMITED else: realm.plan_type = Realm.SELF_HOSTED if realm.notifications_stream_id is not None: notifications_stream_id = int(realm.notifications_stream_id) # type: Optional[int] else: notifications_stream_id = None realm.notifications_stream_id = None if realm.signup_notifications_stream_id is not None: signup_notifications_stream_id = int(realm.signup_notifications_stream_id) # type: Optional[int] else: signup_notifications_stream_id = None realm.signup_notifications_stream_id = None realm.save() # Email tokens will automatically be randomly generated when the # Stream objects are created by Django. fix_datetime_fields(data, 'zerver_stream') re_map_foreign_keys(data, 'zerver_stream', 'realm', related_table="realm") bulk_import_model(data, Stream) realm.notifications_stream_id = notifications_stream_id realm.signup_notifications_stream_id = signup_notifications_stream_id realm.save() # Remap the user IDs for notification_bot and friends to their # appropriate IDs on this server for item in data['zerver_userprofile_crossrealm']: logging.info("Adding to ID map: %s %s" % (item['id'], get_system_bot(item['email']).id)) new_user_id = get_system_bot(item['email']).id update_id_map(table='user_profile', old_id=item['id'], new_id=new_user_id) new_recipient_id = Recipient.objects.get(type=Recipient.PERSONAL, type_id=new_user_id).id update_id_map(table='recipient', old_id=item['recipient_id'], new_id=new_recipient_id) # Merge in zerver_userprofile_mirrordummy data['zerver_userprofile'] = data['zerver_userprofile'] + data['zerver_userprofile_mirrordummy'] del data['zerver_userprofile_mirrordummy'] data['zerver_userprofile'].sort(key=lambda r: r['id']) # To remap foreign key for UserProfile.last_active_message_id update_message_foreign_keys(import_dir) fix_datetime_fields(data, 'zerver_userprofile') update_model_ids(UserProfile, data, 'user_profile') re_map_foreign_keys(data, 'zerver_userprofile', 'realm', related_table="realm") re_map_foreign_keys(data, 'zerver_userprofile', 'bot_owner', related_table="user_profile") re_map_foreign_keys(data, 'zerver_userprofile', 'default_sending_stream', related_table="stream") re_map_foreign_keys(data, 'zerver_userprofile', 'default_events_register_stream', related_table="stream") re_map_foreign_keys(data, 'zerver_userprofile', 'last_active_message_id', related_table="message", id_field=True) for user_profile_dict in data['zerver_userprofile']: user_profile_dict['password'] = None user_profile_dict['api_key'] = generate_api_key() # Since Zulip doesn't use these permissions, drop them del user_profile_dict['user_permissions'] del user_profile_dict['groups'] user_profiles = [UserProfile(**item) for item in data['zerver_userprofile']] for user_profile in user_profiles: user_profile.set_unusable_password() UserProfile.objects.bulk_create(user_profiles) re_map_foreign_keys(data, 'zerver_defaultstream', 'stream', related_table="stream") re_map_foreign_keys(data, 'zerver_realmemoji', 'author', related_table="user_profile") for (table, model, related_table) in realm_tables: re_map_foreign_keys(data, table, 'realm', related_table="realm") update_model_ids(model, data, related_table) bulk_import_model(data, model) if 'zerver_huddle' in data: update_model_ids(Huddle, data, 'huddle') # We don't import Huddle yet, since we don't have the data to # compute huddle hashes until we've imported some of the # tables below. # TODO: double-check this. re_map_foreign_keys(data, 'zerver_recipient', 'type_id', related_table="stream", recipient_field=True, id_field=True) re_map_foreign_keys(data, 'zerver_recipient', 'type_id', related_table="user_profile", recipient_field=True, id_field=True) re_map_foreign_keys(data, 'zerver_recipient', 'type_id', related_table="huddle", recipient_field=True, id_field=True) update_model_ids(Recipient, data, 'recipient') bulk_import_model(data, Recipient) re_map_foreign_keys(data, 'zerver_subscription', 'user_profile', related_table="user_profile") get_huddles_from_subscription(data, 'zerver_subscription') re_map_foreign_keys(data, 'zerver_subscription', 'recipient', related_table="recipient") update_model_ids(Subscription, data, 'subscription') bulk_import_model(data, Subscription) if 'zerver_realmauditlog' in data: fix_datetime_fields(data, 'zerver_realmauditlog') re_map_foreign_keys(data, 'zerver_realmauditlog', 'realm', related_table="realm") re_map_foreign_keys(data, 'zerver_realmauditlog', 'modified_user', related_table='user_profile') re_map_foreign_keys(data, 'zerver_realmauditlog', 'acting_user', related_table='user_profile') re_map_foreign_keys(data, 'zerver_realmauditlog', 'modified_stream', related_table="stream") update_model_ids(RealmAuditLog, data, related_table="realmauditlog") bulk_import_model(data, RealmAuditLog) else: logging.info('about to call create_subscription_events') create_subscription_events( data=data, realm_id=realm.id, ) logging.info('done with create_subscription_events') if 'zerver_huddle' in data: process_huddle_hash(data, 'zerver_huddle') bulk_import_model(data, Huddle) if 'zerver_userhotspot' in data: fix_datetime_fields(data, 'zerver_userhotspot') re_map_foreign_keys(data, 'zerver_userhotspot', 'user', related_table='user_profile') update_model_ids(UserHotspot, data, 'userhotspot') bulk_import_model(data, UserHotspot) if 'zerver_mutedtopic' in data: re_map_foreign_keys(data, 'zerver_mutedtopic', 'user_profile', related_table='user_profile') re_map_foreign_keys(data, 'zerver_mutedtopic', 'stream', related_table='stream') re_map_foreign_keys(data, 'zerver_mutedtopic', 'recipient', related_table='recipient') update_model_ids(MutedTopic, data, 'mutedtopic') bulk_import_model(data, MutedTopic) if 'zerver_service' in data: re_map_foreign_keys(data, 'zerver_service', 'user_profile', related_table='user_profile') fix_service_tokens(data, 'zerver_service') update_model_ids(Service, data, 'service') bulk_import_model(data, Service) if 'zerver_usergroup' in data: re_map_foreign_keys(data, 'zerver_usergroup', 'realm', related_table='realm') re_map_foreign_keys_many_to_many(data, 'zerver_usergroup', 'members', related_table='user_profile') update_model_ids(UserGroup, data, 'usergroup') bulk_import_model(data, UserGroup) re_map_foreign_keys(data, 'zerver_usergroupmembership', 'user_group', related_table='usergroup') re_map_foreign_keys(data, 'zerver_usergroupmembership', 'user_profile', related_table='user_profile') update_model_ids(UserGroupMembership, data, 'usergroupmembership') bulk_import_model(data, UserGroupMembership) if 'zerver_botstoragedata' in data: re_map_foreign_keys(data, 'zerver_botstoragedata', 'bot_profile', related_table='user_profile') update_model_ids(BotStorageData, data, 'botstoragedata') bulk_import_model(data, BotStorageData) if 'zerver_botconfigdata' in data: re_map_foreign_keys(data, 'zerver_botconfigdata', 'bot_profile', related_table='user_profile') update_model_ids(BotConfigData, data, 'botconfigdata') bulk_import_model(data, BotConfigData) fix_datetime_fields(data, 'zerver_userpresence') re_map_foreign_keys(data, 'zerver_userpresence', 'user_profile', related_table="user_profile") re_map_foreign_keys(data, 'zerver_userpresence', 'client', related_table='client') update_model_ids(UserPresence, data, 'user_presence') bulk_import_model(data, UserPresence) fix_datetime_fields(data, 'zerver_useractivity') re_map_foreign_keys(data, 'zerver_useractivity', 'user_profile', related_table="user_profile") re_map_foreign_keys(data, 'zerver_useractivity', 'client', related_table='client') update_model_ids(UserActivity, data, 'useractivity') bulk_import_model(data, UserActivity) fix_datetime_fields(data, 'zerver_useractivityinterval') re_map_foreign_keys(data, 'zerver_useractivityinterval', 'user_profile', related_table="user_profile") update_model_ids(UserActivityInterval, data, 'useractivityinterval') bulk_import_model(data, UserActivityInterval) re_map_foreign_keys(data, 'zerver_customprofilefield', 'realm', related_table="realm") update_model_ids(CustomProfileField, data, related_table="customprofilefield") bulk_import_model(data, CustomProfileField) re_map_foreign_keys(data, 'zerver_customprofilefieldvalue', 'user_profile', related_table="user_profile") re_map_foreign_keys(data, 'zerver_customprofilefieldvalue', 'field', related_table="customprofilefield") fix_customprofilefield(data) update_model_ids(CustomProfileFieldValue, data, related_table="customprofilefieldvalue") bulk_import_model(data, CustomProfileFieldValue) # Import uploaded files and avatars import_uploads(os.path.join(import_dir, "avatars"), processing_avatars=True) import_uploads(os.path.join(import_dir, "uploads")) # We need to have this check as the emoji files are only present in the data # importer from slack # For Zulip export, this doesn't exist if os.path.exists(os.path.join(import_dir, "emoji")): import_uploads(os.path.join(import_dir, "emoji"), processing_emojis=True) # Import zerver_message and zerver_usermessage import_message_data(import_dir) re_map_foreign_keys(data, 'zerver_reaction', 'message', related_table="message") re_map_foreign_keys(data, 'zerver_reaction', 'user_profile', related_table="user_profile") re_map_foreign_keys(data, 'zerver_reaction', 'emoji_code', related_table="realmemoji", id_field=True, reaction_field=True) update_model_ids(Reaction, data, 'reaction') bulk_import_model(data, Reaction) # Do attachments AFTER message data is loaded. # TODO: de-dup how we read these json files. fn = os.path.join(import_dir, "attachment.json") if not os.path.exists(fn): raise Exception("Missing attachment.json file!") logging.info("Importing attachment data from %s" % (fn,)) with open(fn) as f: data = ujson.load(f) import_attachments(data) return realm
def do_create_realm( string_id: str, name: str, *, emails_restricted_to_domains: Optional[bool] = None, email_address_visibility: Optional[int] = None, description: Optional[str] = None, invite_required: Optional[bool] = None, plan_type: Optional[int] = None, org_type: Optional[int] = None, date_created: Optional[datetime.datetime] = None, is_demo_organization: bool = False, enable_spectator_access: Optional[bool] = None, ) -> Realm: if string_id == settings.SOCIAL_AUTH_SUBDOMAIN: raise AssertionError("Creating a realm on SOCIAL_AUTH_SUBDOMAIN is not allowed!") if Realm.objects.filter(string_id=string_id).exists(): raise AssertionError(f"Realm {string_id} already exists!") if not server_initialized(): logging.info("Server not yet initialized. Creating the internal realm first.") create_internal_realm() kwargs: Dict[str, Any] = {} if emails_restricted_to_domains is not None: kwargs["emails_restricted_to_domains"] = emails_restricted_to_domains if email_address_visibility is not None: kwargs["email_address_visibility"] = email_address_visibility if description is not None: kwargs["description"] = description if invite_required is not None: kwargs["invite_required"] = invite_required if plan_type is not None: kwargs["plan_type"] = plan_type if org_type is not None: kwargs["org_type"] = org_type if enable_spectator_access is not None: kwargs["enable_spectator_access"] = enable_spectator_access if date_created is not None: # The date_created parameter is intended only for use by test # suites that want to backdate the date of a realm's creation. assert not settings.PRODUCTION kwargs["date_created"] = date_created with transaction.atomic(): realm = Realm(string_id=string_id, name=name, **kwargs) if is_demo_organization: realm.demo_organization_scheduled_deletion_date = ( realm.date_created + datetime.timedelta(days=settings.DEMO_ORG_DEADLINE_DAYS) ) set_realm_permissions_based_on_org_type(realm) realm.save() RealmAuditLog.objects.create( # acting_user will be set as the initial realm owner inside # do_create_user(..., realm_creation=True). acting_user=None, realm=realm, event_type=RealmAuditLog.REALM_CREATED, event_time=realm.date_created, ) RealmUserDefault.objects.create(realm=realm) create_system_user_groups_for_realm(realm) # Create stream once Realm object has been saved notifications_stream = ensure_stream( realm, Realm.DEFAULT_NOTIFICATION_STREAM_NAME, stream_description="Everyone is added to this stream by default. Welcome! :octopus:", acting_user=None, ) realm.notifications_stream = notifications_stream # With the current initial streams situation, the only public # stream is the notifications_stream. DefaultStream.objects.create(stream=notifications_stream, realm=realm) signup_notifications_stream = ensure_stream( realm, Realm.INITIAL_PRIVATE_STREAM_NAME, invite_only=True, stream_description="A private stream for core team members.", acting_user=None, ) realm.signup_notifications_stream = signup_notifications_stream realm.save(update_fields=["notifications_stream", "signup_notifications_stream"]) if plan_type is None and settings.BILLING_ENABLED: # We use acting_user=None for setting the initial plan type. do_change_realm_plan_type(realm, Realm.PLAN_TYPE_LIMITED, acting_user=None) admin_realm = get_realm(settings.SYSTEM_BOT_REALM) sender = get_system_bot(settings.NOTIFICATION_BOT, admin_realm.id) # Send a notification to the admin realm signup_message = _("Signups enabled") try: signups_stream = get_signups_stream(admin_realm) topic = realm.display_subdomain internal_send_stream_message( sender, signups_stream, topic, signup_message, ) except Stream.DoesNotExist: # nocoverage # If the signups stream hasn't been created in the admin # realm, don't auto-create it to send to it; just do nothing. pass setup_realm_internal_bots(realm) return realm