diff --git a/zerver/lib/actions.py b/zerver/lib/actions.py index 91f08e6caf..22e8277ded 100644 --- a/zerver/lib/actions.py +++ b/zerver/lib/actions.py @@ -106,9 +106,9 @@ from confirmation.models import Confirmation, create_confirmation_link from confirmation import settings as confirmation_settings from zerver.lib.bulk_create import bulk_create_users -from zerver.lib.create_user import random_api_key from zerver.lib.timestamp import timestamp_to_datetime, datetime_to_timestamp from zerver.lib.queue import queue_json_publish +from zerver.lib.utils import generate_api_key from zerver.lib.create_user import create_user from zerver.lib import bugdown from zerver.lib.cache import cache_with_key, cache_set, \ @@ -2932,7 +2932,7 @@ def do_change_tos_version(user_profile: UserProfile, tos_version: str) -> None: event_time=event_time) def do_regenerate_api_key(user_profile: UserProfile, acting_user: UserProfile) -> None: - user_profile.api_key = random_api_key() + user_profile.api_key = generate_api_key() user_profile.save(update_fields=["api_key"]) event_time = timezone_now() RealmAuditLog.objects.create(realm=user_profile.realm, acting_user=acting_user, diff --git a/zerver/lib/create_user.py b/zerver/lib/create_user.py index 5678cf9ea5..7a0468a915 100644 --- a/zerver/lib/create_user.py +++ b/zerver/lib/create_user.py @@ -4,6 +4,7 @@ from django.utils.timezone import now as timezone_now from zerver.models import UserProfile, Recipient, Subscription, Realm, Stream from zerver.lib.upload import copy_avatar from zerver.lib.hotspots import copy_hotpots +from zerver.lib.utils import generate_api_key import base64 import ujson @@ -12,11 +13,6 @@ import string from typing import Optional -def random_api_key() -> str: - choices = string.ascii_letters + string.digits - altchars = ''.join([choices[ord(os.urandom(1)) % 62] for _ in range(2)]).encode("utf-8") - return base64.b64encode(os.urandom(24), altchars=altchars).decode("utf-8") - def copy_user_settings(source_profile: UserProfile, target_profile: UserProfile) -> None: """Warning: Does not save, to avoid extra database queries""" for settings_name in UserProfile.property_types: @@ -73,7 +69,7 @@ def create_user_profile(realm: Realm, email: str, password: Optional[str], user_profile.set_password(password) - user_profile.api_key = random_api_key() + user_profile.api_key = generate_api_key() return user_profile def create_user(email: str, password: Optional[str], realm: Realm, diff --git a/zerver/lib/import_realm.py b/zerver/lib/import_realm.py index a89ffa14c6..cbfa3e0489 100644 --- a/zerver/lib/import_realm.py +++ b/zerver/lib/import_realm.py @@ -15,12 +15,11 @@ from typing import Any, Dict, List, Optional, Set, Tuple, \ from zerver.lib.avatar_hash import user_avatar_path_from_ids from zerver.lib.bulk_create import bulk_create_users -from zerver.lib.create_user import random_api_key from zerver.lib.export import DATE_FIELDS, realm_tables, \ Record, TableData, TableName, Field, Path from zerver.lib.upload import random_name, sanitize_name, \ S3UploadBackend, LocalUploadBackend -from zerver.lib.create_user import random_api_key +from zerver.lib.utils import generate_api_key from zerver.models import UserProfile, Realm, Client, Huddle, Stream, \ UserMessage, Subscription, Message, RealmEmoji, \ RealmDomain, Recipient, get_user_profile_by_id, \ @@ -149,11 +148,11 @@ def create_subscription_events(data: TableData, table: TableName) -> None: def fix_service_tokens(data: TableData, table: TableName) -> None: """ - The tokens in the services are created by 'random_api_key'. + The tokens in the services are created by 'generate_api_key'. As the tokens are unique, they should be re-created for the imports. """ for item in data[table]: - item['token'] = random_api_key() + item['token'] = generate_api_key() def process_huddle_hash(data: TableData, table: TableName) -> None: """ @@ -646,7 +645,7 @@ def do_import_realm(import_dir: Path, subdomain: str) -> Realm: 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() + 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'] diff --git a/zerver/lib/utils.py b/zerver/lib/utils.py index 1eec5943a7..8860784a0e 100644 --- a/zerver/lib/utils.py +++ b/zerver/lib/utils.py @@ -7,6 +7,7 @@ import hashlib import heapq import itertools import os +import string import sys from time import sleep from itertools import zip_longest @@ -112,6 +113,12 @@ def log_statsd_event(name: str) -> None: def generate_random_token(length: int) -> str: return str(base64.b16encode(os.urandom(length // 2)).decode('utf-8').lower()) +def generate_api_key() -> str: + choices = string.ascii_letters + string.digits + altchars = ''.join([choices[ord(os.urandom(1)) % 62] for _ in range(2)]).encode("utf-8") + api_key = base64.b64encode(os.urandom(24), altchars=altchars).decode("utf-8") + return api_key + def query_chunker(queries: List[Any], id_collector: Optional[Set[int]]=None, chunk_size: int=1000, diff --git a/zerver/views/users.py b/zerver/views/users.py index ddbecb83e4..79df5d818f 100644 --- a/zerver/views/users.py +++ b/zerver/views/users.py @@ -32,12 +32,11 @@ from zerver.lib.validator import check_bool, check_string, check_int, check_url, from zerver.lib.users import check_valid_bot_type, check_bot_creation_policy, \ check_full_name, check_short_name, check_valid_interface_type, check_valid_bot_config, \ access_bot_by_id, add_service, access_user_by_id -from zerver.lib.utils import generate_random_token +from zerver.lib.utils import generate_api_key, generate_random_token from zerver.models import UserProfile, Stream, Message, email_allowed_for_realm, \ get_user_profile_by_id, get_user, Service, get_user_including_cross_realm, \ DomainNotAllowedForRealmError, DisposableEmailError, get_user_profile_by_id_in_realm, \ EmailContainsPlusError -from zerver.lib.create_user import random_api_key def deactivate_user_backend(request: HttpRequest, user_profile: UserProfile, user_id: int) -> HttpResponse: @@ -310,7 +309,7 @@ def add_bot_backend( user_profile=bot_profile, base_url=payload_url, interface=interface_type, - token=random_api_key()) + token=generate_api_key()) if bot_type == UserProfile.EMBEDDED_BOT: for key, value in config_data.items(): diff --git a/zilencer/management/commands/populate_db.py b/zilencer/management/commands/populate_db.py index eb9e7444d1..6231367936 100644 --- a/zilencer/management/commands/populate_db.py +++ b/zilencer/management/commands/populate_db.py @@ -16,7 +16,6 @@ from zerver.lib.actions import STREAM_ASSIGNMENT_COLORS, check_add_realm_emoji, do_change_is_admin, do_send_messages, do_update_user_custom_profile_data, \ try_add_realm_custom_profile_field from zerver.lib.bulk_create import bulk_create_streams, bulk_create_users -from zerver.lib.create_user import random_api_key from zerver.lib.cache import cache_set from zerver.lib.generate_test_data import create_test_data from zerver.lib.onboarding import create_if_missing_realm_internal_bots @@ -24,6 +23,7 @@ from zerver.lib.upload import upload_backend from zerver.lib.users import add_service from zerver.lib.url_preview.preview import CACHE_NAME as PREVIEW_CACHE_NAME from zerver.lib.user_groups import create_user_group +from zerver.lib.utils import generate_api_key from zerver.models import CustomProfileField, DefaultStream, Message, Realm, RealmAuditLog, \ RealmDomain, RealmEmoji, Recipient, Service, Stream, Subscription, \ UserMessage, UserPresence, UserProfile, clear_database, \ @@ -219,7 +219,7 @@ class Command(BaseCommand): bot_type=UserProfile.OUTGOING_WEBHOOK_BOT, bot_owner=aaron) outgoing_webhook = get_user("outgoing-webhook@zulip.com", zulip_realm) add_service("outgoing-webhook", user_profile=outgoing_webhook, interface=Service.GENERIC, - base_url="http://127.0.0.1:5002", token=random_api_key()) + base_url="http://127.0.0.1:5002", token=generate_api_key()) # Add the realm internl bots to each realm. create_if_missing_realm_internal_bots()