utils: Move random API key generator as generate_api_key.

random_api_key, the function we use to generate random tokens for API
keys, has been moved to zerver/lib/utils.py because it's used in more
parts of the codebase (apart from user creation), and having it in
zerver/lib/create_user.py was prone to cyclic dependencies.

The function has also been renamed to generate_api_key to have an
imperative name, that makes clearer what it does.
This commit is contained in:
Yago González
2018-08-01 11:18:37 +02:00
committed by Tim Abbott
parent f6219745de
commit 6a192ac84c
6 changed files with 19 additions and 18 deletions

View File

@@ -106,9 +106,9 @@ from confirmation.models import Confirmation, create_confirmation_link
from confirmation import settings as confirmation_settings from confirmation import settings as confirmation_settings
from zerver.lib.bulk_create import bulk_create_users 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.timestamp import timestamp_to_datetime, datetime_to_timestamp
from zerver.lib.queue import queue_json_publish 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.create_user import create_user
from zerver.lib import bugdown from zerver.lib import bugdown
from zerver.lib.cache import cache_with_key, cache_set, \ 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) event_time=event_time)
def do_regenerate_api_key(user_profile: UserProfile, acting_user: UserProfile) -> None: 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"]) user_profile.save(update_fields=["api_key"])
event_time = timezone_now() event_time = timezone_now()
RealmAuditLog.objects.create(realm=user_profile.realm, acting_user=acting_user, RealmAuditLog.objects.create(realm=user_profile.realm, acting_user=acting_user,

View File

@@ -4,6 +4,7 @@ from django.utils.timezone import now as timezone_now
from zerver.models import UserProfile, Recipient, Subscription, Realm, Stream from zerver.models import UserProfile, Recipient, Subscription, Realm, Stream
from zerver.lib.upload import copy_avatar from zerver.lib.upload import copy_avatar
from zerver.lib.hotspots import copy_hotpots from zerver.lib.hotspots import copy_hotpots
from zerver.lib.utils import generate_api_key
import base64 import base64
import ujson import ujson
@@ -12,11 +13,6 @@ import string
from typing import Optional 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: def copy_user_settings(source_profile: UserProfile, target_profile: UserProfile) -> None:
"""Warning: Does not save, to avoid extra database queries""" """Warning: Does not save, to avoid extra database queries"""
for settings_name in UserProfile.property_types: 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.set_password(password)
user_profile.api_key = random_api_key() user_profile.api_key = generate_api_key()
return user_profile return user_profile
def create_user(email: str, password: Optional[str], realm: Realm, def create_user(email: str, password: Optional[str], realm: Realm,

View File

@@ -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.avatar_hash import user_avatar_path_from_ids
from zerver.lib.bulk_create import bulk_create_users 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, \ from zerver.lib.export import DATE_FIELDS, realm_tables, \
Record, TableData, TableName, Field, Path Record, TableData, TableName, Field, Path
from zerver.lib.upload import random_name, sanitize_name, \ from zerver.lib.upload import random_name, sanitize_name, \
S3UploadBackend, LocalUploadBackend 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, \ from zerver.models import UserProfile, Realm, Client, Huddle, Stream, \
UserMessage, Subscription, Message, RealmEmoji, \ UserMessage, Subscription, Message, RealmEmoji, \
RealmDomain, Recipient, get_user_profile_by_id, \ 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: 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. As the tokens are unique, they should be re-created for the imports.
""" """
for item in data[table]: for item in data[table]:
item['token'] = random_api_key() item['token'] = generate_api_key()
def process_huddle_hash(data: TableData, table: TableName) -> None: 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) related_table="message", id_field=True)
for user_profile_dict in data['zerver_userprofile']: for user_profile_dict in data['zerver_userprofile']:
user_profile_dict['password'] = None 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 # Since Zulip doesn't use these permissions, drop them
del user_profile_dict['user_permissions'] del user_profile_dict['user_permissions']
del user_profile_dict['groups'] del user_profile_dict['groups']

View File

@@ -7,6 +7,7 @@ import hashlib
import heapq import heapq
import itertools import itertools
import os import os
import string
import sys import sys
from time import sleep from time import sleep
from itertools import zip_longest from itertools import zip_longest
@@ -112,6 +113,12 @@ def log_statsd_event(name: str) -> None:
def generate_random_token(length: int) -> str: def generate_random_token(length: int) -> str:
return str(base64.b16encode(os.urandom(length // 2)).decode('utf-8').lower()) 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], def query_chunker(queries: List[Any],
id_collector: Optional[Set[int]]=None, id_collector: Optional[Set[int]]=None,
chunk_size: int=1000, chunk_size: int=1000,

View File

@@ -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, \ 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, \ check_full_name, check_short_name, check_valid_interface_type, check_valid_bot_config, \
access_bot_by_id, add_service, access_user_by_id 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, \ from zerver.models import UserProfile, Stream, Message, email_allowed_for_realm, \
get_user_profile_by_id, get_user, Service, get_user_including_cross_realm, \ get_user_profile_by_id, get_user, Service, get_user_including_cross_realm, \
DomainNotAllowedForRealmError, DisposableEmailError, get_user_profile_by_id_in_realm, \ DomainNotAllowedForRealmError, DisposableEmailError, get_user_profile_by_id_in_realm, \
EmailContainsPlusError EmailContainsPlusError
from zerver.lib.create_user import random_api_key
def deactivate_user_backend(request: HttpRequest, user_profile: UserProfile, def deactivate_user_backend(request: HttpRequest, user_profile: UserProfile,
user_id: int) -> HttpResponse: user_id: int) -> HttpResponse:
@@ -310,7 +309,7 @@ def add_bot_backend(
user_profile=bot_profile, user_profile=bot_profile,
base_url=payload_url, base_url=payload_url,
interface=interface_type, interface=interface_type,
token=random_api_key()) token=generate_api_key())
if bot_type == UserProfile.EMBEDDED_BOT: if bot_type == UserProfile.EMBEDDED_BOT:
for key, value in config_data.items(): for key, value in config_data.items():

View File

@@ -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, \ do_change_is_admin, do_send_messages, do_update_user_custom_profile_data, \
try_add_realm_custom_profile_field try_add_realm_custom_profile_field
from zerver.lib.bulk_create import bulk_create_streams, bulk_create_users 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.cache import cache_set
from zerver.lib.generate_test_data import create_test_data from zerver.lib.generate_test_data import create_test_data
from zerver.lib.onboarding import create_if_missing_realm_internal_bots 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.users import add_service
from zerver.lib.url_preview.preview import CACHE_NAME as PREVIEW_CACHE_NAME 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.user_groups import create_user_group
from zerver.lib.utils import generate_api_key
from zerver.models import CustomProfileField, DefaultStream, Message, Realm, RealmAuditLog, \ from zerver.models import CustomProfileField, DefaultStream, Message, Realm, RealmAuditLog, \
RealmDomain, RealmEmoji, Recipient, Service, Stream, Subscription, \ RealmDomain, RealmEmoji, Recipient, Service, Stream, Subscription, \
UserMessage, UserPresence, UserProfile, clear_database, \ UserMessage, UserPresence, UserProfile, clear_database, \
@@ -219,7 +219,7 @@ class Command(BaseCommand):
bot_type=UserProfile.OUTGOING_WEBHOOK_BOT, bot_owner=aaron) bot_type=UserProfile.OUTGOING_WEBHOOK_BOT, bot_owner=aaron)
outgoing_webhook = get_user("outgoing-webhook@zulip.com", zulip_realm) outgoing_webhook = get_user("outgoing-webhook@zulip.com", zulip_realm)
add_service("outgoing-webhook", user_profile=outgoing_webhook, interface=Service.GENERIC, 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. # Add the realm internl bots to each realm.
create_if_missing_realm_internal_bots() create_if_missing_realm_internal_bots()