mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	We shouldn't export the entire Client table - it includes Clients for all the realms on the server, completely unrelated to the realm we're exporting. Since these contain parts of the UserAgents used by the users, we should treat these as private data and only export the Clients that the specific data we're exporting "knows" about.
		
			
				
	
	
		
			71 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			71 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import re
 | 
						|
import secrets
 | 
						|
from collections.abc import Callable
 | 
						|
from typing import TypeVar
 | 
						|
 | 
						|
from django.db import models
 | 
						|
 | 
						|
T = TypeVar("T")
 | 
						|
 | 
						|
 | 
						|
def generate_api_key() -> str:
 | 
						|
    api_key = ""
 | 
						|
    while len(api_key) < 32:
 | 
						|
        # One iteration suffices 99.4992% of the time.
 | 
						|
        api_key += secrets.token_urlsafe(3 * 9).replace("_", "").replace("-", "")
 | 
						|
    return api_key[:32]
 | 
						|
 | 
						|
 | 
						|
def has_api_key_format(key: str) -> bool:
 | 
						|
    return bool(re.fullmatch(r"([A-Za-z0-9]){32}", key))
 | 
						|
 | 
						|
 | 
						|
def assert_is_not_none(value: T | None) -> T:
 | 
						|
    assert value is not None
 | 
						|
    return value
 | 
						|
 | 
						|
 | 
						|
def process_list_in_batches(
 | 
						|
    lst: list[T], chunk_size: int, process_batch: Callable[[list[T]], None]
 | 
						|
) -> None:
 | 
						|
    offset = 0
 | 
						|
 | 
						|
    while True:
 | 
						|
        items = lst[offset : offset + chunk_size]
 | 
						|
        if not items:
 | 
						|
            break
 | 
						|
        process_batch(items)
 | 
						|
        offset += chunk_size
 | 
						|
 | 
						|
 | 
						|
def optional_bytes_to_mib(value: int | None) -> int | None:
 | 
						|
    if value is None:
 | 
						|
        return None
 | 
						|
    else:
 | 
						|
        return value >> 20
 | 
						|
 | 
						|
 | 
						|
def get_fk_field_name(model: type[models.Model], related_model: type[models.Model]) -> str | None:
 | 
						|
    """
 | 
						|
    Get the name of the foreign key field in model, pointing the related_model table.
 | 
						|
    Returns None if there is no such field.
 | 
						|
 | 
						|
    Example usage:
 | 
						|
 | 
						|
    get_fk_field_name(UserProfile, Realm) returns "realm"
 | 
						|
    """
 | 
						|
 | 
						|
    fields = model._meta.get_fields()
 | 
						|
    foreign_key_fields_to_related_model = [
 | 
						|
        field
 | 
						|
        for field in fields
 | 
						|
        if hasattr(field, "related_model") and field.related_model == related_model
 | 
						|
    ]
 | 
						|
 | 
						|
    if len(foreign_key_fields_to_related_model) == 0:
 | 
						|
        return None
 | 
						|
 | 
						|
    assert len(foreign_key_fields_to_related_model) == 1
 | 
						|
 | 
						|
    return foreign_key_fields_to_related_model[0].name
 |